1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2005, 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, 59 Temple Place - Suite 330, Boston, *
20 * MA 02111-1307, 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 */
68 /* We don't have libiberty, so use malloc. */
69 #define xmalloc(S) malloc (S)
70 #define xrealloc(V,S) realloc (V,S)
78 #include <sys/utime.h>
94 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
97 /* Header files and definitions for __gnat_set_file_time_name. */
109 /* Use native 64-bit arithmetic. */
110 #define unix_time_to_vms(X,Y) \
111 { unsigned long long reftime, tmptime = (X); \
112 $DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
113 SYS$BINTIM (&unixtime, &reftime); \
114 Y = tmptime * 10000000 + reftime; }
116 /* descrip.h doesn't have everything ... */
117 struct dsc$descriptor_fib
119 unsigned long fib$l_len
;
120 struct fibdef
*fib$l_addr
;
123 /* I/O Status Block. */
126 unsigned short status
, count
;
127 unsigned long devdep
;
130 static char *tryfile
;
132 /* Variable length string. */
136 char string
[NAM$C_MAXRSS
+1];
143 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
151 #define DIR_SEPARATOR '\\'
156 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
157 defined in the current system. On DOS-like systems these flags control
158 whether the file is opened/created in text-translation mode (CR/LF in
159 external file mapped to LF in internal file), but in Unix-like systems,
160 no text translation is required, so these flags have no effect. */
162 #if defined (__EMX__)
178 #ifndef HOST_EXECUTABLE_SUFFIX
179 #define HOST_EXECUTABLE_SUFFIX ""
182 #ifndef HOST_OBJECT_SUFFIX
183 #define HOST_OBJECT_SUFFIX ".o"
186 #ifndef PATH_SEPARATOR
187 #define PATH_SEPARATOR ':'
190 #ifndef DIR_SEPARATOR
191 #define DIR_SEPARATOR '/'
194 char __gnat_dir_separator
= DIR_SEPARATOR
;
196 char __gnat_path_separator
= PATH_SEPARATOR
;
198 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
199 the base filenames that libraries specified with -lsomelib options
200 may have. This is used by GNATMAKE to check whether an executable
201 is up-to-date or not. The syntax is
203 library_template ::= { pattern ; } pattern NUL
204 pattern ::= [ prefix ] * [ postfix ]
206 These should only specify names of static libraries as it makes
207 no sense to determine at link time if dynamic-link libraries are
208 up to date or not. Any libraries that are not found are supposed
211 * if they are needed but not present, the link
214 * otherwise they are libraries in the system paths and so
215 they are considered part of the system and not checked
218 ??? This should be part of a GNAT host-specific compiler
219 file instead of being included in all user applications
220 as well. This is only a temporary work-around for 3.11b. */
222 #ifndef GNAT_LIBRARY_TEMPLATE
223 #if defined (__EMX__)
224 #define GNAT_LIBRARY_TEMPLATE "*.a"
226 #define GNAT_LIBRARY_TEMPLATE "*.olb"
228 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
232 const char *__gnat_library_template
= GNAT_LIBRARY_TEMPLATE
;
234 /* This variable is used in hostparm.ads to say whether the host is a VMS
237 const int __gnat_vmsp
= 1;
239 const int __gnat_vmsp
= 0;
243 #define GNAT_MAX_PATH_LEN MAX_PATH
246 #define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
248 #elif defined (__vxworks) || defined (__OPENNT)
249 #define GNAT_MAX_PATH_LEN PATH_MAX
253 #if defined (__MINGW32__)
257 #include <sys/param.h>
261 #include <sys/param.h>
264 #define GNAT_MAX_PATH_LEN MAXPATHLEN
268 /* The __gnat_max_path_len variable is used to export the maximum
269 length of a path name to Ada code. max_path_len is also provided
270 for compatibility with older GNAT versions, please do not use
273 int __gnat_max_path_len
= GNAT_MAX_PATH_LEN
;
274 int max_path_len
= GNAT_MAX_PATH_LEN
;
276 /* The following macro HAVE_READDIR_R should be defined if the
277 system provides the routine readdir_r. */
278 #undef HAVE_READDIR_R
280 #if defined(VMS) && defined (__LONG_POINTERS)
282 /* Return a 32 bit pointer to an array of 32 bit pointers
283 given a 64 bit pointer to an array of 64 bit pointers */
285 typedef __char_ptr32
*__char_ptr_char_ptr32
__attribute__ ((mode (SI
)));
287 static __char_ptr_char_ptr32
288 to_ptr32 (char **ptr64
)
291 __char_ptr_char_ptr32 short_argv
;
293 for (argc
=0; ptr64
[argc
]; argc
++);
295 /* Reallocate argv with 32 bit pointers. */
296 short_argv
= (__char_ptr_char_ptr32
) decc$malloc
297 (sizeof (__char_ptr32
) * (argc
+ 1));
299 for (argc
=0; ptr64
[argc
]; argc
++)
300 short_argv
[argc
] = (__char_ptr32
) decc$
strdup (ptr64
[argc
]);
302 short_argv
[argc
] = (__char_ptr32
) 0;
306 #define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
308 #define MAYBE_TO_PTR32(argv) argv
322 time_t time
= (time_t) *p_time
;
325 /* On Windows systems, the time is sometimes rounded up to the nearest
326 even second, so if the number of seconds is odd, increment it. */
332 res
= localtime (&time
);
334 res
= gmtime (&time
);
339 *p_year
= res
->tm_year
;
340 *p_month
= res
->tm_mon
;
341 *p_day
= res
->tm_mday
;
342 *p_hours
= res
->tm_hour
;
343 *p_mins
= res
->tm_min
;
344 *p_secs
= res
->tm_sec
;
347 *p_year
= *p_month
= *p_day
= *p_hours
= *p_mins
= *p_secs
= 0;
350 /* Place the contents of the symbolic link named PATH in the buffer BUF,
351 which has size BUFSIZ. If PATH is a symbolic link, then return the number
352 of characters of its content in BUF. Otherwise, return -1. For Windows,
353 OS/2 and vxworks, always return -1. */
356 __gnat_readlink (char *path ATTRIBUTE_UNUSED
,
357 char *buf ATTRIBUTE_UNUSED
,
358 size_t bufsiz ATTRIBUTE_UNUSED
)
360 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__)
362 #elif defined (__INTERIX) || defined (VMS)
364 #elif defined (__vxworks)
367 return readlink (path
, buf
, bufsiz
);
371 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH. If
372 NEWPATH exists it will NOT be overwritten. For Windows, OS/2, VxWorks,
373 Interix and VMS, always return -1. */
376 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED
,
377 char *newpath ATTRIBUTE_UNUSED
)
379 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__)
381 #elif defined (__INTERIX) || defined (VMS)
383 #elif defined (__vxworks)
386 return symlink (oldpath
, newpath
);
390 /* Try to lock a file, return 1 if success. */
392 #if defined (__vxworks) || defined (MSDOS) || defined (_WIN32)
394 /* Version that does not use link. */
397 __gnat_try_lock (char *dir
, char *file
)
402 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
403 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
411 #elif defined (__EMX__) || defined (VMS)
413 /* More cases that do not use link; identical code, to solve too long
417 __gnat_try_lock (char *dir
, char *file
)
422 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
423 fd
= open (full_path
, O_CREAT
| O_EXCL
, 0600);
433 /* Version using link(), more secure over NFS. */
434 /* See TN 6913-016 for discussion ??? */
437 __gnat_try_lock (char *dir
, char *file
)
441 struct stat stat_result
;
444 sprintf (full_path
, "%s%c%s", dir
, DIR_SEPARATOR
, file
);
445 sprintf (temp_file
, "%s%cTMP-%ld-%ld",
446 dir
, DIR_SEPARATOR
, (long)getpid(), (long)getppid ());
448 /* Create the temporary file and write the process number. */
449 fd
= open (temp_file
, O_CREAT
| O_WRONLY
, 0600);
455 /* Link it with the new file. */
456 link (temp_file
, full_path
);
458 /* Count the references on the old one. If we have a count of two, then
459 the link did succeed. Remove the temporary file before returning. */
460 __gnat_stat (temp_file
, &stat_result
);
462 return stat_result
.st_nlink
== 2;
466 /* Return the maximum file name length. */
469 __gnat_get_maximum_file_name_length (void)
474 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
483 /* Return nonzero if file names are case sensitive. */
486 __gnat_get_file_names_case_sensitive (void)
488 #if defined (__EMX__) || defined (MSDOS) || defined (VMS) || defined (WINNT)
496 __gnat_get_default_identifier_character_set (void)
498 #if defined (__EMX__) || defined (MSDOS)
505 /* Return the current working directory. */
508 __gnat_get_current_dir (char *dir
, int *length
)
511 /* Force Unix style, which is what GNAT uses internally. */
512 getcwd (dir
, *length
, 0);
514 getcwd (dir
, *length
);
517 *length
= strlen (dir
);
519 if (dir
[*length
- 1] != DIR_SEPARATOR
)
521 dir
[*length
] = DIR_SEPARATOR
;
527 /* Return the suffix for object files. */
530 __gnat_get_object_suffix_ptr (int *len
, const char **value
)
532 *value
= HOST_OBJECT_SUFFIX
;
537 *len
= strlen (*value
);
542 /* Return the suffix for executable files. */
545 __gnat_get_executable_suffix_ptr (int *len
, const char **value
)
547 *value
= HOST_EXECUTABLE_SUFFIX
;
551 *len
= strlen (*value
);
556 /* Return the suffix for debuggable files. Usually this is the same as the
557 executable extension. */
560 __gnat_get_debuggable_suffix_ptr (int *len
, const char **value
)
563 *value
= HOST_EXECUTABLE_SUFFIX
;
565 /* On DOS, the extensionless COFF file is what gdb likes. */
572 *len
= strlen (*value
);
578 __gnat_open_read (char *path
, int fmode
)
581 int o_fmode
= O_BINARY
;
587 /* Optional arguments mbc,deq,fop increase read performance. */
588 fd
= open (path
, O_RDONLY
| o_fmode
, 0444,
589 "mbc=16", "deq=64", "fop=tef");
590 #elif defined (__vxworks)
591 fd
= open (path
, O_RDONLY
| o_fmode
, 0444);
593 fd
= open (path
, O_RDONLY
| o_fmode
);
596 return fd
< 0 ? -1 : fd
;
599 #if defined (__EMX__) || defined (__MINGW32__)
600 #define PERM (S_IREAD | S_IWRITE)
602 /* Excerpt from DECC C RTL Reference Manual:
603 To create files with OpenVMS RMS default protections using the UNIX
604 system-call functions umask, mkdir, creat, and open, call mkdir, creat,
605 and open with a file-protection mode argument of 0777 in a program
606 that never specifically calls umask. These default protections include
607 correctly establishing protections based on ACLs, previous versions of
611 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
615 __gnat_open_rw (char *path
, int fmode
)
618 int o_fmode
= O_BINARY
;
624 fd
= open (path
, O_RDWR
| o_fmode
, PERM
,
625 "mbc=16", "deq=64", "fop=tef");
627 fd
= open (path
, O_RDWR
| o_fmode
, PERM
);
630 return fd
< 0 ? -1 : fd
;
634 __gnat_open_create (char *path
, int fmode
)
637 int o_fmode
= O_BINARY
;
643 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
,
644 "mbc=16", "deq=64", "fop=tef");
646 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| o_fmode
, PERM
);
649 return fd
< 0 ? -1 : fd
;
653 __gnat_create_output_file (char *path
)
657 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
,
658 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
659 "shr=del,get,put,upd");
661 fd
= open (path
, O_WRONLY
| O_CREAT
| O_TRUNC
| O_TEXT
, PERM
);
664 return fd
< 0 ? -1 : fd
;
668 __gnat_open_append (char *path
, int fmode
)
671 int o_fmode
= O_BINARY
;
677 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
,
678 "mbc=16", "deq=64", "fop=tef");
680 fd
= open (path
, O_WRONLY
| O_CREAT
| O_APPEND
| o_fmode
, PERM
);
683 return fd
< 0 ? -1 : fd
;
686 /* Open a new file. Return error (-1) if the file already exists. */
689 __gnat_open_new (char *path
, int fmode
)
692 int o_fmode
= O_BINARY
;
698 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
699 "mbc=16", "deq=64", "fop=tef");
701 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
704 return fd
< 0 ? -1 : fd
;
707 /* Open a new temp file. Return error (-1) if the file already exists.
708 Special options for VMS allow the file to be shared between parent and child
709 processes, however they really slow down output. Used in gnatchop. */
712 __gnat_open_new_temp (char *path
, int fmode
)
715 int o_fmode
= O_BINARY
;
717 strcpy (path
, "GNAT-XXXXXX");
719 #if (defined (__FreeBSD__) || defined (linux)) && !defined (__vxworks)
720 return mkstemp (path
);
721 #elif defined (__Lynx__)
724 if (mktemp (path
) == NULL
)
732 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
,
733 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
734 "mbc=16", "deq=64", "fop=tef");
736 fd
= open (path
, O_WRONLY
| O_CREAT
| O_EXCL
| o_fmode
, PERM
);
739 return fd
< 0 ? -1 : fd
;
742 /* Return the number of bytes in the specified file. */
745 __gnat_file_length (int fd
)
750 ret
= fstat (fd
, &statbuf
);
751 if (ret
|| !S_ISREG (statbuf
.st_mode
))
754 return (statbuf
.st_size
);
757 /* Return the number of bytes in the specified named file. */
760 __gnat_named_file_length (char *name
)
765 ret
= __gnat_stat (name
, &statbuf
);
766 if (ret
|| !S_ISREG (statbuf
.st_mode
))
769 return (statbuf
.st_size
);
772 /* Create a temporary filename and put it in string pointed to by
776 __gnat_tmp_name (char *tmp_filename
)
782 /* tempnam tries to create a temporary file in directory pointed to by
783 TMP environment variable, in c:\temp if TMP is not set, and in
784 directory specified by P_tmpdir in stdio.h if c:\temp does not
785 exist. The filename will be created with the prefix "gnat-". */
787 pname
= (char *) tempnam ("c:\\temp", "gnat-");
789 /* if pname is NULL, the file was not created properly, the disk is full
790 or there is no more free temporary files */
793 *tmp_filename
= '\0';
795 /* If pname start with a back slash and not path information it means that
796 the filename is valid for the current working directory. */
798 else if (pname
[0] == '\\')
800 strcpy (tmp_filename
, ".\\");
801 strcat (tmp_filename
, pname
+1);
804 strcpy (tmp_filename
, pname
);
809 #elif defined (linux) || defined (__FreeBSD__)
810 #define MAX_SAFE_PATH 1000
811 char *tmpdir
= getenv ("TMPDIR");
813 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
814 a buffer overflow. */
815 if (tmpdir
== NULL
|| strlen (tmpdir
) > MAX_SAFE_PATH
)
816 strcpy (tmp_filename
, "/tmp/gnat-XXXXXX");
818 sprintf (tmp_filename
, "%s/gnat-XXXXXX", tmpdir
);
820 close (mkstemp(tmp_filename
));
822 tmpnam (tmp_filename
);
826 /* Read the next entry in a directory. The returned string points somewhere
830 __gnat_readdir (DIR *dirp
, char *buffer
)
832 /* If possible, try to use the thread-safe version. */
833 #ifdef HAVE_READDIR_R
834 if (readdir_r (dirp
, buffer
) != NULL
)
835 return ((struct dirent
*) buffer
)->d_name
;
840 struct dirent
*dirent
= (struct dirent
*) readdir (dirp
);
844 strcpy (buffer
, dirent
->d_name
);
853 /* Returns 1 if readdir is thread safe, 0 otherwise. */
856 __gnat_readdir_is_thread_safe (void)
858 #ifdef HAVE_READDIR_R
866 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
867 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
869 /* Returns the file modification timestamp using Win32 routines which are
870 immune against daylight saving time change. It is in fact not possible to
871 use fstat for this purpose as the DST modify the st_mtime field of the
875 win32_filetime (HANDLE h
)
880 unsigned long long ull_time
;
883 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
884 since <Jan 1st 1601>. This function must return the number of seconds
885 since <Jan 1st 1970>. */
887 if (GetFileTime (h
, NULL
, NULL
, &t_write
.ft_time
))
888 return (time_t) (t_write
.ull_time
/ 10000000ULL
894 /* Return a GNAT time stamp given a file name. */
897 __gnat_file_time_name (char *name
)
900 #if defined (__EMX__) || defined (MSDOS)
901 int fd
= open (name
, O_RDONLY
| O_BINARY
);
902 time_t ret
= __gnat_file_time_fd (fd
);
906 #elif defined (_WIN32)
908 HANDLE h
= CreateFile (name
, GENERIC_READ
, FILE_SHARE_READ
, 0,
909 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, 0);
911 if (h
!= INVALID_HANDLE_VALUE
)
913 ret
= win32_filetime (h
);
916 return (OS_Time
) ret
;
919 if (__gnat_stat (name
, &statbuf
) != 0) {
923 /* VMS has file versioning. */
924 return (OS_Time
)statbuf
.st_ctime
;
926 return (OS_Time
)statbuf
.st_mtime
;
932 /* Return a GNAT time stamp given a file descriptor. */
935 __gnat_file_time_fd (int fd
)
937 /* The following workaround code is due to the fact that under EMX and
938 DJGPP fstat attempts to convert time values to GMT rather than keep the
939 actual OS timestamp of the file. By using the OS2/DOS functions directly
940 the GNAT timestamp are independent of this behavior, which is desired to
941 facilitate the distribution of GNAT compiled libraries. */
943 #if defined (__EMX__) || defined (MSDOS)
947 int ret
= DosQueryFileInfo (fd
, 1, (unsigned char *) &fs
,
948 sizeof (FILESTATUS
));
950 unsigned file_year
= fs
.fdateLastWrite
.year
;
951 unsigned file_month
= fs
.fdateLastWrite
.month
;
952 unsigned file_day
= fs
.fdateLastWrite
.day
;
953 unsigned file_hour
= fs
.ftimeLastWrite
.hours
;
954 unsigned file_min
= fs
.ftimeLastWrite
.minutes
;
955 unsigned file_tsec
= fs
.ftimeLastWrite
.twosecs
;
959 int ret
= getftime (fd
, &fs
);
961 unsigned file_year
= fs
.ft_year
;
962 unsigned file_month
= fs
.ft_month
;
963 unsigned file_day
= fs
.ft_day
;
964 unsigned file_hour
= fs
.ft_hour
;
965 unsigned file_min
= fs
.ft_min
;
966 unsigned file_tsec
= fs
.ft_tsec
;
969 /* Calculate the seconds since epoch from the time components. First count
970 the whole days passed. The value for years returned by the DOS and OS2
971 functions count years from 1980, so to compensate for the UNIX epoch which
972 begins in 1970 start with 10 years worth of days and add days for each
973 four year period since then. */
976 int cum_days
[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
977 int days_passed
= 3652 + (file_year
/ 4) * 1461;
978 int years_since_leap
= file_year
% 4;
980 if (years_since_leap
== 1)
982 else if (years_since_leap
== 2)
984 else if (years_since_leap
== 3)
990 days_passed
+= cum_days
[file_month
- 1];
991 if (years_since_leap
== 0 && file_year
!= 20 && file_month
> 2)
994 days_passed
+= file_day
- 1;
996 /* OK - have whole days. Multiply -- then add in other parts. */
998 tot_secs
= days_passed
* 86400;
999 tot_secs
+= file_hour
* 3600;
1000 tot_secs
+= file_min
* 60;
1001 tot_secs
+= file_tsec
* 2;
1002 return (OS_Time
) tot_secs
;
1004 #elif defined (_WIN32)
1005 HANDLE h
= (HANDLE
) _get_osfhandle (fd
);
1006 time_t ret
= win32_filetime (h
);
1007 return (OS_Time
) ret
;
1010 struct stat statbuf
;
1012 if (fstat (fd
, &statbuf
) != 0) {
1013 return (OS_Time
) -1;
1016 /* VMS has file versioning. */
1017 return (OS_Time
) statbuf
.st_ctime
;
1019 return (OS_Time
) statbuf
.st_mtime
;
1025 /* Set the file time stamp. */
1028 __gnat_set_file_time_name (char *name
, time_t time_stamp
)
1030 #if defined (__EMX__) || defined (MSDOS) || defined (__vxworks)
1032 /* Code to implement __gnat_set_file_time_name for these systems. */
1034 #elif defined (_WIN32)
1038 unsigned long long ull_time
;
1041 HANDLE h
= CreateFile (name
, GENERIC_WRITE
, FILE_SHARE_WRITE
, NULL
,
1042 OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
,
1044 if (h
== INVALID_HANDLE_VALUE
)
1046 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1047 t_write
.ull_time
= ((unsigned long long)time_stamp
+ w32_epoch_offset
);
1048 /* Convert to 100 nanosecond units */
1049 t_write
.ull_time
*= 10000000ULL;
1051 SetFileTime(h
, NULL
, NULL
, &t_write
.ft_time
);
1061 unsigned long long backup
, create
, expire
, revise
;
1065 unsigned short value
;
1068 unsigned system
: 4;
1074 } Fat
= { 0, 0, 0, 0, 0, { 0 }};
1078 { ATR$S_CREDATE
, ATR$C_CREDATE
, &Fat
.create
},
1079 { ATR$S_REVDATE
, ATR$C_REVDATE
, &Fat
.revise
},
1080 { ATR$S_EXPDATE
, ATR$C_EXPDATE
, &Fat
.expire
},
1081 { ATR$S_BAKDATE
, ATR$C_BAKDATE
, &Fat
.backup
},
1082 { ATR$S_FPRO
, ATR$C_FPRO
, &Fat
.prot
},
1083 { ATR$S_UIC
, ATR$C_UIC
, &Fat
.uic
},
1088 struct dsc$descriptor_fib fibdsc
= {sizeof (fib
), (void *) &fib
};
1092 unsigned long long newtime
;
1093 unsigned long long revtime
;
1097 struct vstring file
;
1098 struct dsc$descriptor_s filedsc
1099 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) file
.string
};
1100 struct vstring device
;
1101 struct dsc$descriptor_s devicedsc
1102 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) device
.string
};
1103 struct vstring timev
;
1104 struct dsc$descriptor_s timedsc
1105 = {NAM$C_MAXRSS
, DSC$K_DTYPE_T
, DSC$K_CLASS_S
, (void *) timev
.string
};
1106 struct vstring result
;
1107 struct dsc$descriptor_s resultdsc
1108 = {NAM$C_MAXRSS
, DSC$K_DTYPE_VT
, DSC$K_CLASS_VS
, (void *) result
.string
};
1110 tryfile
= (char *) __gnat_to_host_dir_spec (name
, 0);
1112 /* Allocate and initialize a FAB and NAM structures. */
1116 nam
.nam$l_esa
= file
.string
;
1117 nam
.nam$b_ess
= NAM$C_MAXRSS
;
1118 nam
.nam$l_rsa
= result
.string
;
1119 nam
.nam$b_rss
= NAM$C_MAXRSS
;
1120 fab
.fab$l_fna
= tryfile
;
1121 fab
.fab$b_fns
= strlen (tryfile
);
1122 fab
.fab$l_nam
= &nam
;
1124 /* Validate filespec syntax and device existence. */
1125 status
= SYS$
PARSE (&fab
, 0, 0);
1126 if ((status
& 1) != 1)
1127 LIB$
SIGNAL (status
);
1129 file
.string
[nam
.nam$b_esl
] = 0;
1131 /* Find matching filespec. */
1132 status
= SYS$
SEARCH (&fab
, 0, 0);
1133 if ((status
& 1) != 1)
1134 LIB$
SIGNAL (status
);
1136 file
.string
[nam
.nam$b_esl
] = 0;
1137 result
.string
[result
.length
=nam
.nam$b_rsl
] = 0;
1139 /* Get the device name and assign an IO channel. */
1140 strncpy (device
.string
, nam
.nam$l_dev
, nam
.nam$b_dev
);
1141 devicedsc
.dsc$w_length
= nam
.nam$b_dev
;
1143 status
= SYS$
ASSIGN (&devicedsc
, &chan
, 0, 0, 0);
1144 if ((status
& 1) != 1)
1145 LIB$
SIGNAL (status
);
1147 /* Initialize the FIB and fill in the directory id field. */
1148 memset (&fib
, 0, sizeof (fib
));
1149 fib
.fib$w_did
[0] = nam
.nam$w_did
[0];
1150 fib
.fib$w_did
[1] = nam
.nam$w_did
[1];
1151 fib
.fib$w_did
[2] = nam
.nam$w_did
[2];
1152 fib
.fib$l_acctl
= 0;
1154 strcpy (file
.string
, (strrchr (result
.string
, ']') + 1));
1155 filedsc
.dsc$w_length
= strlen (file
.string
);
1156 result
.string
[result
.length
= 0] = 0;
1158 /* Open and close the file to fill in the attributes. */
1160 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1161 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1162 if ((status
& 1) != 1)
1163 LIB$
SIGNAL (status
);
1164 if ((iosb
.status
& 1) != 1)
1165 LIB$
SIGNAL (iosb
.status
);
1167 result
.string
[result
.length
] = 0;
1168 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0, &fibdsc
, 0, 0, 0,
1170 if ((status
& 1) != 1)
1171 LIB$
SIGNAL (status
);
1172 if ((iosb
.status
& 1) != 1)
1173 LIB$
SIGNAL (iosb
.status
);
1178 /* Set creation time to requested time. */
1179 unix_time_to_vms (time_stamp
, newtime
);
1181 t
= time ((time_t) 0);
1183 /* Set revision time to now in local time. */
1184 unix_time_to_vms (t
, revtime
);
1187 /* Reopen the file, modify the times and then close. */
1188 fib
.fib$l_acctl
= FIB$M_WRITE
;
1190 = SYS$
QIOW (0, chan
, IO$_ACCESS
|IO$M_ACCESS
, &iosb
, 0, 0,
1191 &fibdsc
, &filedsc
, &result
.length
, &resultdsc
, &atrlst
, 0);
1192 if ((status
& 1) != 1)
1193 LIB$
SIGNAL (status
);
1194 if ((iosb
.status
& 1) != 1)
1195 LIB$
SIGNAL (iosb
.status
);
1197 Fat
.create
= newtime
;
1198 Fat
.revise
= revtime
;
1200 status
= SYS$
QIOW (0, chan
, IO$_DEACCESS
, &iosb
, 0, 0,
1201 &fibdsc
, 0, 0, 0, &atrlst
, 0);
1202 if ((status
& 1) != 1)
1203 LIB$
SIGNAL (status
);
1204 if ((iosb
.status
& 1) != 1)
1205 LIB$
SIGNAL (iosb
.status
);
1207 /* Deassign the channel and exit. */
1208 status
= SYS$
DASSGN (chan
);
1209 if ((status
& 1) != 1)
1210 LIB$
SIGNAL (status
);
1212 struct utimbuf utimbuf
;
1215 /* Set modification time to requested time. */
1216 utimbuf
.modtime
= time_stamp
;
1218 /* Set access time to now in local time. */
1219 t
= time ((time_t) 0);
1220 utimbuf
.actime
= mktime (localtime (&t
));
1222 utime (name
, &utimbuf
);
1227 __gnat_get_env_value_ptr (char *name
, int *len
, char **value
)
1229 *value
= getenv (name
);
1233 *len
= strlen (*value
);
1238 /* VMS specific declarations for set_env_value. */
1242 static char *to_host_path_spec (char *);
1246 unsigned short len
, mbz
;
1250 typedef struct _ile3
1252 unsigned short len
, code
;
1254 unsigned short *retlen_adr
;
1260 __gnat_set_env_value (char *name
, char *value
)
1265 struct descriptor_s name_desc
;
1266 /* Put in JOB table for now, so that the project stuff at least works. */
1267 struct descriptor_s table_desc
= {7, 0, "LNM$JOB"};
1268 char *host_pathspec
= value
;
1269 char *copy_pathspec
;
1270 int num_dirs_in_pathspec
= 1;
1274 name_desc
.len
= strlen (name
);
1276 name_desc
.adr
= name
;
1278 if (*host_pathspec
== 0)
1281 status
= LIB$
DELETE_LOGICAL (&name_desc
, &table_desc
);
1282 /* no need to check status; if the logical name is not
1283 defined, that's fine. */
1287 ptr
= host_pathspec
;
1290 num_dirs_in_pathspec
++;
1294 ile_s
*ile_array
= alloca (sizeof (ile_s
) * (num_dirs_in_pathspec
+ 1));
1295 char *copy_pathspec
= alloca (strlen (host_pathspec
) + 1);
1298 strcpy (copy_pathspec
, host_pathspec
);
1299 curr
= copy_pathspec
;
1300 for (i
= 0; i
< num_dirs_in_pathspec
; i
++)
1302 next
= strchr (curr
, ',');
1304 next
= strchr (curr
, 0);
1307 ile_array
[i
].len
= strlen (curr
);
1309 /* Code 2 from lnmdef.h means its a string. */
1310 ile_array
[i
].code
= 2;
1311 ile_array
[i
].adr
= curr
;
1313 /* retlen_adr is ignored. */
1314 ile_array
[i
].retlen_adr
= 0;
1318 /* Terminating item must be zero. */
1319 ile_array
[i
].len
= 0;
1320 ile_array
[i
].code
= 0;
1321 ile_array
[i
].adr
= 0;
1322 ile_array
[i
].retlen_adr
= 0;
1324 status
= LIB$
SET_LOGICAL (&name_desc
, 0, &table_desc
, 0, ile_array
);
1325 if ((status
& 1) != 1)
1326 LIB$
SIGNAL (status
);
1330 int size
= strlen (name
) + strlen (value
) + 2;
1333 expression
= (char *) xmalloc (size
* sizeof (char));
1335 sprintf (expression
, "%s=%s", name
, value
);
1336 putenv (expression
);
1341 #include <windows.h>
1344 /* Get the list of installed standard libraries from the
1345 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1349 __gnat_get_libraries_from_registry (void)
1351 char *result
= (char *) "";
1353 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_COMPILE)
1356 DWORD name_size
, value_size
;
1363 /* First open the key. */
1364 res
= RegOpenKeyExA (HKEY_LOCAL_MACHINE
, "SOFTWARE", 0, KEY_READ
, ®_key
);
1366 if (res
== ERROR_SUCCESS
)
1367 res
= RegOpenKeyExA (reg_key
, "Ada Core Technologies", 0,
1368 KEY_READ
, ®_key
);
1370 if (res
== ERROR_SUCCESS
)
1371 res
= RegOpenKeyExA (reg_key
, "GNAT", 0, KEY_READ
, ®_key
);
1373 if (res
== ERROR_SUCCESS
)
1374 res
= RegOpenKeyExA (reg_key
, "Standard Libraries", 0, KEY_READ
, ®_key
);
1376 /* If the key exists, read out all the values in it and concatenate them
1378 for (index
= 0; res
== ERROR_SUCCESS
; index
++)
1380 value_size
= name_size
= 256;
1381 res
= RegEnumValue (reg_key
, index
, name
, &name_size
, 0,
1382 &type
, (LPBYTE
)value
, &value_size
);
1384 if (res
== ERROR_SUCCESS
&& type
== REG_SZ
)
1386 char *old_result
= result
;
1388 result
= (char *) xmalloc (strlen (old_result
) + value_size
+ 2);
1389 strcpy (result
, old_result
);
1390 strcat (result
, value
);
1391 strcat (result
, ";");
1395 /* Remove the trailing ";". */
1397 result
[strlen (result
) - 1] = 0;
1404 __gnat_stat (char *name
, struct stat
*statbuf
)
1407 /* Under Windows the directory name for the stat function must not be
1408 terminated by a directory separator except if just after a drive name. */
1409 int name_len
= strlen (name
);
1410 char last_char
= name
[name_len
- 1];
1411 char win32_name
[GNAT_MAX_PATH_LEN
+ 2];
1413 if (name_len
> GNAT_MAX_PATH_LEN
)
1416 strcpy (win32_name
, name
);
1418 while (name_len
> 1 && (last_char
== '\\' || last_char
== '/'))
1420 win32_name
[name_len
- 1] = '\0';
1422 last_char
= win32_name
[name_len
- 1];
1425 if (name_len
== 2 && win32_name
[1] == ':')
1426 strcat (win32_name
, "\\");
1428 return stat (win32_name
, statbuf
);
1431 return stat (name
, statbuf
);
1436 __gnat_file_exists (char *name
)
1438 struct stat statbuf
;
1440 return !__gnat_stat (name
, &statbuf
);
1444 __gnat_is_absolute_path (char *name
, int length
)
1446 return (length
!= 0) &&
1447 (*name
== '/' || *name
== DIR_SEPARATOR
1448 #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
1449 || (length
> 1 && isalpha (name
[0]) && name
[1] == ':')
1455 __gnat_is_regular_file (char *name
)
1458 struct stat statbuf
;
1460 ret
= __gnat_stat (name
, &statbuf
);
1461 return (!ret
&& S_ISREG (statbuf
.st_mode
));
1465 __gnat_is_directory (char *name
)
1468 struct stat statbuf
;
1470 ret
= __gnat_stat (name
, &statbuf
);
1471 return (!ret
&& S_ISDIR (statbuf
.st_mode
));
1475 __gnat_is_readable_file (char *name
)
1479 struct stat statbuf
;
1481 ret
= __gnat_stat (name
, &statbuf
);
1482 mode
= statbuf
.st_mode
& S_IRUSR
;
1483 return (!ret
&& mode
);
1487 __gnat_is_writable_file (char *name
)
1491 struct stat statbuf
;
1493 ret
= __gnat_stat (name
, &statbuf
);
1494 mode
= statbuf
.st_mode
& S_IWUSR
;
1495 return (!ret
&& mode
);
1499 __gnat_set_writable (char *name
)
1502 struct stat statbuf
;
1504 if (stat (name
, &statbuf
) == 0)
1506 statbuf
.st_mode
= statbuf
.st_mode
| S_IWUSR
;
1507 chmod (name
, statbuf
.st_mode
);
1513 __gnat_set_executable (char *name
)
1516 struct stat statbuf
;
1518 if (stat (name
, &statbuf
) == 0)
1520 statbuf
.st_mode
= statbuf
.st_mode
| S_IXUSR
;
1521 chmod (name
, statbuf
.st_mode
);
1527 __gnat_set_readonly (char *name
)
1530 struct stat statbuf
;
1532 if (stat (name
, &statbuf
) == 0)
1534 statbuf
.st_mode
= statbuf
.st_mode
& 07577;
1535 chmod (name
, statbuf
.st_mode
);
1541 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED
)
1543 #if defined (__vxworks)
1546 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
1548 struct stat statbuf
;
1550 ret
= lstat (name
, &statbuf
);
1551 return (!ret
&& S_ISLNK (statbuf
.st_mode
));
1558 #if defined (sun) && defined (__SVR4)
1559 /* Using fork on Solaris will duplicate all the threads. fork1, which
1560 duplicates only the active thread, must be used instead, or spawning
1561 subprocess from a program with tasking will lead into numerous problems. */
1566 __gnat_portable_spawn (char *args
[])
1569 int finished ATTRIBUTE_UNUSED
;
1570 int pid ATTRIBUTE_UNUSED
;
1572 #if defined (MSDOS) || defined (_WIN32)
1573 /* args[0] must be quotes as it could contain a full pathname with spaces */
1574 char *args_0
= args
[0];
1575 args
[0] = (char *)xmalloc (strlen (args_0
) + 3);
1576 strcpy (args
[0], "\"");
1577 strcat (args
[0], args_0
);
1578 strcat (args
[0], "\"");
1580 status
= spawnvp (P_WAIT
, args_0
, (char* const*)args
);
1582 /* restore previous value */
1584 args
[0] = (char *)args_0
;
1591 #elif defined (__vxworks)
1596 pid
= spawnvp (P_NOWAIT
, args
[0], args
);
1608 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
1610 return -1; /* execv is in parent context on VMS. */
1618 finished
= waitpid (pid
, &status
, 0);
1620 if (finished
!= pid
|| WIFEXITED (status
) == 0)
1623 return WEXITSTATUS (status
);
1629 /* Create a copy of the given file descriptor.
1630 Return -1 if an error occurred. */
1633 __gnat_dup (int oldfd
)
1635 #if defined (__vxworks)
1636 /* Not supported on VxWorks. */
1643 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
1644 Return -1 if an error occured. */
1647 __gnat_dup2 (int oldfd
, int newfd
)
1649 #if defined (__vxworks)
1650 /* Not supported on VxWorks. */
1653 return dup2 (oldfd
, newfd
);
1657 /* WIN32 code to implement a wait call that wait for any child process. */
1661 /* Synchronization code, to be thread safe. */
1663 static CRITICAL_SECTION plist_cs
;
1666 __gnat_plist_init (void)
1668 InitializeCriticalSection (&plist_cs
);
1674 EnterCriticalSection (&plist_cs
);
1680 LeaveCriticalSection (&plist_cs
);
1683 typedef struct _process_list
1686 struct _process_list
*next
;
1689 static Process_List
*PLIST
= NULL
;
1691 static int plist_length
= 0;
1694 add_handle (HANDLE h
)
1698 pl
= (Process_List
*) xmalloc (sizeof (Process_List
));
1702 /* -------------------- critical section -------------------- */
1707 /* -------------------- critical section -------------------- */
1713 remove_handle (HANDLE h
)
1716 Process_List
*prev
= NULL
;
1720 /* -------------------- critical section -------------------- */
1729 prev
->next
= pl
->next
;
1741 /* -------------------- critical section -------------------- */
1747 win32_no_block_spawn (char *command
, char *args
[])
1751 PROCESS_INFORMATION PI
;
1752 SECURITY_ATTRIBUTES SA
;
1757 /* compute the total command line length */
1761 csize
+= strlen (args
[k
]) + 1;
1765 full_command
= (char *) xmalloc (csize
);
1768 SI
.cb
= sizeof (STARTUPINFO
);
1769 SI
.lpReserved
= NULL
;
1770 SI
.lpReserved2
= NULL
;
1771 SI
.lpDesktop
= NULL
;
1775 SI
.wShowWindow
= SW_HIDE
;
1777 /* Security attributes. */
1778 SA
.nLength
= sizeof (SECURITY_ATTRIBUTES
);
1779 SA
.bInheritHandle
= TRUE
;
1780 SA
.lpSecurityDescriptor
= NULL
;
1782 /* Prepare the command string. */
1783 strcpy (full_command
, command
);
1784 strcat (full_command
, " ");
1789 strcat (full_command
, args
[k
]);
1790 strcat (full_command
, " ");
1794 result
= CreateProcess
1795 (NULL
, (char *) full_command
, &SA
, NULL
, TRUE
,
1796 GetPriorityClass (GetCurrentProcess()), NULL
, NULL
, &SI
, &PI
);
1798 free (full_command
);
1802 add_handle (PI
.hProcess
);
1803 CloseHandle (PI
.hThread
);
1804 return (int) PI
.hProcess
;
1811 win32_wait (int *status
)
1820 if (plist_length
== 0)
1826 hl
= (HANDLE
*) xmalloc (sizeof (HANDLE
) * plist_length
);
1831 /* -------------------- critical section -------------------- */
1838 /* -------------------- critical section -------------------- */
1842 res
= WaitForMultipleObjects (plist_length
, hl
, FALSE
, INFINITE
);
1843 h
= hl
[res
- WAIT_OBJECT_0
];
1848 GetExitCodeProcess (h
, &exitcode
);
1851 *status
= (int) exitcode
;
1858 __gnat_portable_no_block_spawn (char *args
[])
1862 #if defined (__EMX__) || defined (MSDOS)
1864 /* ??? For PC machines I (Franco) don't know the system calls to implement
1865 this routine. So I'll fake it as follows. This routine will behave
1866 exactly like the blocking portable_spawn and will systematically return
1867 a pid of 0 unless the spawned task did not complete successfully, in
1868 which case we return a pid of -1. To synchronize with this the
1869 portable_wait below systematically returns a pid of 0 and reports that
1870 the subprocess terminated successfully. */
1872 if (spawnvp (P_WAIT
, args
[0], args
) != 0)
1875 #elif defined (_WIN32)
1877 pid
= win32_no_block_spawn (args
[0], args
);
1880 #elif defined (__vxworks)
1889 if (execv (args
[0], MAYBE_TO_PTR32 (args
)) != 0)
1891 return -1; /* execv is in parent context on VMS. */
1903 __gnat_portable_wait (int *process_status
)
1908 #if defined (_WIN32)
1910 pid
= win32_wait (&status
);
1912 #elif defined (__EMX__) || defined (MSDOS)
1913 /* ??? See corresponding comment in portable_no_block_spawn. */
1915 #elif defined (__vxworks)
1916 /* Not sure what to do here, so do same as __EMX__ case, i.e., nothing but
1920 pid
= waitpid (-1, &status
, 0);
1921 status
= status
& 0xffff;
1924 *process_status
= status
;
1929 __gnat_waitpid (int pid
)
1933 #if defined (_WIN32)
1934 cwait (&status
, pid
, _WAIT_CHILD
);
1935 #elif defined (__EMX__) || defined (MSDOS) || defined (__vxworks)
1936 /* Status is already zero, so nothing to do. */
1938 waitpid (pid
, &status
, 0);
1939 status
= WEXITSTATUS (status
);
1946 __gnat_os_exit (int status
)
1951 /* Locate a regular file, give a Path value. */
1954 __gnat_locate_regular_file (char *file_name
, char *path_val
)
1957 int absolute
= __gnat_is_absolute_path (file_name
, strlen (file_name
));
1959 /* Handle absolute pathnames. */
1962 if (__gnat_is_regular_file (file_name
))
1963 return xstrdup (file_name
);
1968 /* If file_name include directory separator(s), try it first as
1969 a path name relative to the current directory */
1970 for (ptr
= file_name
; *ptr
&& *ptr
!= '/' && *ptr
!= DIR_SEPARATOR
; ptr
++)
1975 if (__gnat_is_regular_file (file_name
))
1976 return xstrdup (file_name
);
1983 /* The result has to be smaller than path_val + file_name. */
1984 char *file_path
= alloca (strlen (path_val
) + strlen (file_name
) + 2);
1988 for (; *path_val
== PATH_SEPARATOR
; path_val
++)
1994 for (ptr
= file_path
; *path_val
&& *path_val
!= PATH_SEPARATOR
; )
1995 *ptr
++ = *path_val
++;
1998 if (*ptr
!= '/' && *ptr
!= DIR_SEPARATOR
)
1999 *++ptr
= DIR_SEPARATOR
;
2001 strcpy (++ptr
, file_name
);
2003 if (__gnat_is_regular_file (file_path
))
2004 return xstrdup (file_path
);
2011 /* Locate an executable given a Path argument. This routine is only used by
2012 gnatbl and should not be used otherwise. Use locate_exec_on_path
2016 __gnat_locate_exec (char *exec_name
, char *path_val
)
2018 if (!strstr (exec_name
, HOST_EXECUTABLE_SUFFIX
))
2020 char *full_exec_name
2021 = alloca (strlen (exec_name
) + strlen (HOST_EXECUTABLE_SUFFIX
) + 1);
2023 strcpy (full_exec_name
, exec_name
);
2024 strcat (full_exec_name
, HOST_EXECUTABLE_SUFFIX
);
2025 return __gnat_locate_regular_file (full_exec_name
, path_val
);
2028 return __gnat_locate_regular_file (exec_name
, path_val
);
2031 /* Locate an executable using the Systems default PATH. */
2034 __gnat_locate_exec_on_path (char *exec_name
)
2038 char *path_val
= "/VAXC$PATH";
2040 char *path_val
= getenv ("PATH");
2043 /* In Win32 systems we expand the PATH as for XP environment
2044 variables are not automatically expanded. */
2045 int len
= strlen (path_val
) * 3;
2046 char *expanded_path_val
= alloca (len
+ 1);
2048 DWORD res
= ExpandEnvironmentStrings (path_val
, expanded_path_val
, len
);
2052 path_val
= expanded_path_val
;
2056 apath_val
= alloca (strlen (path_val
) + 1);
2057 strcpy (apath_val
, path_val
);
2059 return __gnat_locate_exec (exec_name
, apath_val
);
2064 /* These functions are used to translate to and from VMS and Unix syntax
2065 file, directory and path specifications. */
2068 #define MAXNAMES 256
2069 #define NEW_CANONICAL_FILELIST_INCREMENT 64
2071 static char new_canonical_dirspec
[MAXPATH
];
2072 static char new_canonical_filespec
[MAXPATH
];
2073 static char new_canonical_pathspec
[MAXNAMES
*MAXPATH
];
2074 static unsigned new_canonical_filelist_index
;
2075 static unsigned new_canonical_filelist_in_use
;
2076 static unsigned new_canonical_filelist_allocated
;
2077 static char **new_canonical_filelist
;
2078 static char new_host_pathspec
[MAXNAMES
*MAXPATH
];
2079 static char new_host_dirspec
[MAXPATH
];
2080 static char new_host_filespec
[MAXPATH
];
2082 /* Routine is called repeatedly by decc$from_vms via
2083 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2087 wildcard_translate_unix (char *name
)
2090 char buff
[MAXPATH
];
2092 strncpy (buff
, name
, MAXPATH
);
2093 buff
[MAXPATH
- 1] = (char) 0;
2094 ver
= strrchr (buff
, '.');
2096 /* Chop off the version. */
2100 /* Dynamically extend the allocation by the increment. */
2101 if (new_canonical_filelist_in_use
== new_canonical_filelist_allocated
)
2103 new_canonical_filelist_allocated
+= NEW_CANONICAL_FILELIST_INCREMENT
;
2104 new_canonical_filelist
= (char **) xrealloc
2105 (new_canonical_filelist
,
2106 new_canonical_filelist_allocated
* sizeof (char *));
2109 new_canonical_filelist
[new_canonical_filelist_in_use
++] = xstrdup (buff
);
2114 /* Translate a wildcard VMS file spec into a list of Unix file specs. First do
2115 full translation and copy the results into a list (_init), then return them
2116 one at a time (_next). If onlydirs set, only expand directory files. */
2119 __gnat_to_canonical_file_list_init (char *filespec
, int onlydirs
)
2122 char buff
[MAXPATH
];
2124 len
= strlen (filespec
);
2125 strncpy (buff
, filespec
, MAXPATH
);
2127 /* Only look for directories */
2128 if (onlydirs
&& !strstr (&buff
[len
-5], "*.dir"))
2129 strncat (buff
, "*.dir", MAXPATH
);
2131 buff
[MAXPATH
- 1] = (char) 0;
2133 decc$
from_vms (buff
, wildcard_translate_unix
, 1);
2135 /* Remove the .dir extension. */
2141 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2143 ext
= strstr (new_canonical_filelist
[i
], ".dir");
2149 return new_canonical_filelist_in_use
;
2152 /* Return the next filespec in the list. */
2155 __gnat_to_canonical_file_list_next ()
2157 return new_canonical_filelist
[new_canonical_filelist_index
++];
2160 /* Free storage used in the wildcard expansion. */
2163 __gnat_to_canonical_file_list_free ()
2167 for (i
= 0; i
< new_canonical_filelist_in_use
; i
++)
2168 free (new_canonical_filelist
[i
]);
2170 free (new_canonical_filelist
);
2172 new_canonical_filelist_in_use
= 0;
2173 new_canonical_filelist_allocated
= 0;
2174 new_canonical_filelist_index
= 0;
2175 new_canonical_filelist
= 0;
2178 /* Translate a VMS syntax directory specification in to Unix syntax. If
2179 PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
2180 found, return input string. Also translate a dirname that contains no
2181 slashes, in case it's a logical name. */
2184 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag
)
2188 strcpy (new_canonical_dirspec
, "");
2189 if (strlen (dirspec
))
2193 if (strchr (dirspec
, ']') || strchr (dirspec
, ':'))
2195 strncpy (new_canonical_dirspec
,
2196 (char *) decc$
translate_vms (dirspec
),
2199 else if (!strchr (dirspec
, '/') && (dirspec1
= getenv (dirspec
)) != 0)
2201 strncpy (new_canonical_dirspec
,
2202 (char *) decc$
translate_vms (dirspec1
),
2207 strncpy (new_canonical_dirspec
, dirspec
, MAXPATH
);
2211 len
= strlen (new_canonical_dirspec
);
2212 if (prefixflag
&& new_canonical_dirspec
[len
-1] != '/')
2213 strncat (new_canonical_dirspec
, "/", MAXPATH
);
2215 new_canonical_dirspec
[MAXPATH
- 1] = (char) 0;
2217 return new_canonical_dirspec
;
2221 /* Translate a VMS syntax file specification into Unix syntax.
2222 If no indicators of VMS syntax found, return input string. */
2225 __gnat_to_canonical_file_spec (char *filespec
)
2227 strncpy (new_canonical_filespec
, "", MAXPATH
);
2229 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
2231 strncpy (new_canonical_filespec
,
2232 (char *) decc$
translate_vms (filespec
),
2237 strncpy (new_canonical_filespec
, filespec
, MAXPATH
);
2240 new_canonical_filespec
[MAXPATH
- 1] = (char) 0;
2242 return new_canonical_filespec
;
2245 /* Translate a VMS syntax path specification into Unix syntax.
2246 If no indicators of VMS syntax found, return input string. */
2249 __gnat_to_canonical_path_spec (char *pathspec
)
2251 char *curr
, *next
, buff
[MAXPATH
];
2256 /* If there are /'s, assume it's a Unix path spec and return. */
2257 if (strchr (pathspec
, '/'))
2260 new_canonical_pathspec
[0] = 0;
2265 next
= strchr (curr
, ',');
2267 next
= strchr (curr
, 0);
2269 strncpy (buff
, curr
, next
- curr
);
2270 buff
[next
- curr
] = 0;
2272 /* Check for wildcards and expand if present. */
2273 if (strchr (buff
, '*') || strchr (buff
, '%') || strstr (buff
, "..."))
2277 dirs
= __gnat_to_canonical_file_list_init (buff
, 1);
2278 for (i
= 0; i
< dirs
; i
++)
2282 next_dir
= __gnat_to_canonical_file_list_next ();
2283 strncat (new_canonical_pathspec
, next_dir
, MAXPATH
);
2285 /* Don't append the separator after the last expansion. */
2287 strncat (new_canonical_pathspec
, ":", MAXPATH
);
2290 __gnat_to_canonical_file_list_free ();
2293 strncat (new_canonical_pathspec
,
2294 __gnat_to_canonical_dir_spec (buff
, 0), MAXPATH
);
2299 strncat (new_canonical_pathspec
, ":", MAXPATH
);
2303 new_canonical_pathspec
[MAXPATH
- 1] = (char) 0;
2305 return new_canonical_pathspec
;
2308 static char filename_buff
[MAXPATH
];
2311 translate_unix (char *name
, int type
)
2313 strncpy (filename_buff
, name
, MAXPATH
);
2314 filename_buff
[MAXPATH
- 1] = (char) 0;
2318 /* Translate a Unix syntax path spec into a VMS style (comma separated list of
2322 to_host_path_spec (char *pathspec
)
2324 char *curr
, *next
, buff
[MAXPATH
];
2329 /* Can't very well test for colons, since that's the Unix separator! */
2330 if (strchr (pathspec
, ']') || strchr (pathspec
, ','))
2333 new_host_pathspec
[0] = 0;
2338 next
= strchr (curr
, ':');
2340 next
= strchr (curr
, 0);
2342 strncpy (buff
, curr
, next
- curr
);
2343 buff
[next
- curr
] = 0;
2345 strncat (new_host_pathspec
, __gnat_to_host_dir_spec (buff
, 0), MAXPATH
);
2348 strncat (new_host_pathspec
, ",", MAXPATH
);
2352 new_host_pathspec
[MAXPATH
- 1] = (char) 0;
2354 return new_host_pathspec
;
2357 /* Translate a Unix syntax directory specification into VMS syntax. The
2358 PREFIXFLAG has no effect, but is kept for symmetry with
2359 to_canonical_dir_spec. If indicators of VMS syntax found, return input
2363 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2365 int len
= strlen (dirspec
);
2367 strncpy (new_host_dirspec
, dirspec
, MAXPATH
);
2368 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
2370 if (strchr (new_host_dirspec
, ']') || strchr (new_host_dirspec
, ':'))
2371 return new_host_dirspec
;
2373 while (len
> 1 && new_host_dirspec
[len
- 1] == '/')
2375 new_host_dirspec
[len
- 1] = 0;
2379 decc$
to_vms (new_host_dirspec
, translate_unix
, 1, 2);
2380 strncpy (new_host_dirspec
, filename_buff
, MAXPATH
);
2381 new_host_dirspec
[MAXPATH
- 1] = (char) 0;
2383 return new_host_dirspec
;
2386 /* Translate a Unix syntax file specification into VMS syntax.
2387 If indicators of VMS syntax found, return input string. */
2390 __gnat_to_host_file_spec (char *filespec
)
2392 strncpy (new_host_filespec
, "", MAXPATH
);
2393 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
2395 strncpy (new_host_filespec
, filespec
, MAXPATH
);
2399 decc$
to_vms (filespec
, translate_unix
, 1, 1);
2400 strncpy (new_host_filespec
, filename_buff
, MAXPATH
);
2403 new_host_filespec
[MAXPATH
- 1] = (char) 0;
2405 return new_host_filespec
;
2409 __gnat_adjust_os_resource_limits ()
2411 SYS$
ADJWSL (131072, 0);
2416 /* Dummy functions for Osint import for non-VMS systems. */
2419 __gnat_to_canonical_file_list_init
2420 (char *dirspec ATTRIBUTE_UNUSED
, int onlydirs ATTRIBUTE_UNUSED
)
2426 __gnat_to_canonical_file_list_next (void)
2432 __gnat_to_canonical_file_list_free (void)
2437 __gnat_to_canonical_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2443 __gnat_to_canonical_file_spec (char *filespec
)
2449 __gnat_to_canonical_path_spec (char *pathspec
)
2455 __gnat_to_host_dir_spec (char *dirspec
, int prefixflag ATTRIBUTE_UNUSED
)
2461 __gnat_to_host_file_spec (char *filespec
)
2467 __gnat_adjust_os_resource_limits (void)
2473 /* For EMX, we cannot include dummy in libgcc, since it is too difficult
2474 to coordinate this with the EMX distribution. Consequently, we put the
2475 definition of dummy which is used for exception handling, here. */
2477 #if defined (__EMX__)
2481 #if defined (__mips_vxworks)
2485 CACHE_USER_FLUSH (0, ENTIRE_CACHE
);
2489 #if defined (CROSS_COMPILE) \
2490 || (! (defined (sparc) && defined (sun) && defined (__SVR4)) \
2491 && ! (defined (linux) && defined (i386)) \
2492 && ! defined (__FreeBSD__) \
2493 && ! defined (__hpux__) \
2494 && ! defined (_AIX) \
2495 && ! (defined (__alpha__) && defined (__osf__)) \
2496 && ! defined (__MINGW32__) \
2497 && ! (defined (__mips) && defined (__sgi)))
2499 /* Dummy function to satisfy g-trasym.o. Currently Solaris sparc, HP/UX,
2500 GNU/Linux x86, Tru64 & Windows provide a non-dummy version of this
2501 procedure in libaddr2line.a. */
2504 convert_addresses (void *addrs ATTRIBUTE_UNUSED
,
2505 int n_addr ATTRIBUTE_UNUSED
,
2506 void *buf ATTRIBUTE_UNUSED
,
2507 int *len ATTRIBUTE_UNUSED
)
2513 #if defined (_WIN32)
2514 int __gnat_argument_needs_quote
= 1;
2516 int __gnat_argument_needs_quote
= 0;
2519 /* This option is used to enable/disable object files handling from the
2520 binder file by the GNAT Project module. For example, this is disabled on
2521 Windows (prior to GCC 3.4) as it is already done by the mdll module.
2522 Stating with GCC 3.4 the shared libraries are not based on mdll
2523 anymore as it uses the GCC's -shared option */
2524 #if defined (_WIN32) \
2525 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
2526 int __gnat_prj_add_obj_files
= 0;
2528 int __gnat_prj_add_obj_files
= 1;
2531 /* char used as prefix/suffix for environment variables */
2532 #if defined (_WIN32)
2533 char __gnat_environment_char
= '%';
2535 char __gnat_environment_char
= '$';
2538 /* This functions copy the file attributes from a source file to a
2541 mode = 0 : In this mode copy only the file time stamps (last access and
2542 last modification time stamps).
2544 mode = 1 : In this mode, time stamps and read/write/execute attributes are
2547 Returns 0 if operation was successful and -1 in case of error. */
2550 __gnat_copy_attribs (char *from
, char *to
, int mode
)
2552 #if defined (VMS) || defined (__vxworks)
2556 struct utimbuf tbuf
;
2558 if (stat (from
, &fbuf
) == -1)
2563 tbuf
.actime
= fbuf
.st_atime
;
2564 tbuf
.modtime
= fbuf
.st_mtime
;
2566 if (utime (to
, &tbuf
) == -1)
2573 if (chmod (to
, fbuf
.st_mode
) == -1)
2583 /* This function is installed in libgcc.a. */
2584 extern void __gnat_install_locks (void (*) (void), void (*) (void));
2586 /* This function offers a hook for libgnarl to set the
2587 locking subprograms for libgcc_eh.
2588 This is only needed on OpenVMS, since other platforms use standard
2589 --enable-threads=posix option, or similar. */
2592 __gnatlib_install_locks (void (*lock
) (void) ATTRIBUTE_UNUSED
,
2593 void (*unlock
) (void) ATTRIBUTE_UNUSED
)
2595 #if defined (IN_RTS) && defined (VMS)
2596 __gnat_install_locks (lock
, unlock
);
2597 /* There is a bootstrap path issue if adaint is build with this
2598 symbol unresolved for the stage1 compiler. Since the compiler
2599 does not use tasking, we simply make __gnatlib_install_locks
2600 a no-op in this case. */
2605 __gnat_lseek (int fd
, long offset
, int whence
)
2607 return (int) lseek (fd
, offset
, whence
);
2610 /* This function returns the version of GCC being used. Here it's GCC 3. */
2612 get_gcc_version (void)
2618 __gnat_set_close_on_exec (int fd
, int close_on_exec_p
)
2620 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
2621 int flags
= fcntl (fd
, F_GETFD
, 0);
2624 if (close_on_exec_p
)
2625 flags
|= FD_CLOEXEC
;
2627 flags
&= ~FD_CLOEXEC
;
2628 return fcntl (fd
, F_SETFD
, flags
| FD_CLOEXEC
);
2631 /* For the Windows case, we should use SetHandleInformation to remove
2632 the HANDLE_INHERIT property from fd. This is not implemented yet,
2633 but for our purposes (support of GNAT.Expect) this does not matter,
2634 as by default handles are *not* inherited. */