geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

routines.c
Go to the documentation of this file.
1/*
2* Copyright (c) 2002-2003, Darren Hiebert
3*
4* This source code is released for free distribution under the terms of the
5* GNU General Public License version 2 or (at your option) any later version.
6*
7* This module contains a lose assortment of shared functions.
8*/
9
10/*
11* INCLUDE FILES
12*/
13#include "general.h" /* must always come first */
14
15#include <stdlib.h> /* to declare malloc (), realloc (), mbcs() */
16#include <ctype.h>
17#include <string.h>
18#include <stdio.h> /* to declare tempnam(), and SEEK_SET (hopefully) */
19
20#ifdef HAVE_FCNTL_H
21# include <fcntl.h> /* to declare O_RDWR, O_CREAT, O_EXCL */
22#endif
23#ifdef HAVE_UNISTD_H
24# include <unistd.h> /* to declare mkstemp () */
25#endif
26
27#include <limits.h> /* to declare MB_LEN_MAX */
28#ifndef MB_LEN_MAX
29# define MB_LEN_MAX 6
30#endif
31
32/* To declare "struct stat" and stat ().
33 */
34#if defined (HAVE_SYS_TYPES_H)
35# include <sys/types.h>
36#else
37# if defined (HAVE_TYPES_H)
38# include <types.h>
39# endif
40#endif
41#ifdef HAVE_SYS_STAT_H
42# include <sys/stat.h>
43#else
44# ifdef HAVE_STAT_H
45# include <stat.h>
46# endif
47#endif
48
49#ifdef HAVE_DIRECT_H
50# include <direct.h> /* to _getcwd */
51#endif
52#ifdef HAVE_IO_H
53# include <io.h> /* to declare open() */
54#endif
55#include "debug.h"
56#include "routines.h"
57#include "routines_p.h"
58#include <errno.h>
59
60#include "vstring.h"
61
62/*
63* MACROS
64*/
65#ifndef TMPDIR
66# define TMPDIR "/tmp"
67#endif
68
69/* File type tests.
70 */
71#ifndef S_ISREG
72# if defined (S_IFREG)
73# define S_ISREG(mode) ((mode) & S_IFREG)
74# endif
75#endif
76
77#ifndef S_ISLNK
78# ifdef S_IFLNK
79# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
80# else
81# define S_ISLNK(mode) false /* assume no soft links */
82# endif
83#endif
84
85#ifndef S_ISDIR
86# ifdef S_IFDIR
87# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
88# else
89# define S_ISDIR(mode) false /* assume no soft links */
90# endif
91#endif
92
93#ifndef S_IFMT
94# define S_IFMT 0
95#endif
96
97#ifndef S_IXUSR
98# define S_IXUSR 0
99#endif
100#ifndef S_IXGRP
101# define S_IXGRP 0
102#endif
103#ifndef S_IXOTH
104# define S_IXOTH 0
105#endif
106
107#ifndef S_IRUSR
108# define S_IRUSR 0400
109#endif
110#ifndef S_IWUSR
111# define S_IWUSR 0200
112#endif
113
114#ifndef S_ISUID
115# define S_ISUID 0
116#endif
117
118#ifndef S_ISGID
119# define S_ISGID 0
120#endif
121
122/* Hack for ridiculous practice of Microsoft Visual C++.
123 */
124#if defined (WIN32)
125# if defined (_MSC_VER) || defined (__MINGW32__)
126# ifndef stat
127# define stat _stat
128# endif
129# define getcwd _getcwd
130# define currentdrive() (_getdrive() + 'A' - 1)
131# else
132# define currentdrive() 'C'
133# endif
134#endif
135
136#ifndef PATH_MAX
137# define PATH_MAX 256
138#endif
139
140/*
141 * Miscellaneous macros
142 */
143
144
145/*
146* DATA DEFINITIONS
147*/
148#if defined (MSDOS_STYLE_PATH)
149const char *const PathDelimiters = ":/\\";
150#endif
151
153
154static const char *ExecutableProgram;
155static const char *ExecutableName;
156
157/*
158* FUNCTION PROTOTYPES
159*/
160#ifdef NEED_PROTO_STAT
161extern int stat (const char *, struct stat *);
162#endif
163#ifdef NEED_PROTO_LSTAT
164extern int lstat (const char *, struct stat *);
165#endif
166#if defined (WIN32)
167# define lstat(fn,buf) stat(fn,buf)
168#endif
169
170static bool isPathSeparator (const int c);
171static char *strSeparator (const char *s);
172static char *strRSeparator (const char *s);
173static void canonicalizePath (char *const path);
174
175
176/*
177* FUNCTION DEFINITIONS
178*/
179
180extern void freeRoutineResources (void)
181{
182 if (CurrentDirectory != NULL)
184}
185
186extern void setExecutableName (const char *const path)
187{
188 ExecutableProgram = path;
190}
191
192extern const char *getExecutableName (void)
193{
194 return ExecutableName;
195}
196
197extern const char *getExecutablePath (void)
198{
199 return ExecutableProgram;
200}
201
202/*
203 * compare file/dirname characters with platform-correct case sensitivity
204 */
205static bool fnmChEq (int c1, int c2)
206{
207#ifdef WIN32
208 return tolower( c1 ) == tolower( c2 ); /* case-insensitive */
209#else
210 return c1 == c2 ; /* case- sensitive */
211#endif
212}
213
214/*
215 * Memory allocation functions
216 */
217
218extern void *eMalloc (const size_t size)
219{
220 void *buffer = malloc (size);
221
222 if (buffer == NULL && size != 0)
223 error (FATAL, "out of memory");
224
225 return buffer;
226}
227
228extern void *eCalloc (const size_t count, const size_t size)
229{
230 void *buffer = calloc (count, size);
231
232 if (buffer == NULL && count != 0 && size != 0)
233 error (FATAL, "out of memory");
234
235 return buffer;
236}
237
238extern void *eRealloc (void *const ptr, const size_t size)
239{
240 void *buffer;
241 if (ptr == NULL)
242 buffer = eMalloc (size);
243 else
244 {
245 buffer = realloc (ptr, size);
246 if (buffer == NULL && size != 0)
247 error (FATAL, "out of memory");
248 }
249 return buffer;
250}
251
252extern void eFree (void *const ptr)
253{
254 Assert (ptr != NULL);
255 free (ptr);
256}
257
258extern void eFreeNoNullCheck (void *const ptr)
259{
260 free (ptr);
261}
262
263extern void eFreeIndirect(void **ptr)
264{
265 if (ptr && *ptr)
266 {
267 eFree (*ptr);
268 *ptr = NULL;
269 }
270}
271
272/*
273 * String manipulation functions
274 */
275
276/*
277 * Compare two strings, ignoring case.
278 * Return 0 for match, < 0 for smaller, > 0 for bigger
279 * Make sure case is folded to uppercase in comparison (like for 'sort -f')
280 * This makes a difference when one of the chars lies between upper and lower
281 * ie. one of the chars [ \ ] ^ _ ` for ascii. (The '_' in particular !)
282 */
283extern int struppercmp (const char *s1, const char *s2)
284{
285 int result;
286 do
287 {
288 result = toupper ((int) *s1) - toupper ((int) *s2);
289 } while (result == 0 && *s1++ != '\0' && *s2++ != '\0');
290 return result;
291}
292
293extern int strnuppercmp (const char *s1, const char *s2, size_t n)
294{
295 int result;
296 do
297 {
298 result = toupper ((int) *s1) - toupper ((int) *s2);
299 } while (result == 0 && --n > 0 && *s1++ != '\0' && *s2++ != '\0');
300 return result;
301}
302
303#ifndef HAVE_STRSTR
304extern char* strstr (const char *str, const char *substr)
305{
306 const size_t length = strlen (substr);
307 const char *p;
308
309 for (p = str ; *p != '\0' ; ++p)
310 if (strncmp (p, substr, length) == 0)
311 return (char*) p;
312 return NULL;
313}
314#endif
315
316extern char* strrstr (const char *str, const char *substr)
317{
318 const size_t length = strlen (substr);
319 const char *p;
320
321 for (p = str + strlen(str) - length ; p >= str ; --p)
322 if (strncmp (p, substr, length) == 0)
323 return (char*) p;
324 return NULL;
325}
326
327extern char* eStrdup (const char* str)
328{
329 char* result = xMalloc (strlen (str) + 1, char);
330 strcpy (result, str);
331 return result;
332}
333
334extern char* eStrndup (const char* str, size_t len)
335{
336 char* result = xMalloc (len + 1, char);
337 strncpy (result, str, len);
338 result [len] = '\0';
339 return result;
340}
341
342extern void toLowerString (char* str)
343{
344 while (*str != '\0')
345 {
346 *str = tolower ((int) *str);
347 ++str;
348 }
349}
350
351extern void toUpperString (char* str)
352{
353 while (*str != '\0')
354 {
355 *str = toupper ((int) *str);
356 ++str;
357 }
358}
359
360/* Newly allocated string containing lower case conversion of a string.
361 */
362extern char* newLowerString (const char* str)
363{
364 char* const result = xMalloc (strlen (str) + 1, char);
365 int i = 0;
366 do
367 result [i] = tolower ((int) str [i]);
368 while (str [i++] != '\0');
369 return result;
370}
371
372/* Newly allocated string containing upper case conversion of a string.
373 */
374extern char* newUpperString (const char* str)
375{
376 char* const result = xMalloc (strlen (str) + 1, char);
377 int i = 0;
378 do
379 result [i] = toupper ((int) str [i]);
380 while (str [i++] != '\0');
381 return result;
382}
383
384/* Safe wrapper for strtoul
385 *
386 * The conversion result is placed in value and must only be used if the
387 * function returned true.
388 */
389extern bool strToULong(const char *const str, int base, unsigned long *value)
390{
391 char *endptr;
392
393 errno = 0;
394 *value = strtoul (str, &endptr, base);
395 return *endptr == '\0' && str != endptr && errno == 0;
396}
397
398/* Safe wrapper for strtol/atol
399 *
400 * The conversion result is placed in value and must only be used if the
401 * function returned true.
402 */
403extern bool strToLong(const char *const str, int base, long *value)
404{
405 char *endptr;
406
407 errno = 0;
408 *value = strtol (str, &endptr, base);
409 return *endptr == '\0' && str != endptr && errno == 0;
410}
411
412extern bool strToUInt(const char *const str, int base, unsigned int *value)
413{
414 unsigned long ulong_value;
415
416 if(!strToULong(str, base, &ulong_value) || ulong_value > UINT_MAX)
417 return false;
418
419 *value = (unsigned int) ulong_value;
420 return true;
421}
422
423extern bool strToInt(const char *const str, int base, int *value)
424{
425 long long_value;
426
427 if(!strToLong(str, base, &long_value) || long_value > INT_MAX || long_value < INT_MIN)
428 return false;
429
430 *value = (int) long_value;
431 return true;
432}
433
434/*
435 * File system functions
436 */
437
438extern void setCurrentDirectory (void) /* TODO */
439{
440 char* buf;
441 if (CurrentDirectory == NULL)
442 CurrentDirectory = xMalloc ((size_t) (PATH_MAX + 1), char);
443 buf = getcwd (CurrentDirectory, PATH_MAX);
444 if (buf == NULL)
445 perror ("");
446 if (! isPathSeparator (CurrentDirectory [strlen (CurrentDirectory) - (size_t) 1]))
447 {
448 sprintf (CurrentDirectory + strlen (CurrentDirectory), "%c",
450 }
452}
453
454/* For caching of stat() calls */
455extern fileStatus *eStat (const char *const fileName)
456{
457 struct stat status;
458 static fileStatus file;
459 if (file.name == NULL || strcmp (fileName, file.name) != 0)
460 {
461 eStatFree (&file);
462 file.name = eStrdup (fileName);
463 if (lstat (file.name, &status) != 0)
464 file.exists = false;
465 else
466 {
467 file.isSymbolicLink = (bool) S_ISLNK (status.st_mode);
468 if (file.isSymbolicLink && stat (file.name, &status) != 0)
469 file.exists = false;
470 else
471 {
472 file.exists = true;
473 file.isDirectory = (bool) S_ISDIR (status.st_mode);
474 file.isNormalFile = (bool) (S_ISREG (status.st_mode));
475 file.isExecutable = (bool) ((status.st_mode &
476 (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
477 file.isSetuid = (bool) ((status.st_mode & S_ISUID) != 0);
478 file.isSetgid = (bool) ((status.st_mode & S_ISGID) != 0);
479 file.size = status.st_size;
480 }
481 }
482 }
483 return &file;
484}
485
486extern void eStatFree (fileStatus *status)
487{
488 if (status->name != NULL)
489 {
490 eFree (status->name);
491 status->name = NULL;
492 }
493}
494
495extern bool doesFileExist (const char *const fileName)
496{
497 fileStatus *status = eStat (fileName);
498 return status->exists;
499}
500
501extern bool doesExecutableExist (const char *const fileName)
502{
503 fileStatus *status = eStat (fileName);
504 return status->exists && status->isExecutable;
505}
506
507extern bool isRecursiveLink (const char* const dirName)
508{
509 bool result = false;
510 fileStatus *status = eStat (dirName);
511 if (status->isSymbolicLink)
512 {
513 char* const path = absoluteFilename (dirName);
514 while (isPathSeparator (path [strlen (path) - 1]))
515 path [strlen (path) - 1] = '\0';
516 while (! result && strlen (path) > (size_t) 1)
517 {
518 char *const separator = strRSeparator (path);
519 if (separator == NULL)
520 break;
521 else if (separator == path) /* backed up to root directory */
522 *(separator + 1) = '\0';
523 else
524 *separator = '\0';
525 result = isSameFile (path, dirName);
526 }
527 eFree (path);
528 }
529 return result;
530}
531
532/*
533 * Pathname manipulation (O/S dependent!!!)
534 */
535
536static bool isPathSeparator (const int c)
537{
538 bool result;
539#if defined (MSDOS_STYLE_PATH)
540 result = (bool) (strchr (PathDelimiters, c) != NULL);
541#else
542 result = (bool) (c == PATH_SEPARATOR);
543#endif
544 return result;
545}
546
547static char *strSeparator (const char *s)
548{
549#if defined (MSDOS_STYLE_PATH)
550 return strpbrk (s, PathDelimiters);
551#else
552 return strchr (s, PATH_SEPARATOR);
553#endif
554}
555
556static char *strRSeparator (const char *s)
557{
558#if defined (MSDOS_STYLE_PATH)
559 const char *last = NULL;
560
561 while (( s = strSeparator (s) ))
562 {
563 last = s;
564 s++;
565 }
566 return (char*) last;
567#else
568 return strrchr (s, PATH_SEPARATOR);
569#endif
570}
571
572static void canonicalizePath (char *const path CTAGS_ATTR_UNUSED)
573{
574# if defined (MSDOS_STYLE_PATH)
575 char *p;
576 for (p = path ; *p != '\0' ; ++p)
577 if (isPathSeparator (*p) && *p != ':')
579# endif
580}
581
582extern bool isSameFile (const char *const name1, const char *const name2)
583{
584 bool result = false;
585#if defined (HAVE_STAT_ST_INO)
586 struct stat stat1, stat2;
587
588 if (stat (name1, &stat1) == 0 && stat (name2, &stat2) == 0)
589 result = (bool) (stat1.st_ino == stat2.st_ino);
590#else
591 {
592 char *const n1 = absoluteFilename (name1);
593 char *const n2 = absoluteFilename (name2);
594 canonicalizePath (n1);
595 canonicalizePath (n2);
596# if defined (CASE_INSENSITIVE_FILENAMES)
597 result = (bool) (strcasecmp (n1, n2) == 0);
598# else
599 result = (bool) (strcmp (n1, n2) == 0);
600# endif
601 eFree (n1);
602 eFree (n2);
603 }
604#endif
605 return result;
606}
607
608extern const char *baseFilename (const char *const filePath)
609{
610#if defined (MSDOS_STYLE_PATH)
611 const char *tail = NULL;
612 unsigned int i;
613
614 /* Find whichever of the path delimiters is last.
615 */
616 for (i = 0 ; i < strlen (PathDelimiters) ; ++i)
617 {
618# ifdef HAVE_MBLEN
619 const char *p;
620 int ml;
621
622 /* Some DBCS has letter contains 0x5C in trailing byte.
623 * So skip to the trailing byte. */
624 for (p = filePath ; *p != '\0' ; ++p)
625 {
626 ml = mblen(p, MB_LEN_MAX);
627 if (ml > 1)
628 p += ml - 1;
629 else if (*p == PathDelimiters [i] && p > tail)
630 tail = p;
631 }
632# else
633 const char *sep = strrchr (filePath, PathDelimiters [i]);
634
635 if (sep > tail)
636 tail = sep;
637# endif
638 }
639#else
640 const char *tail = strRSeparator (filePath);
641#endif
642 if (tail == NULL)
643 tail = filePath;
644 else
645 ++tail; /* step past last delimiter */
646
647 return tail;
648}
649
650extern const char *fileExtension (const char *const fileName)
651{
652 const char *extension;
653 const char *pDelimiter;
654 const char *const base = baseFilename (fileName);
655
656 pDelimiter = strrchr (base, '.');
657
658 if (pDelimiter == NULL)
659 extension = "";
660 else
661 extension = pDelimiter + 1; /* skip to first char of extension */
662
663 return extension;
664}
665
666extern char* baseFilenameSansExtensionNew (const char *const fileName,
667 const char *const templateExt)
668{
669 const char *pDelimiter;
670 const char *const base = baseFilename (fileName);
671 char* shorten_base;
672
673 pDelimiter = strrchr (base, templateExt[0]);
674
675 if (pDelimiter && (strcmp (pDelimiter, templateExt) == 0))
676 {
677 shorten_base = eStrndup (base, pDelimiter - base);
678 return shorten_base;
679 }
680 else
681 return NULL;
682}
683
684extern bool isAbsolutePath (const char *const path)
685{
686 bool result;
687#if defined (MSDOS_STYLE_PATH)
688 if (isPathSeparator (path [0]))
689 result = true;
690 else if (isalpha (path [0]) && path [1] == ':')
691 {
692 if (isPathSeparator (path [2]))
693 result = true;
694 else
695 {
696 result = false;
697 /* We don't support non-absolute file names with a drive
698 * letter, like `d:NAME' (it's too much hassle).
699 */
700 error (FATAL,
701 "%s: relative file names with drive letters not supported",
702 path);
703 }
704 }
705 else
706 result = false;
707#else
708 result = isPathSeparator (path [0]);
709#endif
710 return result;
711}
712
713extern char *combinePathAndFile (
714 const char *const path, const char *const file)
715{
716 vString *const filePath = vStringNew ();
717 size_t len = strlen (path);
718
719 if (len)
720 {
721 const int lastChar = path [len - 1];
722 bool terminated = isPathSeparator (lastChar);
723 vStringCopyS (filePath, path);
724 if (! terminated)
726 }
727
728 vStringCatS (filePath, file);
729 return vStringDeleteUnwrap (filePath);
730}
731
732/* Return a newly-allocated string whose contents concatenate those of
733 * s1, s2, s3.
734 * Routine adapted from Gnu etags.
735 */
736static char* concat (const char *s1, const char *s2, const char *s3)
737{
738 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
739 char *result = xMalloc (len1 + len2 + len3 + 1, char);
740
741 strcpy (result, s1);
742 strcpy (result + len1, s2);
743 strcpy (result + len1 + len2, s3);
744 result [len1 + len2 + len3] = '\0';
745
746 return result;
747}
748
749/* Return a newly allocated string containing the absolute file name of FILE
750 * given CWD (which should end with a slash).
751 * Routine adapted from Gnu etags.
752 */
753extern char* absoluteFilename (const char *file)
754{
755 char *slashp, *cp;
756 char *res = NULL;
757 if (isAbsolutePath (file))
758 {
759#ifdef MSDOS_STYLE_PATH
760 if (file [1] == ':')
761 res = eStrdup (file);
762 else
763 {
764 char drive [3];
765 sprintf (drive, "%c:", currentdrive ());
766 res = concat (drive, file, "");
767 }
768#else
769 res = eStrdup (file);
770#endif
771 }
772 else
773 res = concat (CurrentDirectory, file, "");
774
775 /* Delete the "/dirname/.." and "/." substrings. */
776 slashp = strSeparator (res);
777 while (slashp != NULL && slashp [0] != '\0')
778 {
779 if (slashp[1] == '.')
780 {
781 if (slashp [2] == '.' &&
782 (isPathSeparator (slashp [3]) || slashp [3] == '\0'))
783 {
784 cp = slashp;
785 do
786 cp--;
787 while (cp >= res && ! isAbsolutePath (cp));
788 if (cp < res)
789 cp = slashp;/* the absolute name begins with "/.." */
790#ifdef MSDOS_STYLE_PATH
791 /* Under MSDOS and NT we get `d:/NAME' as absolute file name,
792 * so the user could say `d:/../NAME'. We silently treat this
793 * as `d:/NAME'.
794 */
795 else if (!isPathSeparator (cp [0]))
796 cp = slashp;
797#endif
798 memmove (cp, slashp + 3, strlen (slashp + 3) + 1);
799 slashp = cp;
800 continue;
801 }
802 else if (isPathSeparator (slashp [2]) || slashp [2] == '\0')
803 {
804 memmove (slashp, slashp + 2, strlen (slashp + 2) + 1);
805 continue;
806 }
807 }
808 slashp = strSeparator (slashp + 1);
809 }
810
811 if (res [0] == '\0')
812 {
813 const char root [] = {OUTPUT_PATH_SEPARATOR, '\0'};
814 eFree (res);
815 res = eStrdup (root);
816 }
817 else
818 {
819#ifdef MSDOS_STYLE_PATH
820 /* Canonicalize drive letter case. */
821 if (res [1] == ':' && islower (res [0]))
822 res [0] = toupper (res [0]);
823#endif
824 }
825 canonicalizePath (res);
826 return res;
827}
828
829/* Return a newly allocated string containing the absolute file name of dir
830 * where `file' resides given `CurrentDirectory'.
831 * Routine adapted from Gnu etags.
832 */
833extern char* absoluteDirname (char *file)
834{
835 char *slashp, *res;
836 char save;
837 slashp = strRSeparator (file);
838 if (slashp == NULL)
840 else
841 {
842 save = slashp [1];
843 slashp [1] = '\0';
844 res = absoluteFilename (file);
845 slashp [1] = save;
846 }
847 return res;
848}
849
850/* Return a newly allocated string containing the file name of FILE relative
851 * to the absolute directory DIR (which should end with a slash).
852 * Routine adapted from Gnu etags.
853 */
854extern char* relativeFilename (const char *file, const char *dir)
855{
856 const char *fp, *dp;
857 char *absdir, *res;
858 int i;
859
860 /* Find the common root of file and dir (with a trailing slash). */
861 absdir = absoluteFilename (file);
862 fp = absdir;
863 dp = dir;
864 while (fnmChEq (*fp++, *dp++))
865 continue;
866 fp--;
867 dp--; /* back to the first differing char */
868 do
869 { /* look at the equal chars until path sep */
870 if (fp == absdir)
871 return absdir; /* first char differs, give up */
872 fp--;
873 dp--;
874 } while (!isPathSeparator (*fp));
875
876 /* Build a sequence of "../" strings for the resulting relative file name.
877 */
878 i = 0;
879 while ((dp = strSeparator (dp + 1)) != NULL)
880 i += 1;
881 res = xMalloc (3 * i + strlen (fp + 1) + 1, char);
882 res [0] = '\0';
883 while (i-- > 0)
884 {
885 const char parent [] = {'.', '.', OUTPUT_PATH_SEPARATOR, '\0'};
886 strcat (res, parent);
887 }
888
889 /* Add the file name relative to the common root of file and dir. */
890 strcat (res, fp + 1);
891 eFree (absdir);
892
893 return res;
894}
895
896extern MIO *tempFile (const char *const mode, char **const pName)
897{
898 char *name;
899 FILE *fp;
900 MIO *mio;
901 int fd;
902#if defined(HAVE_MKSTEMP)
903 const char *const pattern = "tags.XXXXXX";
904 const char *tmpdir = NULL;
906# ifdef WIN32
907 tmpdir = getenv ("TMP");
908# else
909 if (! file->isSetuid)
910 tmpdir = getenv ("TMPDIR");
911# endif
912 if (tmpdir == NULL)
913 tmpdir = TMPDIR;
914 name = xMalloc (strlen (tmpdir) + 1 + strlen (pattern) + 1, char);
915 sprintf (name, "%s%c%s", tmpdir, OUTPUT_PATH_SEPARATOR, pattern);
916 fd = mkstemp (name);
917# ifdef WIN32
918 if (fd == -1)
919 {
920 /* mkstemp() sometimes fails with unknown reasons.
921 * Retry a few times. */
922 int i;
923 for (i = 0; i < 5 && fd == -1; i++)
924 {
925 sprintf (name, "%s%c%s", tmpdir, OUTPUT_PATH_SEPARATOR, pattern);
926 fd = mkstemp (name);
927 }
928 }
929# endif
930 eStatFree (file);
931#elif defined(HAVE_TEMPNAM)
932 const char *tmpdir = NULL;
933# ifdef WIN32
934 tmpdir = getenv ("TMP");
935# endif
936 if (tmpdir == NULL)
937 tmpdir = TMPDIR;
938 name = tempnam (tmpdir, "tags");
939 if (name == NULL)
940 error (FATAL | PERROR, "cannot allocate temporary file name");
941 fd = open (name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
942#else
943 name = xMalloc (L_tmpnam, char);
944 if (tmpnam (name) != name)
945 error (FATAL | PERROR, "cannot assign temporary file name");
946 fd = open (name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
947#endif
948 if (fd == -1)
949 error (FATAL | PERROR, "cannot open temporary file: %s", name);
950 fp = fdopen (fd, mode);
951 if (fp == NULL)
952 error (FATAL | PERROR, "cannot open temporary file");
953 mio = mio_new_fp (fp, fclose);
955 debugPrintf (DEBUG_STATUS, "opened temporary file %s\n", name); )
956 Assert (*pName == NULL);
957 *pName = name;
958 return mio;
959}
GeanyBuildCommand ** ptr
Definition: build.c:2679
#define Assert(c)
Definition: debug.h:47
#define DebugStatement(x)
Definition: debug.h:45
@ DEBUG_STATUS
Definition: debug.h:67
void debugPrintf(const enum eDebugLevels level, const char *const format,...)
const gchar * name
Definition: document.c:3219
int mkstemp(char *template_name)
void error(const errorSelection selection, const char *const format,...)
Definition: error.c:53
GtkWidget * open
Definition: filebrowser.c:96
int errno
#define CTAGS_ATTR_UNUSED
Definition: gcc-attr.h:22
unsigned int count
static bool tail(const char *cp)
Definition: geany_pascal.c:70
#define strcasecmp(s1, s2)
Definition: general.h:37
MIO * mio_new_fp(FILE *fp, MIOFCloseFunc close_func)
mio_new_fp: @fp: An opened #FILE object @close_func: (allow-none): Function used to close @fp when th...
Definition: mio.c:259
#define NULL
Definition: rbtree.h:150
#define S_IXGRP
Definition: routines.c:101
char * absoluteFilename(const char *file)
Definition: routines.c:753
char * combinePathAndFile(const char *const path, const char *const file)
Definition: routines.c:713
char * eStrndup(const char *str, size_t len)
Definition: routines.c:334
#define TMPDIR
Definition: routines.c:66
static bool isPathSeparator(const int c)
Definition: routines.c:536
bool doesFileExist(const char *const fileName)
Definition: routines.c:495
#define S_ISUID
Definition: routines.c:115
#define S_ISDIR(mode)
Definition: routines.c:89
bool strToUInt(const char *const str, int base, unsigned int *value)
Definition: routines.c:412
#define S_IXOTH
Definition: routines.c:104
bool strToInt(const char *const str, int base, int *value)
Definition: routines.c:423
int struppercmp(const char *s1, const char *s2)
Definition: routines.c:283
char * newLowerString(const char *str)
Definition: routines.c:362
int strnuppercmp(const char *s1, const char *s2, size_t n)
Definition: routines.c:293
void setExecutableName(const char *const path)
Definition: routines.c:186
char * CurrentDirectory
Definition: routines.c:152
void * eMalloc(const size_t size)
Definition: routines.c:218
static char * concat(const char *s1, const char *s2, const char *s3)
Definition: routines.c:736
bool strToULong(const char *const str, int base, unsigned long *value)
Definition: routines.c:389
const char * getExecutablePath(void)
Definition: routines.c:197
void toLowerString(char *str)
Definition: routines.c:342
static void canonicalizePath(char *const path)
Definition: routines.c:572
bool isSameFile(const char *const name1, const char *const name2)
Definition: routines.c:582
#define S_ISLNK(mode)
Definition: routines.c:81
char * baseFilenameSansExtensionNew(const char *const fileName, const char *const templateExt)
Definition: routines.c:666
char * newUpperString(const char *str)
Definition: routines.c:374
void eFreeNoNullCheck(void *const ptr)
Definition: routines.c:258
#define S_IRUSR
Definition: routines.c:108
const char * fileExtension(const char *const fileName)
Definition: routines.c:650
#define MB_LEN_MAX
Definition: routines.c:29
char * absoluteDirname(char *file)
Definition: routines.c:833
char * strstr(const char *str, const char *substr)
Definition: routines.c:304
void eFreeIndirect(void **ptr)
Definition: routines.c:263
bool isRecursiveLink(const char *const dirName)
Definition: routines.c:507
#define S_ISGID
Definition: routines.c:119
const char * getExecutableName(void)
Definition: routines.c:192
static char * strSeparator(const char *s)
Definition: routines.c:547
void * eRealloc(void *const ptr, const size_t size)
Definition: routines.c:238
static const char * ExecutableName
Definition: routines.c:155
static const char * ExecutableProgram
Definition: routines.c:154
char * eStrdup(const char *str)
Definition: routines.c:327
void setCurrentDirectory(void)
Definition: routines.c:438
bool isAbsolutePath(const char *const path)
Definition: routines.c:684
void eFree(void *const ptr)
Definition: routines.c:252
bool doesExecutableExist(const char *const fileName)
Definition: routines.c:501
fileStatus * eStat(const char *const fileName)
Definition: routines.c:455
static char * strRSeparator(const char *s)
Definition: routines.c:556
void eStatFree(fileStatus *status)
Definition: routines.c:486
MIO * tempFile(const char *const mode, char **const pName)
Definition: routines.c:896
#define S_IWUSR
Definition: routines.c:111
const char * baseFilename(const char *const filePath)
Definition: routines.c:608
void toUpperString(char *str)
Definition: routines.c:351
#define PATH_MAX
Definition: routines.c:137
bool strToLong(const char *const str, int base, long *value)
Definition: routines.c:403
char * strrstr(const char *str, const char *substr)
Definition: routines.c:316
#define S_IXUSR
Definition: routines.c:98
void freeRoutineResources(void)
Definition: routines.c:180
static bool fnmChEq(int c1, int c2)
Definition: routines.c:205
void * eCalloc(const size_t count, const size_t size)
Definition: routines.c:228
char * relativeFilename(const char *file, const char *dir)
Definition: routines.c:854
#define xMalloc(n, Type)
Definition: routines.h:23
@ PERROR
Definition: routines.h:37
@ FATAL
Definition: routines.h:37
#define PATH_SEPARATOR
Definition: routines_p.h:26
#define OUTPUT_PATH_SEPARATOR
Definition: routines_p.h:33
GtkWidget * save
Definition: sidebar.c:57
MIO:
Definition: mio.c:136
bool exists
Definition: routines_p.h:49
bool isSymbolicLink
Definition: routines_p.h:52
bool isExecutable
Definition: routines_p.h:61
bool isSetuid
Definition: routines_p.h:64
char * name
Definition: routines_p.h:46
void vStringCopyS(vString *const string, const char *const s)
Definition: vstring.c:213
vString * vStringNew(void)
Definition: vstring.c:70
void vStringCatS(vString *const string, const char *const s)
Definition: vstring.c:146
char * vStringDeleteUnwrap(vString *const string)
Definition: vstring.c:267
static void vStringPut(vString *const string, const int c)
Definition: vstring.h:101