1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2007, Free Software Foundation, Inc. *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 2, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
31 ****************************************************************************/
33 /* This file contains those routines named by Import pragmas in
34 packages in the GNAT hierarchy (especially GNAT.OS_Lib) and in
35 package Osint. Many of the subprograms in OS_Lib import standard
36 library calls directly. This file contains all other routines. */
40 /* No need to redefine exit here. */
43 /* We want to use the POSIX variants of include files. */
47 #if defined (__mips_vxworks)
49 #endif /* __mips_vxworks */
55 #define HOST_EXECUTABLE_SUFFIX ".exe"
56 #define HOST_OBJECT_SUFFIX ".obj"
70 /* We don't have libiberty, so use malloc. */
71 #define xmalloc(S) malloc (S)
72 #define xrealloc(V,S) realloc (V,S)
79 #if defined (__MINGW32__)
82 #include <sys/utime.h>
85 #elif defined (__Lynx__)
87 /* Lynx utime.h only defines the entities of interest to us if
88 defined (VMOS_DEV), so ... */
101 #elif defined (__vxworks) && defined (__RTP__)
103 #elif defined (__Lynx__)
104 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
105 has a resource.h header as well, included instead of the lynx
106 version in our setup, causing lots of errors. We don't really need
107 the lynx contents of this file, so just workaround the issue by
108 preventing the inclusion of the GCC header from doing anything. */
109 #define GCC_RESOURCE_H
110 #include <sys/wait.h>
112 #include <sys/wait.h>
115 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
118 /* Header files and definitions for __gnat_set_file_time_name. */
120 #define __NEW_STARLET 1
122 #include <vms/atrdef.h>
123 #include <vms/fibdef.h>
124 #include <vms/stsdef.h>
125 #include <vms/iodef.h>
127 #include <vms/descrip.h>
131 /* Use native 64-bit arithmetic. */
132 #define unix_time_to_vms(X,Y) \
133 { unsigned long long reftime, tmptime = (X); \
134 $DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
135 SYS$BINTIM (&unixtime, &reftime); \
136 Y = tmptime * 10000000 + reftime; }
138 /* descrip.h doesn't have everything ... */
139 typedef struct fibdef
* __fibdef_ptr32
__attribute__ (( mode (SI
) ));
140 struct dsc$descriptor_fib
142 unsigned int fib$l_len
;
143 __fibdef_ptr32 fib$l_addr
;
146 /* I/O Status Block. */
149 unsigned short status
, count
;
153 static char *tryfile
;
155 /* Variable length string. */
159 char string
[NAM$C_MAXRSS
+1];
166 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
174 #define DIR_SEPARATOR '\\'
179 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
180 defined in the current system. On DOS-like systems these flags control
181 whether the file is opened/created in text-translation mode (CR/LF in
182 external file mapped to LF in internal file), but in Unix-like systems,
183 no text translation is required, so these flags have no effect. */
185 #if defined (__EMX__)
201 #ifndef HOST_EXECUTABLE_SUFFIX
202 #define HOST_EXECUTABLE_SUFFIX ""
205 #ifndef HOST_OBJECT_SUFFIX
206 #define HOST_OBJECT_SUFFIX ".o"
209 #ifndef PATH_SEPARATOR
210 #define PATH_SEPARATOR ':'
213 #ifndef DIR_SEPARATOR
214 #define DIR_SEPARATOR '/'
217 /* Check for cross-compilation */
218 #ifdef CROSS_DIRECTORY_STRUCTURE
219 int __gnat_is_cross_compiler
= 1;
221 int __gnat_is_cross_compiler
= 0;
224 char __gnat_dir_separator
= DIR_SEPARATOR
;
226 char __gnat_path_separator
= PATH_SEPARATOR
;
228 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
229 the base filenames that libraries specified with -lsomelib options
230 may have. This is used by GNATMAKE to check whether an executable
231 is up-to-date or not. The syntax is
233 library_template ::= { pattern ; } pattern NUL
234 pattern ::= [ prefix ] * [ postfix ]
236 These should only specify names of static libraries as it makes
237 no sense to determine at link time if dynamic-link libraries are
238 up to date or not. Any libraries that are not found are supposed
241 * if they are needed but not present, the link
244 * otherwise they are libraries in the system paths and so
245 they are considered part of the system and not checked
248 ??? This should be part of a GNAT host-specific compiler
249 file instead of being included in all user applications
250 as well. This is only a temporary work-around for 3.11b. */
252 #ifndef GNAT_LIBRARY_TEMPLATE
253 #if defined (__EMX__)
254 #define GNAT_LIBRARY_TEMPLATE "*.a"
256 #define GNAT_LIBRARY_TEMPLATE "*.olb"
258 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
262 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
264 /* This variable is used in hostparm.ads to say whether the host is a VMS
267 const int __gnat_vmsp
= 1;
269 const int __gnat_vmsp
= 0;
273 #define GNAT_MAX_PATH_LEN MAX_PATH
276 #define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
278 #elif defined (__vxworks) || defined (__OPENNT)
279 #define GNAT_MAX_PATH_LEN PATH_MAX
283 #if defined (__MINGW32__)
287 #include <sys/param.h>
291 #include <sys/param.h>
295 #define GNAT_MAX_PATH_LEN MAXPATHLEN
297 #define GNAT_MAX_PATH_LEN 256
302 /* The __gnat_max_path_len variable is used to export the maximum
303 length of a path name to Ada code. max_path_len is also provided
304 for compatibility with older GNAT versions, please do not use
307 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
308 int max_path_len
= GNAT_MAX_PATH_LEN
;
310 /* The following macro HAVE_READDIR_R should be defined if the
311 system provides the routine readdir_r. */
312 #undef HAVE_READDIR_R
314 #if defined(VMS) && defined (__LONG_POINTERS)
316 /* Return a 32 bit pointer to an array of 32 bit pointers
317 given a 64 bit pointer to an array of 64 bit pointers */
319 typedef __char_ptr32
*__char_ptr_char_ptr32
__attribute__ ((mode (SI
)));
321 static __char_ptr_char_ptr32
322 to_ptr32 (char **ptr64
)
325 __char_ptr_char_ptr32 short_argv
;
327 for (argc
=0; ptr64
[argc
]; argc
++);
329 /* Reallocate argv with 32 bit pointers. */
330 short_argv
= (__char_ptr_char_ptr32
) decc$malloc
331 (sizeof (__char_ptr32
) * (argc
+ 1));
333 for (argc
=0; ptr64
[argc
]; argc
++)
334 short_argv
[argc
] = (__char_ptr32
) decc$
strdup (ptr64
[argc
]);
336 short_argv
[argc
] = (__char_ptr32
) 0;
340 #define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
342 #define MAYBE_TO_PTR32(argv) argv
349 time_t res
= time (NULL
);
350 return (OS_Time
) res
;
364 time_t time
= (time_t) *p_time
;
367 /* On Windows systems, the time is sometimes rounded up to the nearest
368 even second, so if the number of seconds is odd, increment it. */
374 res
= localtime (&time
);
376 res
= gmtime (&time
);
381 *p_year
= res
->tm_year
;
382 *p_month
= res
->tm_mon
;
383 *p_day
= res
->tm_mday
;
384 *p_hours
= res
->tm_hour
;
385 *p_mins
= res
->tm_min
;
386 *p_secs
= res
->tm_sec
;
389 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
392 /* Place the contents of the symbolic link named PATH in the buffer BUF,
393 which has size BUFSIZ. If PATH is a symbolic link, then return the number
394 of characters of its content in BUF. Otherwise, return -1. For Windows,
395 OS/2 and vxworks, always return -1. */
398 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
399 char *buf ATTRIBUTE_UNUSED
,
400 size_t bufsiz ATTRIBUTE_UNUSED
)
402 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__)
404 #elif defined (__INTERIX) || defined (VMS)
406 #elif defined (__vxworks)
409 return readlink (path
, buf
, bufsiz
);
413 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH. If
414 NEWPATH exists it will NOT be overwritten. For Windows, OS/2, VxWorks,
415 Interix and VMS, always return -1. */
418 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
419 char *newpath ATTRIBUTE_UNUSED
)
421 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__)
423 #elif defined (__INTERIX) || defined (VMS)
425 #elif defined (__vxworks)
428 return symlink (oldpath
, newpath
);
432 /* Try to lock a file, return 1 if success. */
434 #if defined (__vxworks) || defined (MSDOS) || defined (_WIN32)
436 /* Version that does not use link. */
439 __gnat_try_lock (char *dir
, char *file
)
443 TCHAR wfull_path
[GNAT_MAX_PATH_LEN
];
444 TCHAR wfile
[GNAT_MAX_PATH_LEN
];
445 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
447 S2WSU (wdir
, dir
, GNAT_MAX_PATH_LEN
);
448 S2WSU (wfile
, file
, GNAT_MAX_PATH_LEN
);
450 _stprintf (wfull_path
, _T("%s%c%s"), wdir
, _T(DIR_SEPARATOR
), wfile
);
451 fd
= _topen (wfull_path
, O_CREAT
| O_EXCL
, 0600);
455 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
456 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
466 #elif defined (__EMX__) || defined (VMS)
468 /* More cases that do not use link; identical code, to solve too long
472 __gnat_try_lock (char *dir
, char *file
)
477 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
478 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
489 /* Version using link(), more secure over NFS. */
490 /* See TN 6913-016 for discussion ??? */
493 __gnat_try_lock (char *dir
, char *file
)
497 struct stat stat_result
;
500 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
501 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
502 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
504 /* Create the temporary file and write the process number. */
505 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
511 /* Link it with the new file. */
512 link (temp_file
, full_path
);
514 /* Count the references on the old one. If we have a count of two, then
515 the link did succeed. Remove the temporary file before returning. */
516 __gnat_stat (temp_file
, &stat_result
);
518 return stat_result
.st_nlink
== 2;
522 /* Return the maximum file name length. */
525 __gnat_get_maximum_file_name_length (void)
530 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
539 /* Return nonzero if file names are case sensitive. */
542 __gnat_get_file_names_case_sensitive (void)
544 #if defined (__EMX__) || defined (MSDOS) || defined (VMS) || defined (WINNT)
552 __gnat_get_default_identifier_character_set (void)
554 #if defined (__EMX__) || defined (MSDOS)
561 /* Return the current working directory. */
564 __gnat_get_current_dir (char *dir
, int *length
)
566 #if defined (__MINGW32__)
567 TCHAR wdir
[GNAT_MAX_PATH_LEN
];
569 _tgetcwd (wdir
, *length
);
571 WS2SU (dir
, wdir
, GNAT_MAX_PATH_LEN
);
574 /* Force Unix style, which is what GNAT uses internally. */
575 getcwd (dir
, *length
, 0);
577 getcwd (dir
, *length
);
580 *length
= strlen (dir
);
582 if (dir
[*length
- 1] != DIR_SEPARATOR
)
584 dir
[*length
] = DIR_SEPARATOR
;
590 /* Return the suffix for object files. */
593 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
595 *value
= HOST_OBJECT_SUFFIX
;
600 *len
= strlen (*value
);
605 /* Return the suffix for executable files. */
608 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
610 *value
= HOST_EXECUTABLE_SUFFIX
;
614 *len
= strlen (*value
);
619 /* Return the suffix for debuggable files. Usually this is the same as the
620 executable extension. */
623 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
626 *value
= HOST_EXECUTABLE_SUFFIX
;
628 /* On DOS, the extensionless COFF file is what gdb likes. */
635 *len
= strlen (*value
);
640 /* Returns the OS filename and corresponding encoding. */
643 __gnat_os_filename (char *filename
, char *w_filename
,
644 char *os_name
, int *o_length
,
645 char *encoding
, int *e_length
)
647 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
648 WS2SU (os_name
, (TCHAR
*)w_filename
, o_length
);
649 *o_length
= strlen (os_name
);
650 strcpy (encoding
, "encoding=utf8");
651 *e_length
= strlen (encoding
);
653 strcpy (os_name
, filename
);
654 *o_length
= strlen (filename
);
660 __gnat_fopen (char *path
, char *mode
, int encoding
)
662 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
663 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
666 S2WS (wmode
, mode
, 10);
668 if (encoding
== Encoding_UTF8
)
669 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
671 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
673 return _tfopen (wpath
, wmode
);
675 return decc$
fopen (path
, mode
);
677 return fopen (path
, mode
);
682 __gnat_freopen (char *path
, char *mode
, FILE *stream
, int encoding
)
684 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
685 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
688 S2WS (wmode
, mode
, 10);
690 if (encoding
== Encoding_UTF8
)
691 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
693 S2WS (wpath
, path
, GNAT_MAX_PATH_LEN
);
695 return _tfreopen (wpath
, wmode
, stream
);
697 return decc$
freopen (path
, mode
, stream
);
699 return freopen (path
, mode
, stream
);
704 __gnat_open_read (char *path
, int fmode
)
707 int o_fmode
= O_BINARY
;
713 /* Optional arguments mbc,deq,fop increase read performance. */
714 fd
= open (path
, O_RDONLY
| o_fmode
, 0444,
715 "mbc=16", "deq=64", "fop=tef");
716 #elif defined (__vxworks)
717 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
718 #elif defined (__MINGW32__)
720 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
722 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
723 fd
= _topen (wpath
, O_RDONLY
| o_fmode
, 0444);
726 fd
= open (path
, O_RDONLY
| o_fmode
);
729 return fd
< 0 ? -1 : fd
;
732 #if defined (__EMX__) || defined (__MINGW32__)
733 #define PERM (S_IREAD | S_IWRITE)
735 /* Excerpt from DECC C RTL Reference Manual:
736 To create files with OpenVMS RMS default protections using the UNIX
737 system-call functions umask, mkdir, creat, and open, call mkdir, creat,
738 and open with a file-protection mode argument of 0777 in a program
739 that never specifically calls umask. These default protections include
740 correctly establishing protections based on ACLs, previous versions of
744 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
748 __gnat_open_rw (char *path
, int fmode
)
751 int o_fmode
= O_BINARY
;
757 fd
= open (path
, O_RDWR
| o_fmode
, PERM
,
758 "mbc=16", "deq=64", "fop=tef");
759 #elif defined (__MINGW32__)
761 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
763 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
764 fd
= _topen (wpath
, O_RDWR
| o_fmode
, PERM
);
767 fd
= open (path
, O_RDWR
| o_fmode
, PERM
);
770 return fd
< 0 ? -1 : fd
;
774 __gnat_open_create (char *path
, int fmode
)
777 int o_fmode
= O_BINARY
;
783 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
,
784 "mbc=16", "deq=64", "fop=tef");
785 #elif defined (__MINGW32__)
787 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
789 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
790 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
793 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
796 return fd
< 0 ? -1 : fd
;
800 __gnat_create_output_file (char *path
)
804 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
,
805 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
806 "shr=del,get,put,upd");
807 #elif defined (__MINGW32__)
809 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
811 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
812 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
815 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
818 return fd
< 0 ? -1 : fd
;
822 __gnat_open_append (char *path
, int fmode
)
825 int o_fmode
= O_BINARY
;
831 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
,
832 "mbc=16", "deq=64", "fop=tef");
833 #elif defined (__MINGW32__)
835 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
837 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
838 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
841 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
844 return fd
< 0 ? -1 : fd
;
847 /* Open a new file. Return error (-1) if the file already exists. */
850 __gnat_open_new (char *path
, int fmode
)
853 int o_fmode
= O_BINARY
;
859 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
860 "mbc=16", "deq=64", "fop=tef");
861 #elif defined (__MINGW32__)
863 TCHAR wpath
[GNAT_MAX_PATH_LEN
];
865 S2WSU (wpath
, path
, GNAT_MAX_PATH_LEN
);
866 fd
= _topen (wpath
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
869 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
872 return fd
< 0 ? -1 : fd
;
875 /* Open a new temp file. Return error (-1) if the file already exists.
876 Special options for VMS allow the file to be shared between parent and child
877 processes, however they really slow down output. Used in gnatchop. */
880 __gnat_open_new_temp (char *path
, int fmode
)
883 int o_fmode
= O_BINARY
;
885 strcpy (path
, "GNAT-XXXXXX");
887 #if (defined (__FreeBSD__) || defined (linux)) && !defined (__vxworks)
888 return mkstemp (path
);
889 #elif defined (__Lynx__)
892 if (mktemp (path
) == NULL
)
900 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
901 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
902 "mbc=16", "deq=64", "fop=tef");
904 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
907 return fd
< 0 ? -1 : fd
;
910 /* Return the number of bytes in the specified file. */
913 __gnat_file_length (int fd
)
918 ret
= fstat (fd
, &statbuf
);
919 if (ret
|| !S_ISREG (statbuf
.st_mode
))
922 return (statbuf
.st_size
);
925 /* Return the number of bytes in the specified named file. */
928 __gnat_named_file_length (char *name
)
933 ret
= __gnat_stat (name
, &statbuf
);
934 if (ret
|| !S_ISREG (statbuf
.st_mode
))
937 return (statbuf
.st_size
);
940 /* Create a temporary filename and put it in string pointed to by
944 __gnat_tmp_name (char *tmp_filename
)
950 /* tempnam tries to create a temporary file in directory pointed to by
951 TMP environment variable, in c:\temp if TMP is not set, and in
952 directory specified by P_tmpdir in stdio.h if c:\temp does not
953 exist. The filename will be created with the prefix "gnat-". */
955 pname
= (char *) tempnam ("c:\\temp", "gnat-");
957 /* if pname is NULL, the file was not created properly, the disk is full
958 or there is no more free temporary files */
961 *tmp_filename
= '\0';
963 /* If pname start with a back slash and not path information it means that
964 the filename is valid for the current working directory. */
966 else if (pname
[0] == '\\')
968 strcpy (tmp_filename
, ".\\");
969 strcat (tmp_filename
, pname
+1);
972 strcpy (tmp_filename
, pname
);
977 #elif defined (linux) || defined (__FreeBSD__)
978 #define MAX_SAFE_PATH 1000
979 char *tmpdir
= getenv ("TMPDIR");
981 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
982 a buffer overflow. */
983 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
984 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
986 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
988 close (mkstemp(tmp_filename
));
990 tmpnam (tmp_filename
);
994 /* Open directory and returns a DIR pointer. */
996 DIR* __gnat_opendir (char *name
)
999 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1001 S2WSU (wname
, name
, GNAT_MAX_PATH_LEN
);
1002 return (DIR*)_topendir (wname
);
1005 return opendir (name
);
1009 /* Read the next entry in a directory. The returned string points somewhere
1013 __gnat_readdir (DIR *dirp
, char *buffer
, int *len
)
1015 #if defined (__MINGW32__)
1016 struct _tdirent
*dirent
= _treaddir ((_TDIR
*)dirp
);
1020 WS2SU (buffer
, dirent
->d_name
, GNAT_MAX_PATH_LEN
);
1021 *len
= strlen (buffer
);
1028 #elif defined (HAVE_READDIR_R)
1029 /* If possible, try to use the thread-safe version. */
1030 if (readdir_r (dirp
, buffer
) != NULL
)
1032 *len
= strlen (((struct dirent
*) buffer
)->d_name
);
1033 return ((struct dirent
*) buffer
)->d_name
;
1039 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
1043 strcpy (buffer
, dirent
->d_name
);
1044 *len
= strlen (buffer
);
1053 /* Close a directory entry. */
1055 int __gnat_closedir (DIR *dirp
)
1058 return _tclosedir ((_TDIR
*)dirp
);
1061 return closedir (dirp
);
1065 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1068 __gnat_readdir_is_thread_safe (void)
1070 #ifdef HAVE_READDIR_R
1078 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1079 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
1081 /* Returns the file modification timestamp using Win32 routines which are
1082 immune against daylight saving time change. It is in fact not possible to
1083 use fstat for this purpose as the DST modify the st_mtime field of the
1087 win32_filetime (HANDLE h
)
1092 unsigned long long ull_time
;
1095 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1096 since <Jan 1st 1601>. This function must return the number of seconds
1097 since <Jan 1st 1970>. */
1099 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
1100 return (time_t) (t_write
.ull_time
/ 10000000ULL - w32_epoch_offset
);
1105 /* Return a GNAT time stamp given a file name. */
1108 __gnat_file_time_name (char *name
)
1111 #if defined (__EMX__) || defined (MSDOS)
1112 int fd
= open (name
, O_RDONLY
| O_BINARY
);
1113 time_t ret
= __gnat_file_time_fd (fd
);
1115 return (OS_Time
)ret
;
1117 #elif defined (_WIN32)
1119 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1121 S2WSU (wname
, name
, GNAT_MAX_PATH_LEN
);
1123 HANDLE h
= CreateFile
1124 (wname
, GENERIC_READ
, FILE_SHARE_READ
, 0,
1125 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
1127 if (h
!= INVALID_HANDLE_VALUE
)
1129 ret
= win32_filetime (h
);
1132 return (OS_Time
) ret
;
1134 struct stat statbuf
;
1135 if (__gnat_stat (name
, &statbuf
) != 0) {
1139 /* VMS has file versioning. */
1140 return (OS_Time
)statbuf
.st_ctime
;
1142 return (OS_Time
)statbuf
.st_mtime
;
1148 /* Return a GNAT time stamp given a file descriptor. */
1151 __gnat_file_time_fd (int fd
)
1153 /* The following workaround code is due to the fact that under EMX and
1154 DJGPP fstat attempts to convert time values to GMT rather than keep the
1155 actual OS timestamp of the file. By using the OS2/DOS functions directly
1156 the GNAT timestamp are independent of this behavior, which is desired to
1157 facilitate the distribution of GNAT compiled libraries. */
1159 #if defined (__EMX__) || defined (MSDOS)
1163 int ret
= DosQueryFileInfo (fd
, 1, (unsigned char *) &fs
,
1164 sizeof (FILESTATUS
));
1166 unsigned file_year
= fs
.fdateLastWrite
.year
;
1167 unsigned file_month
= fs
.fdateLastWrite
.month
;
1168 unsigned file_day
= fs
.fdateLastWrite
.day
;
1169 unsigned file_hour
= fs
.ftimeLastWrite
.hours
;
1170 unsigned file_min
= fs
.ftimeLastWrite
.minutes
;
1171 unsigned file_tsec
= fs
.ftimeLastWrite
.twosecs
;
1175 int ret
= getftime (fd
, &fs
);
1177 unsigned file_year
= fs
.ft_year
;
1178 unsigned file_month
= fs
.ft_month
;
1179 unsigned file_day
= fs
.ft_day
;
1180 unsigned file_hour
= fs
.ft_hour
;
1181 unsigned file_min
= fs
.ft_min
;
1182 unsigned file_tsec
= fs
.ft_tsec
;
1185 /* Calculate the seconds since epoch from the time components. First count
1186 the whole days passed. The value for years returned by the DOS and OS2
1187 functions count years from 1980, so to compensate for the UNIX epoch which
1188 begins in 1970 start with 10 years worth of days and add days for each
1189 four year period since then. */
1192 int cum_days
[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1193 int days_passed
= 3652 + (file_year
/ 4) * 1461;
1194 int years_since_leap
= file_year
% 4;
1196 if (years_since_leap
== 1)
1198 else if (years_since_leap
== 2)
1200 else if (years_since_leap
== 3)
1201 days_passed
+= 1096;
1206 days_passed
+= cum_days
[file_month
- 1];
1207 if (years_since_leap
== 0 && file_year
!= 20 && file_month
> 2)
1210 days_passed
+= file_day
- 1;
1212 /* OK - have whole days. Multiply -- then add in other parts. */
1214 tot_secs
= days_passed
* 86400;
1215 tot_secs
+= file_hour
* 3600;
1216 tot_secs
+= file_min
* 60;
1217 tot_secs
+= file_tsec
* 2;
1218 return (OS_Time
) tot_secs
;
1220 #elif defined (_WIN32)
1221 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1222 time_t ret
= win32_filetime (h
);
1223 return (OS_Time
) ret
;
1226 struct stat statbuf
;
1228 if (fstat (fd
, &statbuf
) != 0) {
1229 return (OS_Time
) -1;
1232 /* VMS has file versioning. */
1233 return (OS_Time
) statbuf
.st_ctime
;
1235 return (OS_Time
) statbuf
.st_mtime
;
1241 /* Set the file time stamp. */
1244 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1246 #if defined (__EMX__) || defined (MSDOS) || defined (__vxworks)
1248 /* Code to implement __gnat_set_file_time_name for these systems. */
1250 #elif defined (_WIN32)
1254 unsigned long long ull_time
;
1256 TCHAR wname
[GNAT_MAX_PATH_LEN
];
1258 S2WSU (wname
, name
, GNAT_MAX_PATH_LEN
);
1260 HANDLE h
= CreateFile
1261 (wname
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1262 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1264 if (h
== INVALID_HANDLE_VALUE
)
1266 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1267 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1268 /* Convert to 100 nanosecond units */
1269 t_write
.ull_time
*= 10000000ULL;
1271 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1281 unsigned long long backup
, create
, expire
, revise
;
1285 unsigned short value
;
1288 unsigned system
: 4;
1294 } Fat
= { 0, 0, 0, 0, 0, { 0 }};
1298 { ATR$S_CREDATE
, ATR$C_CREDATE
, &Fat
.create
},
1299 { ATR$S_REVDATE
, ATR$C_REVDATE
, &Fat
.revise
},
1300 { ATR$S_EXPDATE
, ATR$C_EXPDATE
, &Fat
.expire
},
1301 { ATR$S_BAKDATE
, ATR$C_BAKDATE
, &Fat
.backup
},
1302 { ATR$S_FPRO
, ATR$C_FPRO
, &Fat
.prot
},
1303 { ATR$S_UIC
, ATR$C_UIC
, &Fat
.uic
},
1308 struct dsc$descriptor_fib fibdsc
= {sizeof (fib
), (void *) &fib
};
1312 unsigned long long newtime
;
1313 unsigned long long revtime
;
1317 struct vstring file
;
1318 struct dsc$descriptor_s filedsc
1319 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) file
.string
};
1320 struct vstring device
;
1321 struct dsc$descriptor_s devicedsc
1322 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) device
.string
};
1323 struct vstring timev
;
1324 struct dsc$descriptor_s timedsc
1325 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) timev
.string
};
1326 struct vstring result
;
1327 struct dsc$descriptor_s resultdsc
1328 = {NAM$C_MAXRSS
, DSC$K_DTYPE_VT
, DSC$K_CLASS_VS
, (void *) result
.string
};
1330 /* Convert parameter name (a file spec) to host file form. Note that this
1331 is needed on VMS to prepare for subsequent calls to VMS RMS library
1332 routines. Note that it would not work to call __gnat_to_host_dir_spec
1333 as was done in a previous version, since this fails silently unless
1334 the feature logical DECC$EFS_CHARSET is enabled, in which case a DNF
1335 (directory not found) condition is signalled. */
1336 tryfile
= (char *) __gnat_to_host_file_spec (name
);
1338 /* Allocate and initialize a FAB and NAM structures. */
1342 nam
.nam$l_esa
= file
.string
;
1343 nam
.nam$b_ess
= NAM$C_MAXRSS
;
1344 nam
.nam$l_rsa
= result
.string
;
1345 nam
.nam$b_rss
= NAM$C_MAXRSS
;
1346 fab
.fab$l_fna
= tryfile
;
1347 fab
.fab$b_fns
= strlen (tryfile
);
1348 fab
.fab$l_nam
= &nam
;
1350 /* Validate filespec syntax and device existence. */
1351 status
= SYS$
PARSE (&fab
, 0, 0);
1352 if ((status
& 1) != 1)
1353 LIB$
SIGNAL (status
);
1355 file
.string
[nam
.nam$b_esl
] = 0;
1357 /* Find matching filespec. */
1358 status
= SYS$
SEARCH (&fab
, 0, 0);
1359 if ((status
& 1) != 1)
1360 LIB$
SIGNAL (status
);
1362 file
.string
[nam
.nam$b_esl
] = 0;
1363 result
.string
[result
.length
=nam
.nam$b_rsl
] = 0;
1365 /* Get the device name and assign an IO channel. */
1366 strncpy (device
.string
, nam
.nam$l_dev
, nam
.nam$b_dev
);
1367 devicedsc
.dsc$w_length
= nam
.nam$b_dev
;
1369 status
= SYS$
ASSIGN (&devicedsc
, &chan
, 0, 0, 0);
1370 if ((status
& 1) != 1)
1371 LIB$
SIGNAL (status
);
1373 /* Initialize the FIB and fill in the directory id field. */
1374 memset (&fib
, 0, sizeof (fib
));
1375 fib
.fib$w_did
[0] = nam
.nam$w_did
[0];
1376 fib
.fib$w_did
[1] = nam
.nam$w_did
[1];
1377 fib
.fib$w_did
[2] = nam
.nam$w_did
[2];
1378 fib
.fib$l_acctl
= 0;
1380 strcpy (file
.string
, (strrchr (result
.string
, ']') + 1));
1381 filedsc
.dsc$w_length
= strlen (file
.string
);
1382 result
.string
[result
.length
= 0] = 0;
1384 /* Open and close the file to fill in the attributes. */
1386 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1387 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1388 if ((status
& 1) != 1)
1389 LIB$
SIGNAL (status
);
1390 if ((iosb
.status
& 1) != 1)
1391 LIB$
SIGNAL (iosb
.status
);
1393 result
.string
[result
.length
] = 0;
1394 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0, &fibdsc
, 0, 0, 0,
1396 if ((status
& 1) != 1)
1397 LIB$
SIGNAL (status
);
1398 if ((iosb
.status
& 1) != 1)
1399 LIB$
SIGNAL (iosb
.status
);
1404 /* Set creation time to requested time. */
1405 unix_time_to_vms (time_stamp
, newtime
);
1407 t
= time ((time_t) 0);
1409 /* Set revision time to now in local time. */
1410 unix_time_to_vms (t
, revtime
);
1413 /* Reopen the file, modify the times and then close. */
1414 fib
.fib$l_acctl
= FIB$M_WRITE
;
1416 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1417 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1418 if ((status
& 1) != 1)
1419 LIB$
SIGNAL (status
);
1420 if ((iosb
.status
& 1) != 1)
1421 LIB$
SIGNAL (iosb
.status
);
1423 Fat
.create
= newtime
;
1424 Fat
.revise
= revtime
;
1426 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0,
1427 &fibdsc
, 0, 0, 0, &atrlst
, 0);
1428 if ((status
& 1) != 1)
1429 LIB$
SIGNAL (status
);
1430 if ((iosb
.status
& 1) != 1)
1431 LIB$
SIGNAL (iosb
.status
);
1433 /* Deassign the channel and exit. */
1434 status
= SYS$
DASSGN (chan
);
1435 if ((status
& 1) != 1)
1436 LIB$
SIGNAL (status
);
1438 struct utimbuf utimbuf
;
1441 /* Set modification time to requested time. */
1442 utimbuf
.modtime
= time_stamp
;
1444 /* Set access time to now in local time. */
1445 t
= time ((time_t) 0);
1446 utimbuf
.actime
= mktime (localtime (&t
));
1448 utime (name
, &utimbuf
);
1453 #include <windows.h>
1456 /* Get the list of installed standard libraries from the
1457 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1461 __gnat_get_libraries_from_registry (void)
1463 char *result
= (char *) "";
1465 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
1468 DWORD name_size
, value_size
;
1475 /* First open the key. */
1476 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1478 if (res
== ERROR_SUCCESS
)
1479 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1480 KEY_READ
, ®_key
);
1482 if (res
== ERROR_SUCCESS
)
1483 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1485 if (res
== ERROR_SUCCESS
)
1486 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1488 /* If the key exists, read out all the values in it and concatenate them
1490 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1492 value_size
= name_size
= 256;
1493 res
= RegEnumValueA (reg_key
, index
, (TCHAR
*)name
, &name_size
, 0,
1494 &type
, (LPBYTE
)value
, &value_size
);
1496 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1498 char *old_result
= result
;
1500 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1501 strcpy (result
, old_result
);
1502 strcat (result
, value
);
1503 strcat (result
, ";");
1507 /* Remove the trailing ";". */
1509 result
[strlen (result
) - 1] = 0;
1516 __gnat_stat (char *name
, struct stat
*statbuf
)
1519 /* Under Windows the directory name for the stat function must not be
1520 terminated by a directory separator except if just after a drive name. */
1521 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1525 S2WSU (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1526 name_len
= _tcslen (wname
);
1528 if (name_len
> GNAT_MAX_PATH_LEN
)
1531 last_char
= wname
[name_len
- 1];
1533 while (name_len
> 1 && (last_char
== _T('\\') || last_char
== _T('/')))
1535 wname
[name_len
- 1] = _T('\0');
1537 last_char
= wname
[name_len
- 1];
1540 /* Only a drive letter followed by ':', we must add a directory separator
1541 for the stat routine to work properly. */
1542 if (name_len
== 2 && wname
[1] == _T(':'))
1543 _tcscat (wname
, _T("\\"));
1545 return _tstat (wname
, statbuf
);
1548 return stat (name
, statbuf
);
1553 __gnat_file_exists (char *name
)
1556 /* On Windows do not use __gnat_stat() because a bug in Microsoft
1557 _stat() routine. When the system time-zone is set with a negative
1558 offset the _stat() routine fails on specific files like CON: */
1559 TCHAR wname
[GNAT_MAX_PATH_LEN
+ 2];
1561 S2WSU (wname
, name
, GNAT_MAX_PATH_LEN
+ 2);
1562 return GetFileAttributes (wname
) != INVALID_FILE_ATTRIBUTES
;
1564 struct stat statbuf
;
1566 return !__gnat_stat (name
, &statbuf
);
1571 __gnat_is_absolute_path (char *name
, int length
)
1574 /* On VxWorks systems, an absolute path can be represented (depending on
1575 the host platform) as either /dir/file, or device:/dir/file, or
1576 device:drive_letter:/dir/file. */
1583 for (index
= 0; index
< length
; index
++)
1585 if (name
[index
] == ':' &&
1586 ((name
[index
+ 1] == '/') ||
1587 (isalpha (name
[index
+ 1]) && index
+ 2 <= length
&&
1588 name
[index
+ 2] == '/')))
1591 else if (name
[index
] == '/')
1596 return (length
!= 0) &&
1597 (*name
== '/' || *name
== DIR_SEPARATOR
1598 #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
1599 || (length
> 1 && isalpha (name
[0]) && name
[1] == ':')
1606 __gnat_is_regular_file (char *name
)
1609 struct stat statbuf
;
1611 ret
= __gnat_stat (name
, &statbuf
);
1612 return (!ret
&& S_ISREG (statbuf
.st_mode
));
1616 __gnat_is_directory (char *name
)
1619 struct stat statbuf
;
1621 ret
= __gnat_stat (name
, &statbuf
);
1622 return (!ret
&& S_ISDIR (statbuf
.st_mode
));
1626 __gnat_is_readable_file (char *name
)
1630 struct stat statbuf
;
1632 ret
= __gnat_stat (name
, &statbuf
);
1633 mode
= statbuf
.st_mode
& S_IRUSR
;
1634 return (!ret
&& mode
);
1638 __gnat_is_writable_file (char *name
)
1642 struct stat statbuf
;
1644 ret
= __gnat_stat (name
, &statbuf
);
1645 mode
= statbuf
.st_mode
& S_IWUSR
;
1646 return (!ret
&& mode
);
1650 __gnat_set_writable (char *name
)
1653 struct stat statbuf
;
1655 if (stat (name
, &statbuf
) == 0)
1657 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
1658 chmod (name
, statbuf
.st_mode
);
1664 __gnat_set_executable (char *name
)
1667 struct stat statbuf
;
1669 if (stat (name
, &statbuf
) == 0)
1671 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
1672 chmod (name
, statbuf
.st_mode
);
1678 __gnat_set_readonly (char *name
)
1681 struct stat statbuf
;
1683 if (stat (name
, &statbuf
) == 0)
1685 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
1686 chmod (name
, statbuf
.st_mode
);
1692 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
1694 #if defined (__vxworks)
1697 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
1699 struct stat statbuf
;
1701 ret
= lstat (name
, &statbuf
);
1702 return (!ret
&& S_ISLNK (statbuf
.st_mode
));
1709 #if defined (sun) && defined (__SVR4)
1710 /* Using fork on Solaris will duplicate all the threads. fork1, which
1711 duplicates only the active thread, must be used instead, or spawning
1712 subprocess from a program with tasking will lead into numerous problems. */
1717 __gnat_portable_spawn (char *args
[])
1720 int finished ATTRIBUTE_UNUSED
;
1721 int pid ATTRIBUTE_UNUSED
;
1723 #if defined (MSDOS) || defined (_WIN32)
1724 /* args[0] must be quotes as it could contain a full pathname with spaces */
1725 char *args_0
= args
[0];
1726 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
1727 strcpy (args
[0], "\"");
1728 strcat (args
[0], args_0
);
1729 strcat (args
[0], "\"");
1731 status
= spawnvp (P_WAIT
, args_0
, (const char* const*)args
);
1733 /* restore previous value */
1735 args
[0] = (char *)args_0
;
1742 #elif defined (__vxworks)
1747 pid
= spawnvp (P_NOWAIT
, args
[0], args
);
1759 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
1761 return -1; /* execv is in parent context on VMS. */
1769 finished
= waitpid (pid
, &status
, 0);
1771 if (finished
!= pid
|| WIFEXITED (status
) == 0)
1774 return WEXITSTATUS (status
);
1780 /* Create a copy of the given file descriptor.
1781 Return -1 if an error occurred. */
1784 __gnat_dup (int oldfd
)
1786 #if defined (__vxworks) && !defined (__RTP__)
1787 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
1795 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
1796 Return -1 if an error occurred. */
1799 __gnat_dup2 (int oldfd
, int newfd
)
1801 #if defined (__vxworks) && !defined (__RTP__)
1802 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
1806 return dup2 (oldfd
, newfd
);
1810 /* WIN32 code to implement a wait call that wait for any child process. */
1814 /* Synchronization code, to be thread safe. */
1816 static CRITICAL_SECTION plist_cs
;
1819 __gnat_plist_init (void)
1821 InitializeCriticalSection (&plist_cs
);
1827 EnterCriticalSection (&plist_cs
);
1833 LeaveCriticalSection (&plist_cs
);
1836 typedef struct _process_list
1839 struct _process_list
*next
;
1842 static Process_List
*PLIST
= NULL
;
1844 static int plist_length
= 0;
1847 add_handle (HANDLE h
)
1851 pl
= (Process_List
*) xmalloc (sizeof (Process_List
));
1855 /* -------------------- critical section -------------------- */
1860 /* -------------------- critical section -------------------- */
1866 remove_handle (HANDLE h
)
1869 Process_List
*prev
= NULL
;
1873 /* -------------------- critical section -------------------- */
1882 prev
->next
= pl
->next
;
1894 /* -------------------- critical section -------------------- */
1900 win32_no_block_spawn (char *command
, char *args
[])
1904 PROCESS_INFORMATION PI
;
1905 SECURITY_ATTRIBUTES SA
;
1910 /* compute the total command line length */
1914 csize
+= strlen (args
[k
]) + 1;
1918 full_command
= (char *) xmalloc (csize
);
1921 SI
.cb
= sizeof (STARTUPINFO
);
1922 SI
.lpReserved
= NULL
;
1923 SI
.lpReserved2
= NULL
;
1924 SI
.lpDesktop
= NULL
;
1928 SI
.wShowWindow
= SW_HIDE
;
1930 /* Security attributes. */
1931 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
1932 SA
.bInheritHandle
= TRUE
;
1933 SA
.lpSecurityDescriptor
= NULL
;
1935 /* Prepare the command string. */
1936 strcpy (full_command
, command
);
1937 strcat (full_command
, " ");
1942 strcat (full_command
, args
[k
]);
1943 strcat (full_command
, " ");
1948 int wsize
= csize
* 2;
1949 TCHAR
*wcommand
= (TCHAR
*) xmalloc (wsize
);
1951 S2WSU (wcommand
, full_command
, wsize
);
1953 free (full_command
);
1955 result
= CreateProcess
1956 (NULL
, wcommand
, &SA
, NULL
, TRUE
,
1957 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
1964 add_handle (PI
.hProcess
);
1965 CloseHandle (PI
.hThread
);
1966 return (int) PI
.hProcess
;
1973 win32_wait (int *status
)
1982 if (plist_length
== 0)
1988 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * plist_length
);
1993 /* -------------------- critical section -------------------- */
2000 /* -------------------- critical section -------------------- */
2004 res
= WaitForMultipleObjects (plist_length
, hl
, FALSE
, INFINITE
);
2005 h
= hl
[res
- WAIT_OBJECT_0
];
2010 GetExitCodeProcess (h
, &exitcode
);
2013 *status
= (int) exitcode
;
2020 __gnat_portable_no_block_spawn (char *args
[])
2024 #if defined (__EMX__) || defined (MSDOS)
2026 /* ??? For PC machines I (Franco) don't know the system calls to implement
2027 this routine. So I'll fake it as follows. This routine will behave
2028 exactly like the blocking portable_spawn and will systematically return
2029 a pid of 0 unless the spawned task did not complete successfully, in
2030 which case we return a pid of -1. To synchronize with this the
2031 portable_wait below systematically returns a pid of 0 and reports that
2032 the subprocess terminated successfully. */
2034 if (spawnvp (P_WAIT
, args
[0], args
) != 0)
2037 #elif defined (_WIN32)
2039 pid
= win32_no_block_spawn (args
[0], args
);
2042 #elif defined (__vxworks)
2051 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
2053 return -1; /* execv is in parent context on VMS. */
2065 __gnat_portable_wait (int *process_status
)
2070 #if defined (_WIN32)
2072 pid
= win32_wait (&status
);
2074 #elif defined (__EMX__) || defined (MSDOS)
2075 /* ??? See corresponding comment in portable_no_block_spawn. */
2077 #elif defined (__vxworks)
2078 /* Not sure what to do here, so do same as __EMX__ case, i.e., nothing but
2082 pid
= waitpid (-1, &status
, 0);
2083 status
= status
& 0xffff;
2086 *process_status
= status
;
2091 __gnat_os_exit (int status
)
2096 /* Locate a regular file, give a Path value. */
2099 __gnat_locate_regular_file (char *file_name
, char *path_val
)
2102 char *file_path
= alloca (strlen (file_name
) + 1);
2105 /* Return immediately if file_name is empty */
2107 if (*file_name
== '\0')
2110 /* Remove quotes around file_name if present */
2116 strcpy (file_path
, ptr
);
2118 ptr
= file_path
+ strlen (file_path
) - 1;
2123 /* Handle absolute pathnames. */
2125 absolute
= __gnat_is_absolute_path (file_path
, strlen (file_name
));
2129 if (__gnat_is_regular_file (file_path
))
2130 return xstrdup (file_path
);
2135 /* If file_name include directory separator(s), try it first as
2136 a path name relative to the current directory */
2137 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
2142 if (__gnat_is_regular_file (file_name
))
2143 return xstrdup (file_name
);
2150 /* The result has to be smaller than path_val + file_name. */
2151 char *file_path
= alloca (strlen (path_val
) + strlen (file_name
) + 2);
2155 for (; *path_val
== PATH_SEPARATOR
; path_val
++)
2161 /* Skip the starting quote */
2163 if (*path_val
== '"')
2166 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
2167 *ptr
++ = *path_val
++;
2171 /* Skip the ending quote */
2176 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
2177 *++ptr
= DIR_SEPARATOR
;
2179 strcpy (++ptr
, file_name
);
2181 if (__gnat_is_regular_file (file_path
))
2182 return xstrdup (file_path
);
2189 /* Locate an executable given a Path argument. This routine is only used by
2190 gnatbl and should not be used otherwise. Use locate_exec_on_path
2194 __gnat_locate_exec (char *exec_name
, char *path_val
)
2197 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2199 char *full_exec_name
2200 = alloca (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2202 strcpy (full_exec_name
, exec_name
);
2203 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2204 ptr
= __gnat_locate_regular_file (full_exec_name
, path_val
);
2207 return __gnat_locate_regular_file (exec_name
, path_val
);
2211 return __gnat_locate_regular_file (exec_name
, path_val
);
2214 /* Locate an executable using the Systems default PATH. */
2217 __gnat_locate_exec_on_path (char *exec_name
)
2222 TCHAR
*wpath_val
= _tgetenv (_T("PATH"));
2224 /* In Win32 systems we expand the PATH as for XP environment
2225 variables are not automatically expanded. We also prepend the
2226 ".;" to the path to match normal NT path search semantics */
2228 #define EXPAND_BUFFER_SIZE 32767
2230 wapath_val
= alloca (EXPAND_BUFFER_SIZE
);
2232 wapath_val
[0] = '.';
2233 wapath_val
[1] = ';';
2235 DWORD res
= ExpandEnvironmentStrings
2236 (wpath_val
, &wapath_val
[2], EXPAND_BUFFER_SIZE
- 2);
2238 if (!res
) wapath_val
[0] = _T('\0');
2240 apath_val
= alloca (EXPAND_BUFFER_SIZE
);
2242 WS2SU (apath_val
, wapath_val
, EXPAND_BUFFER_SIZE
);
2243 return __gnat_locate_exec (exec_name
, apath_val
);
2248 char *path_val
= "/VAXC$PATH";
2250 char *path_val
= getenv ("PATH");
2252 if (path_val
== NULL
) return NULL
;
2253 apath_val
= alloca (strlen (path_val
) + 1);
2254 strcpy (apath_val
, path_val
);
2255 return __gnat_locate_exec (exec_name
, apath_val
);
2261 /* These functions are used to translate to and from VMS and Unix syntax
2262 file, directory and path specifications. */
2265 #define MAXNAMES 256
2266 #define NEW_CANONICAL_FILELIST_INCREMENT 64
2268 static char new_canonical_dirspec
[MAXPATH
];
2269 static char new_canonical_filespec
[MAXPATH
];
2270 static char new_canonical_pathspec
[MAXNAMES
*MAXPATH
];
2271 static unsigned new_canonical_filelist_index
;
2272 static unsigned new_canonical_filelist_in_use
;
2273 static unsigned new_canonical_filelist_allocated
;
2274 static char **new_canonical_filelist
;
2275 static char new_host_pathspec
[MAXNAMES
*MAXPATH
];
2276 static char new_host_dirspec
[MAXPATH
];
2277 static char new_host_filespec
[MAXPATH
];
2279 /* Routine is called repeatedly by decc$from_vms via
2280 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2284 wildcard_translate_unix (char *name
)
2287 char buff
[MAXPATH
];
2289 strncpy (buff
, name
, MAXPATH
);
2290 buff
[MAXPATH
- 1] = (char) 0;
2291 ver
= strrchr (buff
, '.');
2293 /* Chop off the version. */
2297 /* Dynamically extend the allocation by the increment. */
2298 if (new_canonical_filelist_in_use
== new_canonical_filelist_allocated
)
2300 new_canonical_filelist_allocated
+= NEW_CANONICAL_FILELIST_INCREMENT
;
2301 new_canonical_filelist
= (char **) xrealloc
2302 (new_canonical_filelist
,
2303 new_canonical_filelist_allocated
* sizeof (char *));
2306 new_canonical_filelist
[new_canonical_filelist_in_use
++] = xstrdup (buff
);
2311 /* Translate a wildcard VMS file spec into a list of Unix file specs. First do
2312 full translation and copy the results into a list (_init), then return them
2313 one at a time (_next). If onlydirs set, only expand directory files. */
2316 __gnat_to_canonical_file_list_init (char *filespec
, int onlydirs
)
2319 char buff
[MAXPATH
];
2321 len
= strlen (filespec
);
2322 strncpy (buff
, filespec
, MAXPATH
);
2324 /* Only look for directories */
2325 if (onlydirs
&& !strstr (&buff
[len
-5], "*.dir"))
2326 strncat (buff
, "*.dir", MAXPATH
);
2328 buff
[MAXPATH
- 1] = (char) 0;
2330 decc$
from_vms (buff
, wildcard_translate_unix
, 1);
2332 /* Remove the .dir extension. */
2338 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2340 ext
= strstr (new_canonical_filelist
[i
], ".dir");
2346 return new_canonical_filelist_in_use
;
2349 /* Return the next filespec in the list. */
2352 __gnat_to_canonical_file_list_next ()
2354 return new_canonical_filelist
[new_canonical_filelist_index
++];
2357 /* Free storage used in the wildcard expansion. */
2360 __gnat_to_canonical_file_list_free ()
2364 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2365 free (new_canonical_filelist
[i
]);
2367 free (new_canonical_filelist
);
2369 new_canonical_filelist_in_use
= 0;
2370 new_canonical_filelist_allocated
= 0;
2371 new_canonical_filelist_index
= 0;
2372 new_canonical_filelist
= 0;
2375 /* The functional equivalent of decc$translate_vms routine.
2376 Designed to produce the same output, but is protected against
2377 malformed paths (original version ACCVIOs in this case) and
2378 does not require VMS-specific DECC RTL */
2380 #define NAM$C_MAXRSS 1024
2383 __gnat_translate_vms (char *src
)
2385 static char retbuf
[NAM$C_MAXRSS
+1];
2386 char *srcendpos
, *pos1
, *pos2
, *retpos
;
2387 int disp
, path_present
= 0;
2389 if (!src
) return NULL
;
2391 srcendpos
= strchr (src
, '\0');
2394 /* Look for the node and/or device in front of the path */
2396 pos2
= strchr (pos1
, ':');
2398 if (pos2
&& (pos2
< srcendpos
) && (*(pos2
+ 1) == ':')) {
2399 /* There is a node name. "node_name::" becomes "node_name!" */
2401 strncpy (retbuf
, pos1
, disp
);
2402 retpos
[disp
] = '!';
2403 retpos
= retpos
+ disp
+ 1;
2405 pos2
= strchr (pos1
, ':');
2409 /* There is a device name. "dev_name:" becomes "/dev_name/" */
2412 strncpy (retpos
, pos1
, disp
);
2413 retpos
= retpos
+ disp
;
2418 /* No explicit device; we must look ahead and prepend /sys$disk/ if
2419 the path is absolute */
2420 if ((*pos1
== '[' || *pos1
== '<') && (pos1
< srcendpos
)
2421 && !strchr (".-]>", *(pos1
+ 1))) {
2422 strncpy (retpos
, "/sys$disk/", 10);
2426 /* Process the path part */
2427 while (*pos1
== '[' || *pos1
== '<') {
2430 if (*pos1
== ']' || *pos1
== '>') {
2431 /* Special case, [] translates to '.' */
2436 /* '[000000' means root dir. It can be present in the middle of
2437 the path due to expansion of logical devices, in which case
2439 if (!strncmp (pos1
, "000000", 6) && path_present
> 1 &&
2440 (*(pos1
+ 6) == ']' || *(pos1
+ 6) == '>' || *(pos1
+ 6) == '.')) {
2442 if (*pos1
== '.') pos1
++;
2444 else if (*pos1
== '.') {
2449 /* There is a qualified path */
2450 while (*pos1
&& *pos1
!= ']' && *pos1
!= '>') {
2453 /* '.' is used to separate directories. Replace it with '/' but
2454 only if there isn't already '/' just before */
2455 if (*(retpos
- 1) != '/') *(retpos
++) = '/';
2457 if (pos1
+ 1 < srcendpos
&& *pos1
== '.' && *(pos1
+ 1) == '.') {
2458 /* ellipsis refers to entire subtree; replace with '**' */
2459 *(retpos
++) = '*'; *(retpos
++) = '*'; *(retpos
++) = '/';
2464 /* When after '.' '[' '<' is equivalent to Unix ".." but there
2465 may be several in a row */
2466 if (*(pos1
- 1) == '.' || *(pos1
- 1) == '[' ||
2467 *(pos1
- 1) == '<') {
2468 while (*pos1
== '-') {
2470 *(retpos
++) = '.'; *(retpos
++) = '.'; *(retpos
++) = '/';
2475 /* otherwise fall through to default */
2477 *(retpos
++) = *(pos1
++);
2484 if (pos1
< srcendpos
) {
2485 /* Now add the actual file name, until the version suffix if any */
2486 if (path_present
) *(retpos
++) = '/';
2487 pos2
= strchr (pos1
, ';');
2488 disp
= pos2
? (pos2
- pos1
) : (srcendpos
- pos1
);
2489 strncpy (retpos
, pos1
, disp
);
2491 if (pos2
&& pos2
< srcendpos
) {
2492 /* There is a non-empty version suffix. ";<ver>" becomes ".<ver>" */
2494 disp
= srcendpos
- pos2
- 1;
2495 strncpy (retpos
, pos2
+ 1, disp
);
2506 /* Translate a VMS syntax directory specification in to Unix syntax. If
2507 PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
2508 found, return input string. Also translate a dirname that contains no
2509 slashes, in case it's a logical name. */
2512 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag
)
2516 strcpy (new_canonical_dirspec
, "");
2517 if (strlen (dirspec
))
2521 if (strchr (dirspec
, ']') || strchr (dirspec
, ':'))
2523 strncpy (new_canonical_dirspec
,
2524 __gnat_translate_vms (dirspec
),
2527 else if (!strchr (dirspec
, '/') && (dirspec1
= getenv (dirspec
)) != 0)
2529 strncpy (new_canonical_dirspec
,
2530 __gnat_translate_vms (dirspec1
),
2535 strncpy (new_canonical_dirspec
, dirspec
, MAXPATH
);
2539 len
= strlen (new_canonical_dirspec
);
2540 if (prefixflag
&& new_canonical_dirspec
[len
-1] != '/')
2541 strncat (new_canonical_dirspec
, "/", MAXPATH
);
2543 new_canonical_dirspec
[MAXPATH
- 1] = (char) 0;
2545 return new_canonical_dirspec
;
2549 /* Translate a VMS syntax file specification into Unix syntax.
2550 If no indicators of VMS syntax found, check if it's an uppercase
2551 alphanumeric_ name and if so try it out as an environment
2552 variable (logical name). If all else fails return the
2556 __gnat_to_canonical_file_spec (char *filespec
)
2560 strncpy (new_canonical_filespec
, "", MAXPATH
);
2562 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
2564 char *tspec
= (char *) __gnat_translate_vms (filespec
);
2566 if (tspec
!= (char *) -1)
2567 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
2569 else if ((strlen (filespec
) == strspn (filespec
,
2570 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
2571 && (filespec1
= getenv (filespec
)))
2573 char *tspec
= (char *) __gnat_translate_vms (filespec1
);
2575 if (tspec
!= (char *) -1)
2576 strncpy (new_canonical_filespec
, tspec
, MAXPATH
);
2580 strncpy (new_canonical_filespec
, filespec
, MAXPATH
);
2583 new_canonical_filespec
[MAXPATH
- 1] = (char) 0;
2585 return new_canonical_filespec
;
2588 /* Translate a VMS syntax path specification into Unix syntax.
2589 If no indicators of VMS syntax found, return input string. */
2592 __gnat_to_canonical_path_spec (char *pathspec
)
2594 char *curr
, *next
, buff
[MAXPATH
];
2599 /* If there are /'s, assume it's a Unix path spec and return. */
2600 if (strchr (pathspec
, '/'))
2603 new_canonical_pathspec
[0] = 0;
2608 next
= strchr (curr
, ',');
2610 next
= strchr (curr
, 0);
2612 strncpy (buff
, curr
, next
- curr
);
2613 buff
[next
- curr
] = 0;
2615 /* Check for wildcards and expand if present. */
2616 if (strchr (buff
, '*') || strchr (buff
, '%') || strstr (buff
, "..."))
2620 dirs
= __gnat_to_canonical_file_list_init (buff
, 1);
2621 for (i
= 0; i
< dirs
; i
++)
2625 next_dir
= __gnat_to_canonical_file_list_next ();
2626 strncat (new_canonical_pathspec
, next_dir
, MAXPATH
);
2628 /* Don't append the separator after the last expansion. */
2630 strncat (new_canonical_pathspec
, ":", MAXPATH
);
2633 __gnat_to_canonical_file_list_free ();
2636 strncat (new_canonical_pathspec
,
2637 __gnat_to_canonical_dir_spec (buff
, 0), MAXPATH
);
2642 strncat (new_canonical_pathspec
, ":", MAXPATH
);
2646 new_canonical_pathspec
[MAXPATH
- 1] = (char) 0;
2648 return new_canonical_pathspec
;
2651 static char filename_buff
[MAXPATH
];
2654 translate_unix (char *name
, int type
)
2656 strncpy (filename_buff
, name
, MAXPATH
);
2657 filename_buff
[MAXPATH
- 1] = (char) 0;
2661 /* Translate a Unix syntax path spec into a VMS style (comma separated list of
2665 to_host_path_spec (char *pathspec
)
2667 char *curr
, *next
, buff
[MAXPATH
];
2672 /* Can't very well test for colons, since that's the Unix separator! */
2673 if (strchr (pathspec
, ']') || strchr (pathspec
, ','))
2676 new_host_pathspec
[0] = 0;
2681 next
= strchr (curr
, ':');
2683 next
= strchr (curr
, 0);
2685 strncpy (buff
, curr
, next
- curr
);
2686 buff
[next
- curr
] = 0;
2688 strncat (new_host_pathspec
, __gnat_to_host_dir_spec (buff
, 0), MAXPATH
);
2691 strncat (new_host_pathspec
, ",", MAXPATH
);
2695 new_host_pathspec
[MAXPATH
- 1] = (char) 0;
2697 return new_host_pathspec
;
2700 /* Translate a Unix syntax directory specification into VMS syntax. The
2701 PREFIXFLAG has no effect, but is kept for symmetry with
2702 to_canonical_dir_spec. If indicators of VMS syntax found, return input
2706 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2708 int len
= strlen (dirspec
);
2710 strncpy (new_host_dirspec
, dirspec
, MAXPATH
);
2711 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
2713 if (strchr (new_host_dirspec
, ']') || strchr (new_host_dirspec
, ':'))
2714 return new_host_dirspec
;
2716 while (len
> 1 && new_host_dirspec
[len
- 1] == '/')
2718 new_host_dirspec
[len
- 1] = 0;
2722 decc$
to_vms (new_host_dirspec
, translate_unix
, 1, 2);
2723 strncpy (new_host_dirspec
, filename_buff
, MAXPATH
);
2724 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
2726 return new_host_dirspec
;
2729 /* Translate a Unix syntax file specification into VMS syntax.
2730 If indicators of VMS syntax found, return input string. */
2733 __gnat_to_host_file_spec (char *filespec
)
2735 strncpy (new_host_filespec
, "", MAXPATH
);
2736 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
2738 strncpy (new_host_filespec
, filespec
, MAXPATH
);
2742 decc$
to_vms (filespec
, translate_unix
, 1, 1);
2743 strncpy (new_host_filespec
, filename_buff
, MAXPATH
);
2746 new_host_filespec
[MAXPATH
- 1] = (char) 0;
2748 return new_host_filespec
;
2752 __gnat_adjust_os_resource_limits ()
2754 SYS$
ADJWSL (131072, 0);
2759 /* Dummy functions for Osint import for non-VMS systems. */
2762 __gnat_to_canonical_file_list_init
2763 (char *dirspec ATTRIBUTE_UNUSED
, int onlydirs ATTRIBUTE_UNUSED
)
2769 __gnat_to_canonical_file_list_next (void)
2775 __gnat_to_canonical_file_list_free (void)
2780 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2786 __gnat_to_canonical_file_spec (char *filespec
)
2792 __gnat_to_canonical_path_spec (char *pathspec
)
2798 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2804 __gnat_to_host_file_spec (char *filespec
)
2810 __gnat_adjust_os_resource_limits (void)
2816 /* For EMX, we cannot include dummy in libgcc, since it is too difficult
2817 to coordinate this with the EMX distribution. Consequently, we put the
2818 definition of dummy which is used for exception handling, here. */
2820 #if defined (__EMX__)
2824 #if defined (__mips_vxworks)
2828 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
2832 #if defined (CROSS_DIRECTORY_STRUCTURE) \
2833 || (! ((defined (sparc) || defined (i386)) && defined (sun) \
2834 && defined (__SVR4)) \
2835 && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
2836 && ! (defined (linux) && defined (__ia64__)) \
2837 && ! defined (__FreeBSD__) \
2838 && ! defined (__hpux__) \
2839 && ! defined (__APPLE__) \
2840 && ! defined (_AIX) \
2841 && ! (defined (__alpha__) && defined (__osf__)) \
2842 && ! defined (VMS) \
2843 && ! defined (__MINGW32__) \
2844 && ! (defined (__mips) && defined (__sgi)))
2846 /* Dummy function to satisfy g-trasym.o. See the preprocessor conditional
2847 just above for a list of native platforms that provide a non-dummy
2848 version of this procedure in libaddr2line.a. */
2851 convert_addresses (const char *file_name ATTRIBUTE_UNUSED
,
2852 void *addrs ATTRIBUTE_UNUSED
,
2853 int n_addr ATTRIBUTE_UNUSED
,
2854 void *buf ATTRIBUTE_UNUSED
,
2855 int *len ATTRIBUTE_UNUSED
)
2861 #if defined (_WIN32)
2862 int __gnat_argument_needs_quote
= 1;
2864 int __gnat_argument_needs_quote
= 0;
2867 /* This option is used to enable/disable object files handling from the
2868 binder file by the GNAT Project module. For example, this is disabled on
2869 Windows (prior to GCC 3.4) as it is already done by the mdll module.
2870 Stating with GCC 3.4 the shared libraries are not based on mdll
2871 anymore as it uses the GCC's -shared option */
2872 #if defined (_WIN32) \
2873 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
2874 int __gnat_prj_add_obj_files
= 0;
2876 int __gnat_prj_add_obj_files
= 1;
2879 /* char used as prefix/suffix for environment variables */
2880 #if defined (_WIN32)
2881 char __gnat_environment_char
= '%';
2883 char __gnat_environment_char
= '$';
2886 /* This functions copy the file attributes from a source file to a
2889 mode = 0 : In this mode copy only the file time stamps (last access and
2890 last modification time stamps).
2892 mode = 1 : In this mode, time stamps and read/write/execute attributes are
2895 Returns 0 if operation was successful and -1 in case of error. */
2898 __gnat_copy_attribs (char *from
, char *to
, int mode
)
2900 #if defined (VMS) || defined (__vxworks)
2904 struct utimbuf tbuf
;
2906 if (stat (from
, &fbuf
) == -1)
2911 tbuf
.actime
= fbuf
.st_atime
;
2912 tbuf
.modtime
= fbuf
.st_mtime
;
2914 if (utime (to
, &tbuf
) == -1)
2921 if (chmod (to
, fbuf
.st_mode
) == -1)
2932 __gnat_lseek (int fd
, long offset
, int whence
)
2934 return (int) lseek (fd
, offset
, whence
);
2937 /* This function returns the major version number of GCC being used. */
2939 get_gcc_version (void)
2944 return (int) (version_string
[0] - '0');
2949 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED
,
2950 int close_on_exec_p ATTRIBUTE_UNUSED
)
2952 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
2953 int flags
= fcntl (fd
, F_GETFD
, 0);
2956 if (close_on_exec_p
)
2957 flags
|= FD_CLOEXEC
;
2959 flags
&= ~FD_CLOEXEC
;
2960 return fcntl (fd
, F_SETFD
, flags
| FD_CLOEXEC
);
2963 /* For the Windows case, we should use SetHandleInformation to remove
2964 the HANDLE_INHERIT property from fd. This is not implemented yet,
2965 but for our purposes (support of GNAT.Expect) this does not matter,
2966 as by default handles are *not* inherited. */
2970 /* Indicates if platforms supports automatic initialization through the
2971 constructor mechanism */
2973 __gnat_binder_supports_auto_init ()
2982 /* Indicates that Stand-Alone Libraries are automatically initialized through
2983 the constructor mechanism */
2985 __gnat_sals_init_using_constructors ()
2987 #if defined (__vxworks) || defined (__Lynx__) || defined (VMS)