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)
82 #include <sys/utime.h>
84 #elif defined (__MINGW32__)
87 #include <sys/utime.h>
90 #elif defined (__Lynx__)
92 /* Lynx utime.h only defines the entities of interest to us if
93 defined (VMOS_DEV), so ... */
102 /* wait.h processing */
105 #include <sys/wait.h>
107 #elif defined (__vxworks) && defined (__RTP__)
109 #elif defined (__Lynx__)
110 /* ??? We really need wait.h and it includes resource.h on Lynx. GCC
111 has a resource.h header as well, included instead of the lynx
112 version in our setup, causing lots of errors. We don't really need
113 the lynx contents of this file, so just workaround the issue by
114 preventing the inclusion of the GCC header from doing anything. */
115 #define GCC_RESOURCE_H
116 #include <sys/wait.h>
117 #elif defined (__nucleus__)
118 /* No wait() or waitpid() calls available */
121 #include <sys/wait.h>
124 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
127 /* Header files and definitions for __gnat_set_file_time_name. */
129 #define __NEW_STARLET 1
131 #include <vms/atrdef.h>
132 #include <vms/fibdef.h>
133 #include <vms/stsdef.h>
134 #include <vms/iodef.h>
136 #include <vms/descrip.h>
140 /* Use native 64-bit arithmetic. */
141 #define unix_time_to_vms(X,Y) \
142 { unsigned long long reftime, tmptime = (X); \
143 $DESCRIPTOR (unixtime,"1-JAN-1970 0:00:00.00"); \
144 SYS$BINTIM (&unixtime, &reftime); \
145 Y = tmptime * 10000000 + reftime; }
147 /* descrip.h doesn't have everything ... */
148 typedef struct fibdef* __fibdef_ptr32 __attribute__ (( mode (SI) ));
149 struct dsc$descriptor_fib
151 unsigned int fib$l_len;
152 __fibdef_ptr32 fib$l_addr;
155 /* I/O Status Block. */
158 unsigned short status, count;
162 static char *tryfile;
164 /* Variable length string. */
168 char string[NAM$C_MAXRSS+1];
175 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
183 #define DIR_SEPARATOR '\\'
188 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
189 defined in the current system. On DOS-like systems these flags control
190 whether the file is opened/created in text-translation mode (CR/LF in
191 external file mapped to LF in internal file), but in Unix-like systems,
192 no text translation is required, so these flags have no effect. */
194 #if defined (__EMX__)
210 #ifndef HOST_EXECUTABLE_SUFFIX
211 #define HOST_EXECUTABLE_SUFFIX ""
214 #ifndef HOST_OBJECT_SUFFIX
215 #define HOST_OBJECT_SUFFIX ".o"
218 #ifndef PATH_SEPARATOR
219 #define PATH_SEPARATOR ':'
222 #ifndef DIR_SEPARATOR
223 #define DIR_SEPARATOR '/'
226 /* Check for cross-compilation */
227 #ifdef CROSS_DIRECTORY_STRUCTURE
228 int __gnat_is_cross_compiler = 1;
230 int __gnat_is_cross_compiler = 0;
233 char __gnat_dir_separator = DIR_SEPARATOR;
235 char __gnat_path_separator = PATH_SEPARATOR;
237 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
238 the base filenames that libraries specified with -lsomelib options
239 may have. This is used by GNATMAKE to check whether an executable
240 is up-to-date or not. The syntax is
242 library_template ::= { pattern ; } pattern NUL
243 pattern ::= [ prefix ] * [ postfix ]
245 These should only specify names of static libraries as it makes
246 no sense to determine at link time if dynamic-link libraries are
247 up to date or not. Any libraries that are not found are supposed
250 * if they are needed but not present, the link
253 * otherwise they are libraries in the system paths and so
254 they are considered part of the system and not checked
257 ??? This should be part of a GNAT host-specific compiler
258 file instead of being included in all user applications
259 as well. This is only a temporary work-around for 3.11b. */
261 #ifndef GNAT_LIBRARY_TEMPLATE
262 #if defined (__EMX__)
263 #define GNAT_LIBRARY_TEMPLATE "*.a"
265 #define GNAT_LIBRARY_TEMPLATE "*.olb"
267 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
271 const char *__gnat_library_template = GNAT_LIBRARY_TEMPLATE;
273 /* This variable is used in hostparm.ads to say whether the host is a VMS
276 const int __gnat_vmsp = 1;
278 const int __gnat_vmsp = 0;
282 #define GNAT_MAX_PATH_LEN MAX_PATH
285 #define GNAT_MAX_PATH_LEN 256 /* PATH_MAX */
287 #elif defined (__vxworks) || defined (__OPENNT) || defined(__nucleus__)
288 #define GNAT_MAX_PATH_LEN PATH_MAX
292 #if defined (__MINGW32__)
296 #include <sys/param.h>
300 #include <sys/param.h>
304 #define GNAT_MAX_PATH_LEN MAXPATHLEN
306 #define GNAT_MAX_PATH_LEN 256
311 /* The __gnat_max_path_len variable is used to export the maximum
312 length of a path name to Ada code. max_path_len is also provided
313 for compatibility with older GNAT versions, please do not use
316 int __gnat_max_path_len = GNAT_MAX_PATH_LEN;
317 int max_path_len = GNAT_MAX_PATH_LEN;
319 /* The following macro HAVE_READDIR_R should be defined if the
320 system provides the routine readdir_r. */
321 #undef HAVE_READDIR_R
323 #if defined(VMS) && defined (__LONG_POINTERS)
325 /* Return a 32 bit pointer to an array of 32 bit pointers
326 given a 64 bit pointer to an array of 64 bit pointers */
328 typedef __char_ptr32 *__char_ptr_char_ptr32 __attribute__ ((mode (SI)));
330 static __char_ptr_char_ptr32
331 to_ptr32 (char **ptr64)
334 __char_ptr_char_ptr32 short_argv;
336 for (argc=0; ptr64[argc]; argc++);
338 /* Reallocate argv with 32 bit pointers. */
339 short_argv = (__char_ptr_char_ptr32) decc$malloc
340 (sizeof (__char_ptr32) * (argc + 1));
342 for (argc=0; ptr64[argc]; argc++)
343 short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]);
345 short_argv[argc] = (__char_ptr32) 0;
349 #define MAYBE_TO_PTR32(argv) to_ptr32 (argv)
351 #define MAYBE_TO_PTR32(argv) argv
358 time_t res = time (NULL);
359 return (OS_Time) res;
373 time_t time = (time_t) *p_time;
376 /* On Windows systems, the time is sometimes rounded up to the nearest
377 even second, so if the number of seconds is odd, increment it. */
383 res = localtime (&time);
385 res = gmtime (&time);
390 *p_year = res->tm_year;
391 *p_month = res->tm_mon;
392 *p_day = res->tm_mday;
393 *p_hours = res->tm_hour;
394 *p_mins = res->tm_min;
395 *p_secs = res->tm_sec;
398 *p_year = *p_month = *p_day = *p_hours = *p_mins = *p_secs = 0;
401 /* Place the contents of the symbolic link named PATH in the buffer BUF,
402 which has size BUFSIZ. If PATH is a symbolic link, then return the number
403 of characters of its content in BUF. Otherwise, return -1.
404 For systems not supporting symbolic links, always return -1. */
407 __gnat_readlink (char *path ATTRIBUTE_UNUSED,
408 char *buf ATTRIBUTE_UNUSED,
409 size_t bufsiz ATTRIBUTE_UNUSED)
411 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__) \
412 || defined (VMS) || defined(__vxworks) || defined (__nucleus__)
415 return readlink (path, buf, bufsiz);
419 /* Creates a symbolic link named NEWPATH which contains the string OLDPATH.
420 If NEWPATH exists it will NOT be overwritten.
421 For systems not supporting symbolic links, always return -1. */
424 __gnat_symlink (char *oldpath ATTRIBUTE_UNUSED,
425 char *newpath ATTRIBUTE_UNUSED)
427 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__) \
428 || defined (VMS) || defined(__vxworks) || defined (__nucleus__)
431 return symlink (oldpath, newpath);
435 /* Try to lock a file, return 1 if success. */
437 #if defined (__vxworks) || defined (__nucleus__) || defined (MSDOS) || defined (_WIN32)
439 /* Version that does not use link. */
442 __gnat_try_lock (char *dir, char *file)
446 TCHAR wfull_path[GNAT_MAX_PATH_LEN];
447 TCHAR wfile[GNAT_MAX_PATH_LEN];
448 TCHAR wdir[GNAT_MAX_PATH_LEN];
450 S2WSU (wdir, dir, GNAT_MAX_PATH_LEN);
451 S2WSU (wfile, file, GNAT_MAX_PATH_LEN);
453 _stprintf (wfull_path, _T("%s%c%s"), wdir, _T(DIR_SEPARATOR), wfile);
454 fd = _topen (wfull_path, O_CREAT | O_EXCL, 0600);
458 sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
459 fd = open (full_path, O_CREAT | O_EXCL, 0600);
469 #elif defined (__EMX__) || defined (VMS)
471 /* More cases that do not use link; identical code, to solve too long
475 __gnat_try_lock (char *dir, char *file)
480 sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
481 fd = open (full_path, O_CREAT | O_EXCL, 0600);
492 /* Version using link(), more secure over NFS. */
493 /* See TN 6913-016 for discussion ??? */
496 __gnat_try_lock (char *dir, char *file)
500 struct stat stat_result;
503 sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
504 sprintf (temp_file, "%s%cTMP-%ld-%ld",
505 dir, DIR_SEPARATOR, (long)getpid(), (long)getppid ());
507 /* Create the temporary file and write the process number. */
508 fd = open (temp_file, O_CREAT | O_WRONLY, 0600);
514 /* Link it with the new file. */
515 link (temp_file, full_path);
517 /* Count the references on the old one. If we have a count of two, then
518 the link did succeed. Remove the temporary file before returning. */
519 __gnat_stat (temp_file, &stat_result);
521 return stat_result.st_nlink == 2;
525 /* Return the maximum file name length. */
528 __gnat_get_maximum_file_name_length (void)
533 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
542 /* Return nonzero if file names are case sensitive. */
545 __gnat_get_file_names_case_sensitive (void)
547 #if defined (__EMX__) || defined (MSDOS) || defined (VMS) || defined (WINNT)
555 __gnat_get_default_identifier_character_set (void)
557 #if defined (__EMX__) || defined (MSDOS)
564 /* Return the current working directory. */
567 __gnat_get_current_dir (char *dir, int *length)
569 #if defined (__MINGW32__)
570 TCHAR wdir[GNAT_MAX_PATH_LEN];
572 _tgetcwd (wdir, *length);
574 WS2SU (dir, wdir, GNAT_MAX_PATH_LEN);
577 /* Force Unix style, which is what GNAT uses internally. */
578 getcwd (dir, *length, 0);
580 getcwd (dir, *length);
583 *length = strlen (dir);
585 if (dir [*length - 1] != DIR_SEPARATOR)
587 dir [*length] = DIR_SEPARATOR;
593 /* Return the suffix for object files. */
596 __gnat_get_object_suffix_ptr (int *len, const char **value)
598 *value = HOST_OBJECT_SUFFIX;
603 *len = strlen (*value);
608 /* Return the suffix for executable files. */
611 __gnat_get_executable_suffix_ptr (int *len, const char **value)
613 *value = HOST_EXECUTABLE_SUFFIX;
617 *len = strlen (*value);
622 /* Return the suffix for debuggable files. Usually this is the same as the
623 executable extension. */
626 __gnat_get_debuggable_suffix_ptr (int *len, const char **value)
629 *value = HOST_EXECUTABLE_SUFFIX;
631 /* On DOS, the extensionless COFF file is what gdb likes. */
638 *len = strlen (*value);
643 /* Returns the OS filename and corresponding encoding. */
646 __gnat_os_filename (char *filename, char *w_filename ATTRIBUTE_UNUSED,
647 char *os_name, int *o_length,
648 char *encoding ATTRIBUTE_UNUSED, int *e_length)
650 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
651 WS2SU (os_name, (TCHAR *)w_filename, o_length);
652 *o_length = strlen (os_name);
653 strcpy (encoding, "encoding=utf8");
654 *e_length = strlen (encoding);
656 strcpy (os_name, filename);
657 *o_length = strlen (filename);
663 __gnat_fopen (char *path, char *mode, int encoding ATTRIBUTE_UNUSED)
665 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
666 TCHAR wpath[GNAT_MAX_PATH_LEN];
669 S2WS (wmode, mode, 10);
671 if (encoding == Encoding_UTF8)
672 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
674 S2WS (wpath, path, GNAT_MAX_PATH_LEN);
676 return _tfopen (wpath, wmode);
678 return decc$fopen (path, mode);
680 return fopen (path, mode);
685 __gnat_freopen (char *path, char *mode, FILE *stream, int encoding ATTRIBUTE_UNUSED)
687 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE)
688 TCHAR wpath[GNAT_MAX_PATH_LEN];
691 S2WS (wmode, mode, 10);
693 if (encoding == Encoding_UTF8)
694 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
696 S2WS (wpath, path, GNAT_MAX_PATH_LEN);
698 return _tfreopen (wpath, wmode, stream);
700 return decc$freopen (path, mode, stream);
702 return freopen (path, mode, stream);
707 __gnat_open_read (char *path, int fmode)
710 int o_fmode = O_BINARY;
716 /* Optional arguments mbc,deq,fop increase read performance. */
717 fd = open (path, O_RDONLY | o_fmode, 0444,
718 "mbc=16", "deq=64", "fop=tef");
719 #elif defined (__vxworks)
720 fd = open (path, O_RDONLY | o_fmode, 0444);
721 #elif defined (__MINGW32__)
723 TCHAR wpath[GNAT_MAX_PATH_LEN];
725 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
726 fd = _topen (wpath, O_RDONLY | o_fmode, 0444);
729 fd = open (path, O_RDONLY | o_fmode);
732 return fd < 0 ? -1 : fd;
735 #if defined (__EMX__) || defined (__MINGW32__)
736 #define PERM (S_IREAD | S_IWRITE)
738 /* Excerpt from DECC C RTL Reference Manual:
739 To create files with OpenVMS RMS default protections using the UNIX
740 system-call functions umask, mkdir, creat, and open, call mkdir, creat,
741 and open with a file-protection mode argument of 0777 in a program
742 that never specifically calls umask. These default protections include
743 correctly establishing protections based on ACLs, previous versions of
747 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
751 __gnat_open_rw (char *path, int fmode)
754 int o_fmode = O_BINARY;
760 fd = open (path, O_RDWR | o_fmode, PERM,
761 "mbc=16", "deq=64", "fop=tef");
762 #elif defined (__MINGW32__)
764 TCHAR wpath[GNAT_MAX_PATH_LEN];
766 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
767 fd = _topen (wpath, O_RDWR | o_fmode, PERM);
770 fd = open (path, O_RDWR | o_fmode, PERM);
773 return fd < 0 ? -1 : fd;
777 __gnat_open_create (char *path, int fmode)
780 int o_fmode = O_BINARY;
786 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM,
787 "mbc=16", "deq=64", "fop=tef");
788 #elif defined (__MINGW32__)
790 TCHAR wpath[GNAT_MAX_PATH_LEN];
792 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
793 fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
796 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
799 return fd < 0 ? -1 : fd;
803 __gnat_create_output_file (char *path)
807 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM,
808 "rfm=stmlf", "ctx=rec", "rat=none", "rop=nlk",
809 "shr=del,get,put,upd");
810 #elif defined (__MINGW32__)
812 TCHAR wpath[GNAT_MAX_PATH_LEN];
814 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
815 fd = _topen (wpath, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
818 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
821 return fd < 0 ? -1 : fd;
825 __gnat_open_append (char *path, int fmode)
828 int o_fmode = O_BINARY;
834 fd = open (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM,
835 "mbc=16", "deq=64", "fop=tef");
836 #elif defined (__MINGW32__)
838 TCHAR wpath[GNAT_MAX_PATH_LEN];
840 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
841 fd = _topen (wpath, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
844 fd = open (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
847 return fd < 0 ? -1 : fd;
850 /* Open a new file. Return error (-1) if the file already exists. */
853 __gnat_open_new (char *path, int fmode)
856 int o_fmode = O_BINARY;
862 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM,
863 "mbc=16", "deq=64", "fop=tef");
864 #elif defined (__MINGW32__)
866 TCHAR wpath[GNAT_MAX_PATH_LEN];
868 S2WSU (wpath, path, GNAT_MAX_PATH_LEN);
869 fd = _topen (wpath, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
872 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
875 return fd < 0 ? -1 : fd;
878 /* Open a new temp file. Return error (-1) if the file already exists.
879 Special options for VMS allow the file to be shared between parent and child
880 processes, however they really slow down output. Used in gnatchop. */
883 __gnat_open_new_temp (char *path, int fmode)
886 int o_fmode = O_BINARY;
888 strcpy (path, "GNAT-XXXXXX");
890 #if (defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__) \
891 || defined (linux)) && !defined (__vxworks)
892 return mkstemp (path);
893 #elif defined (__Lynx__)
895 #elif defined (__nucleus__)
898 if (mktemp (path) == NULL)
906 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM,
907 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
908 "mbc=16", "deq=64", "fop=tef");
910 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
913 return fd < 0 ? -1 : fd;
916 /* Return the number of bytes in the specified file. */
919 __gnat_file_length (int fd)
924 ret = fstat (fd, &statbuf);
925 if (ret || !S_ISREG (statbuf.st_mode))
928 return (statbuf.st_size);
931 /* Return the number of bytes in the specified named file. */
934 __gnat_named_file_length (char *name)
939 ret = __gnat_stat (name, &statbuf);
940 if (ret || !S_ISREG (statbuf.st_mode))
943 return (statbuf.st_size);
946 /* Create a temporary filename and put it in string pointed to by
950 __gnat_tmp_name (char *tmp_filename)
956 /* tempnam tries to create a temporary file in directory pointed to by
957 TMP environment variable, in c:\temp if TMP is not set, and in
958 directory specified by P_tmpdir in stdio.h if c:\temp does not
959 exist. The filename will be created with the prefix "gnat-". */
961 pname = (char *) tempnam ("c:\\temp", "gnat-");
963 /* if pname is NULL, the file was not created properly, the disk is full
964 or there is no more free temporary files */
967 *tmp_filename = '\0';
969 /* If pname start with a back slash and not path information it means that
970 the filename is valid for the current working directory. */
972 else if (pname[0] == '\\')
974 strcpy (tmp_filename, ".\\");
975 strcat (tmp_filename, pname+1);
978 strcpy (tmp_filename, pname);
983 #elif defined (linux) || defined (__FreeBSD__) || defined (__NetBSD__) \
984 || defined (__OpenBSD__)
985 #define MAX_SAFE_PATH 1000
986 char *tmpdir = getenv ("TMPDIR");
988 /* If tmpdir is longer than MAX_SAFE_PATH, revert to default value to avoid
989 a buffer overflow. */
990 if (tmpdir == NULL || strlen (tmpdir) > MAX_SAFE_PATH)
991 strcpy (tmp_filename, "/tmp/gnat-XXXXXX");
993 sprintf (tmp_filename, "%s/gnat-XXXXXX", tmpdir);
995 close (mkstemp(tmp_filename));
997 tmpnam (tmp_filename);
1001 /* Open directory and returns a DIR pointer. */
1003 DIR* __gnat_opendir (char *name)
1006 /* Not supported in RTX */
1010 #elif defined (__MINGW32__)
1011 TCHAR wname[GNAT_MAX_PATH_LEN];
1013 S2WSU (wname, name, GNAT_MAX_PATH_LEN);
1014 return (DIR*)_topendir (wname);
1017 return opendir (name);
1021 /* Read the next entry in a directory. The returned string points somewhere
1025 __gnat_readdir (DIR *dirp, char *buffer, int *len)
1028 /* Not supported in RTX */
1031 #elif defined (__MINGW32__)
1032 struct _tdirent *dirent = _treaddir ((_TDIR*)dirp);
1036 WS2SU (buffer, dirent->d_name, GNAT_MAX_PATH_LEN);
1037 *len = strlen (buffer);
1044 #elif defined (HAVE_READDIR_R)
1045 /* If possible, try to use the thread-safe version. */
1046 if (readdir_r (dirp, buffer) != NULL)
1048 *len = strlen (((struct dirent*) buffer)->d_name);
1049 return ((struct dirent*) buffer)->d_name;
1055 struct dirent *dirent = (struct dirent *) readdir (dirp);
1059 strcpy (buffer, dirent->d_name);
1060 *len = strlen (buffer);
1069 /* Close a directory entry. */
1071 int __gnat_closedir (DIR *dirp)
1074 /* Not supported in RTX */
1078 #elif defined (__MINGW32__)
1079 return _tclosedir ((_TDIR*)dirp);
1082 return closedir (dirp);
1086 /* Returns 1 if readdir is thread safe, 0 otherwise. */
1089 __gnat_readdir_is_thread_safe (void)
1091 #ifdef HAVE_READDIR_R
1098 #if defined (_WIN32) && !defined (RTX)
1099 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970>. */
1100 static const unsigned long long w32_epoch_offset = 11644473600ULL;
1102 /* Returns the file modification timestamp using Win32 routines which are
1103 immune against daylight saving time change. It is in fact not possible to
1104 use fstat for this purpose as the DST modify the st_mtime field of the
1108 win32_filetime (HANDLE h)
1113 unsigned long long ull_time;
1116 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
1117 since <Jan 1st 1601>. This function must return the number of seconds
1118 since <Jan 1st 1970>. */
1120 if (GetFileTime (h, NULL, NULL, &t_write.ft_time))
1121 return (time_t) (t_write.ull_time / 10000000ULL - w32_epoch_offset);
1126 /* Return a GNAT time stamp given a file name. */
1129 __gnat_file_time_name (char *name)
1132 #if defined (__EMX__) || defined (MSDOS)
1133 int fd = open (name, O_RDONLY | O_BINARY);
1134 time_t ret = __gnat_file_time_fd (fd);
1136 return (OS_Time)ret;
1138 #elif defined (_WIN32) && !defined (RTX)
1140 TCHAR wname[GNAT_MAX_PATH_LEN];
1142 S2WSU (wname, name, GNAT_MAX_PATH_LEN);
1144 HANDLE h = CreateFile
1145 (wname, GENERIC_READ, FILE_SHARE_READ, 0,
1146 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
1148 if (h != INVALID_HANDLE_VALUE)
1150 ret = win32_filetime (h);
1153 return (OS_Time) ret;
1155 struct stat statbuf;
1156 if (__gnat_stat (name, &statbuf) != 0) {
1160 /* VMS has file versioning. */
1161 return (OS_Time)statbuf.st_ctime;
1163 return (OS_Time)statbuf.st_mtime;
1169 /* Return a GNAT time stamp given a file descriptor. */
1172 __gnat_file_time_fd (int fd)
1174 /* The following workaround code is due to the fact that under EMX and
1175 DJGPP fstat attempts to convert time values to GMT rather than keep the
1176 actual OS timestamp of the file. By using the OS2/DOS functions directly
1177 the GNAT timestamp are independent of this behavior, which is desired to
1178 facilitate the distribution of GNAT compiled libraries. */
1180 #if defined (__EMX__) || defined (MSDOS)
1184 int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
1185 sizeof (FILESTATUS));
1187 unsigned file_year = fs.fdateLastWrite.year;
1188 unsigned file_month = fs.fdateLastWrite.month;
1189 unsigned file_day = fs.fdateLastWrite.day;
1190 unsigned file_hour = fs.ftimeLastWrite.hours;
1191 unsigned file_min = fs.ftimeLastWrite.minutes;
1192 unsigned file_tsec = fs.ftimeLastWrite.twosecs;
1196 int ret = getftime (fd, &fs);
1198 unsigned file_year = fs.ft_year;
1199 unsigned file_month = fs.ft_month;
1200 unsigned file_day = fs.ft_day;
1201 unsigned file_hour = fs.ft_hour;
1202 unsigned file_min = fs.ft_min;
1203 unsigned file_tsec = fs.ft_tsec;
1206 /* Calculate the seconds since epoch from the time components. First count
1207 the whole days passed. The value for years returned by the DOS and OS2
1208 functions count years from 1980, so to compensate for the UNIX epoch which
1209 begins in 1970 start with 10 years worth of days and add days for each
1210 four year period since then. */
1213 int cum_days[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1214 int days_passed = 3652 + (file_year / 4) * 1461;
1215 int years_since_leap = file_year % 4;
1217 if (years_since_leap == 1)
1219 else if (years_since_leap == 2)
1221 else if (years_since_leap == 3)
1222 days_passed += 1096;
1227 days_passed += cum_days[file_month - 1];
1228 if (years_since_leap == 0 && file_year != 20 && file_month > 2)
1231 days_passed += file_day - 1;
1233 /* OK - have whole days. Multiply -- then add in other parts. */
1235 tot_secs = days_passed * 86400;
1236 tot_secs += file_hour * 3600;
1237 tot_secs += file_min * 60;
1238 tot_secs += file_tsec * 2;
1239 return (OS_Time) tot_secs;
1241 #elif defined (_WIN32) && !defined (RTX)
1242 HANDLE h = (HANDLE) _get_osfhandle (fd);
1243 time_t ret = win32_filetime (h);
1244 return (OS_Time) ret;
1247 struct stat statbuf;
1249 if (fstat (fd, &statbuf) != 0) {
1250 return (OS_Time) -1;
1253 /* VMS has file versioning. */
1254 return (OS_Time) statbuf.st_ctime;
1256 return (OS_Time) statbuf.st_mtime;
1262 /* Set the file time stamp. */
1265 __gnat_set_file_time_name (char *name, time_t time_stamp)
1267 #if defined (__EMX__) || defined (MSDOS) || defined (__vxworks)
1269 /* Code to implement __gnat_set_file_time_name for these systems. */
1271 #elif defined (_WIN32) && !defined (RTX)
1275 unsigned long long ull_time;
1277 TCHAR wname[GNAT_MAX_PATH_LEN];
1279 S2WSU (wname, name, GNAT_MAX_PATH_LEN);
1281 HANDLE h = CreateFile
1282 (wname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
1283 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
1285 if (h == INVALID_HANDLE_VALUE)
1287 /* Add number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
1288 t_write.ull_time = ((unsigned long long)time_stamp + w32_epoch_offset);
1289 /* Convert to 100 nanosecond units */
1290 t_write.ull_time *= 10000000ULL;
1292 SetFileTime(h, NULL, NULL, &t_write.ft_time);
1302 unsigned long long backup, create, expire, revise;
1306 unsigned short value;
1309 unsigned system : 4;
1315 } Fat = { 0, 0, 0, 0, 0, { 0 }};
1319 { ATR$S_CREDATE, ATR$C_CREDATE, &Fat.create },
1320 { ATR$S_REVDATE, ATR$C_REVDATE, &Fat.revise },
1321 { ATR$S_EXPDATE, ATR$C_EXPDATE, &Fat.expire },
1322 { ATR$S_BAKDATE, ATR$C_BAKDATE, &Fat.backup },
1323 { ATR$S_FPRO, ATR$C_FPRO, &Fat.prot },
1324 { ATR$S_UIC, ATR$C_UIC, &Fat.uic },
1329 struct dsc$descriptor_fib fibdsc = {sizeof (fib), (void *) &fib};
1333 unsigned long long newtime;
1334 unsigned long long revtime;
1338 struct vstring file;
1339 struct dsc$descriptor_s filedsc
1340 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) file.string};
1341 struct vstring device;
1342 struct dsc$descriptor_s devicedsc
1343 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) device.string};
1344 struct vstring timev;
1345 struct dsc$descriptor_s timedsc
1346 = {NAM$C_MAXRSS, DSC$K_DTYPE_T, DSC$K_CLASS_S, (void *) timev.string};
1347 struct vstring result;
1348 struct dsc$descriptor_s resultdsc
1349 = {NAM$C_MAXRSS, DSC$K_DTYPE_VT, DSC$K_CLASS_VS, (void *) result.string};
1351 /* Convert parameter name (a file spec) to host file form. Note that this
1352 is needed on VMS to prepare for subsequent calls to VMS RMS library
1353 routines. Note that it would not work to call __gnat_to_host_dir_spec
1354 as was done in a previous version, since this fails silently unless
1355 the feature logical DECC$EFS_CHARSET is enabled, in which case a DNF
1356 (directory not found) condition is signalled. */
1357 tryfile = (char *) __gnat_to_host_file_spec (name);
1359 /* Allocate and initialize a FAB and NAM structures. */
1363 nam.nam$l_esa = file.string;
1364 nam.nam$b_ess = NAM$C_MAXRSS;
1365 nam.nam$l_rsa = result.string;
1366 nam.nam$b_rss = NAM$C_MAXRSS;
1367 fab.fab$l_fna = tryfile;
1368 fab.fab$b_fns = strlen (tryfile);
1369 fab.fab$l_nam = &nam;
1371 /* Validate filespec syntax and device existence. */
1372 status = SYS$PARSE (&fab, 0, 0);
1373 if ((status & 1) != 1)
1374 LIB$SIGNAL (status);
1376 file.string[nam.nam$b_esl] = 0;
1378 /* Find matching filespec. */
1379 status = SYS$SEARCH (&fab, 0, 0);
1380 if ((status & 1) != 1)
1381 LIB$SIGNAL (status);
1383 file.string[nam.nam$b_esl] = 0;
1384 result.string[result.length=nam.nam$b_rsl] = 0;
1386 /* Get the device name and assign an IO channel. */
1387 strncpy (device.string, nam.nam$l_dev, nam.nam$b_dev);
1388 devicedsc.dsc$w_length = nam.nam$b_dev;
1390 status = SYS$ASSIGN (&devicedsc, &chan, 0, 0, 0);
1391 if ((status & 1) != 1)
1392 LIB$SIGNAL (status);
1394 /* Initialize the FIB and fill in the directory id field. */
1395 memset (&fib, 0, sizeof (fib));
1396 fib.fib$w_did[0] = nam.nam$w_did[0];
1397 fib.fib$w_did[1] = nam.nam$w_did[1];
1398 fib.fib$w_did[2] = nam.nam$w_did[2];
1399 fib.fib$l_acctl = 0;
1401 strcpy (file.string, (strrchr (result.string, ']') + 1));
1402 filedsc.dsc$w_length = strlen (file.string);
1403 result.string[result.length = 0] = 0;
1405 /* Open and close the file to fill in the attributes. */
1407 = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1408 &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1409 if ((status & 1) != 1)
1410 LIB$SIGNAL (status);
1411 if ((iosb.status & 1) != 1)
1412 LIB$SIGNAL (iosb.status);
1414 result.string[result.length] = 0;
1415 status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0, &fibdsc, 0, 0, 0,
1417 if ((status & 1) != 1)
1418 LIB$SIGNAL (status);
1419 if ((iosb.status & 1) != 1)
1420 LIB$SIGNAL (iosb.status);
1425 /* Set creation time to requested time. */
1426 unix_time_to_vms (time_stamp, newtime);
1428 t = time ((time_t) 0);
1430 /* Set revision time to now in local time. */
1431 unix_time_to_vms (t, revtime);
1434 /* Reopen the file, modify the times and then close. */
1435 fib.fib$l_acctl = FIB$M_WRITE;
1437 = SYS$QIOW (0, chan, IO$_ACCESS|IO$M_ACCESS, &iosb, 0, 0,
1438 &fibdsc, &filedsc, &result.length, &resultdsc, &atrlst, 0);
1439 if ((status & 1) != 1)
1440 LIB$SIGNAL (status);
1441 if ((iosb.status & 1) != 1)
1442 LIB$SIGNAL (iosb.status);
1444 Fat.create = newtime;
1445 Fat.revise = revtime;
1447 status = SYS$QIOW (0, chan, IO$_DEACCESS, &iosb, 0, 0,
1448 &fibdsc, 0, 0, 0, &atrlst, 0);
1449 if ((status & 1) != 1)
1450 LIB$SIGNAL (status);
1451 if ((iosb.status & 1) != 1)
1452 LIB$SIGNAL (iosb.status);
1454 /* Deassign the channel and exit. */
1455 status = SYS$DASSGN (chan);
1456 if ((status & 1) != 1)
1457 LIB$SIGNAL (status);
1459 struct utimbuf utimbuf;
1462 /* Set modification time to requested time. */
1463 utimbuf.modtime = time_stamp;
1465 /* Set access time to now in local time. */
1466 t = time ((time_t) 0);
1467 utimbuf.actime = mktime (localtime (&t));
1469 utime (name, &utimbuf);
1474 #include <windows.h>
1477 /* Get the list of installed standard libraries from the
1478 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
1482 __gnat_get_libraries_from_registry (void)
1484 char *result = (char *) "";
1486 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_DIRECTORY_STRUCTURE) && ! defined (RTX)
1489 DWORD name_size, value_size;
1496 /* First open the key. */
1497 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0, KEY_READ, ®_key);
1499 if (res == ERROR_SUCCESS)
1500 res = RegOpenKeyExA (reg_key, "Ada Core Technologies", 0,
1501 KEY_READ, ®_key);
1503 if (res == ERROR_SUCCESS)
1504 res = RegOpenKeyExA (reg_key, "GNAT", 0, KEY_READ, ®_key);
1506 if (res == ERROR_SUCCESS)
1507 res = RegOpenKeyExA (reg_key, "Standard Libraries", 0, KEY_READ, ®_key);
1509 /* If the key exists, read out all the values in it and concatenate them
1511 for (index = 0; res == ERROR_SUCCESS; index++)
1513 value_size = name_size = 256;
1514 res = RegEnumValueA (reg_key, index, (TCHAR*)name, &name_size, 0,
1515 &type, (LPBYTE)value, &value_size);
1517 if (res == ERROR_SUCCESS && type == REG_SZ)
1519 char *old_result = result;
1521 result = (char *) xmalloc (strlen (old_result) + value_size + 2);
1522 strcpy (result, old_result);
1523 strcat (result, value);
1524 strcat (result, ";");
1528 /* Remove the trailing ";". */
1530 result[strlen (result) - 1] = 0;
1537 __gnat_stat (char *name, struct stat *statbuf)
1540 /* Under Windows the directory name for the stat function must not be
1541 terminated by a directory separator except if just after a drive name. */
1542 TCHAR wname [GNAT_MAX_PATH_LEN + 2];
1546 S2WSU (wname, name, GNAT_MAX_PATH_LEN + 2);
1547 name_len = _tcslen (wname);
1549 if (name_len > GNAT_MAX_PATH_LEN)
1552 last_char = wname[name_len - 1];
1554 while (name_len > 1 && (last_char == _T('\\') || last_char == _T('/')))
1556 wname[name_len - 1] = _T('\0');
1558 last_char = wname[name_len - 1];
1561 /* Only a drive letter followed by ':', we must add a directory separator
1562 for the stat routine to work properly. */
1563 if (name_len == 2 && wname[1] == _T(':'))
1564 _tcscat (wname, _T("\\"));
1566 return _tstat (wname, statbuf);
1569 return stat (name, statbuf);
1574 __gnat_file_exists (char *name)
1576 #if defined (__MINGW32__) && !defined (RTX)
1577 /* On Windows do not use __gnat_stat() because a bug in Microsoft
1578 _stat() routine. When the system time-zone is set with a negative
1579 offset the _stat() routine fails on specific files like CON: */
1580 TCHAR wname [GNAT_MAX_PATH_LEN + 2];
1582 S2WSU (wname, name, GNAT_MAX_PATH_LEN + 2);
1583 return GetFileAttributes (wname) != INVALID_FILE_ATTRIBUTES;
1585 struct stat statbuf;
1587 return !__gnat_stat (name, &statbuf);
1592 __gnat_is_absolute_path (char *name, int length)
1595 /* On VxWorks systems, an absolute path can be represented (depending on
1596 the host platform) as either /dir/file, or device:/dir/file, or
1597 device:drive_letter:/dir/file. */
1604 for (index = 0; index < length; index++)
1606 if (name[index] == ':' &&
1607 ((name[index + 1] == '/') ||
1608 (isalpha (name[index + 1]) && index + 2 <= length &&
1609 name[index + 2] == '/')))
1612 else if (name[index] == '/')
1617 return (length != 0) &&
1618 (*name == '/' || *name == DIR_SEPARATOR
1619 #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
1620 || (length > 1 && isalpha (name[0]) && name[1] == ':')
1627 __gnat_is_regular_file (char *name)
1630 struct stat statbuf;
1632 ret = __gnat_stat (name, &statbuf);
1633 return (!ret && S_ISREG (statbuf.st_mode));
1637 __gnat_is_directory (char *name)
1640 struct stat statbuf;
1642 ret = __gnat_stat (name, &statbuf);
1643 return (!ret && S_ISDIR (statbuf.st_mode));
1647 __gnat_is_readable_file (char *name)
1651 struct stat statbuf;
1653 ret = __gnat_stat (name, &statbuf);
1654 mode = statbuf.st_mode & S_IRUSR;
1655 return (!ret && mode);
1659 __gnat_is_writable_file (char *name)
1663 struct stat statbuf;
1665 ret = __gnat_stat (name, &statbuf);
1666 mode = statbuf.st_mode & S_IWUSR;
1667 return (!ret && mode);
1671 __gnat_set_writable (char *name)
1673 #if ! defined (__vxworks) && ! defined(__nucleus__)
1674 struct stat statbuf;
1676 if (stat (name, &statbuf) == 0)
1678 statbuf.st_mode = statbuf.st_mode | S_IWUSR;
1679 chmod (name, statbuf.st_mode);
1685 __gnat_set_executable (char *name)
1687 #if ! defined (__vxworks) && ! defined(__nucleus__)
1688 struct stat statbuf;
1690 if (stat (name, &statbuf) == 0)
1692 statbuf.st_mode = statbuf.st_mode | S_IXUSR;
1693 chmod (name, statbuf.st_mode);
1699 __gnat_set_readonly (char *name)
1701 #if ! defined (__vxworks) && ! defined(__nucleus__)
1702 struct stat statbuf;
1704 if (stat (name, &statbuf) == 0)
1706 statbuf.st_mode = statbuf.st_mode & 07577;
1707 chmod (name, statbuf.st_mode);
1713 __gnat_is_symbolic_link (char *name ATTRIBUTE_UNUSED)
1715 #if defined (__vxworks) || defined (__nucleus__)
1718 #elif defined (_AIX) || defined (__APPLE__) || defined (__unix__)
1720 struct stat statbuf;
1722 ret = lstat (name, &statbuf);
1723 return (!ret && S_ISLNK (statbuf.st_mode));
1730 #if defined (sun) && defined (__SVR4)
1731 /* Using fork on Solaris will duplicate all the threads. fork1, which
1732 duplicates only the active thread, must be used instead, or spawning
1733 subprocess from a program with tasking will lead into numerous problems. */
1738 __gnat_portable_spawn (char *args[])
1741 int finished ATTRIBUTE_UNUSED;
1742 int pid ATTRIBUTE_UNUSED;
1744 #if defined (__vxworks) || defined(__nucleus__) || defined(RTX)
1747 #elif defined (MSDOS) || defined (_WIN32)
1748 /* args[0] must be quotes as it could contain a full pathname with spaces */
1749 char *args_0 = args[0];
1750 args[0] = (char *)xmalloc (strlen (args_0) + 3);
1751 strcpy (args[0], "\"");
1752 strcat (args[0], args_0);
1753 strcat (args[0], "\"");
1755 status = spawnvp (P_WAIT, args_0, (const char* const*)args);
1757 /* restore previous value */
1759 args[0] = (char *)args_0;
1769 pid = spawnvp (P_NOWAIT, args[0], args);
1781 if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
1783 return -1; /* execv is in parent context on VMS. */
1791 finished = waitpid (pid, &status, 0);
1793 if (finished != pid || WIFEXITED (status) == 0)
1796 return WEXITSTATUS (status);
1802 /* Create a copy of the given file descriptor.
1803 Return -1 if an error occurred. */
1806 __gnat_dup (int oldfd)
1808 #if defined (__vxworks) && !defined (__RTP__)
1809 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
1817 /* Make newfd be the copy of oldfd, closing newfd first if necessary.
1818 Return -1 if an error occurred. */
1821 __gnat_dup2 (int oldfd, int newfd)
1823 #if defined (__vxworks) && !defined (__RTP__)
1824 /* Not supported on VxWorks 5.x, but supported on VxWorks 6.0 when using
1828 return dup2 (oldfd, newfd);
1832 /* WIN32 code to implement a wait call that wait for any child process. */
1834 #if defined (_WIN32) && !defined (RTX)
1836 /* Synchronization code, to be thread safe. */
1838 static CRITICAL_SECTION plist_cs;
1841 __gnat_plist_init (void)
1843 InitializeCriticalSection (&plist_cs);
1849 EnterCriticalSection (&plist_cs);
1855 LeaveCriticalSection (&plist_cs);
1858 typedef struct _process_list
1861 struct _process_list *next;
1864 static Process_List *PLIST = NULL;
1866 static int plist_length = 0;
1869 add_handle (HANDLE h)
1873 pl = (Process_List *) xmalloc (sizeof (Process_List));
1877 /* -------------------- critical section -------------------- */
1882 /* -------------------- critical section -------------------- */
1888 remove_handle (HANDLE h)
1891 Process_List *prev = NULL;
1895 /* -------------------- critical section -------------------- */
1904 prev->next = pl->next;
1916 /* -------------------- critical section -------------------- */
1922 win32_no_block_spawn (char *command, char *args[])
1926 PROCESS_INFORMATION PI;
1927 SECURITY_ATTRIBUTES SA;
1932 /* compute the total command line length */
1936 csize += strlen (args[k]) + 1;
1940 full_command = (char *) xmalloc (csize);
1943 SI.cb = sizeof (STARTUPINFO);
1944 SI.lpReserved = NULL;
1945 SI.lpReserved2 = NULL;
1946 SI.lpDesktop = NULL;
1950 SI.wShowWindow = SW_HIDE;
1952 /* Security attributes. */
1953 SA.nLength = sizeof (SECURITY_ATTRIBUTES);
1954 SA.bInheritHandle = TRUE;
1955 SA.lpSecurityDescriptor = NULL;
1957 /* Prepare the command string. */
1958 strcpy (full_command, command);
1959 strcat (full_command, " ");
1964 strcat (full_command, args[k]);
1965 strcat (full_command, " ");
1970 int wsize = csize * 2;
1971 TCHAR *wcommand = (TCHAR *) xmalloc (wsize);
1973 S2WSU (wcommand, full_command, wsize);
1975 free (full_command);
1977 result = CreateProcess
1978 (NULL, wcommand, &SA, NULL, TRUE,
1979 GetPriorityClass (GetCurrentProcess()), NULL, NULL, &SI, &PI);
1986 add_handle (PI.hProcess);
1987 CloseHandle (PI.hThread);
1988 return (int) PI.hProcess;
1995 win32_wait (int *status)
2004 if (plist_length == 0)
2010 hl = (HANDLE *) xmalloc (sizeof (HANDLE) * plist_length);
2015 /* -------------------- critical section -------------------- */
2022 /* -------------------- critical section -------------------- */
2026 res = WaitForMultipleObjects (plist_length, hl, FALSE, INFINITE);
2027 h = hl[res - WAIT_OBJECT_0];
2032 GetExitCodeProcess (h, &exitcode);
2035 *status = (int) exitcode;
2042 __gnat_portable_no_block_spawn (char *args[])
2046 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2049 #elif defined (__EMX__) || defined (MSDOS)
2051 /* ??? For PC machines I (Franco) don't know the system calls to implement
2052 this routine. So I'll fake it as follows. This routine will behave
2053 exactly like the blocking portable_spawn and will systematically return
2054 a pid of 0 unless the spawned task did not complete successfully, in
2055 which case we return a pid of -1. To synchronize with this the
2056 portable_wait below systematically returns a pid of 0 and reports that
2057 the subprocess terminated successfully. */
2059 if (spawnvp (P_WAIT, args[0], args) != 0)
2062 #elif defined (_WIN32)
2064 pid = win32_no_block_spawn (args[0], args);
2073 if (execv (args[0], MAYBE_TO_PTR32 (args)) != 0)
2075 return -1; /* execv is in parent context on VMS. */
2087 __gnat_portable_wait (int *process_status)
2092 #if defined (__vxworks) || defined (__nucleus__) || defined (RTX)
2093 /* Not sure what to do here, so do same as __EMX__ case, i.e., nothing but
2096 #elif defined (_WIN32)
2098 pid = win32_wait (&status);
2100 #elif defined (__EMX__) || defined (MSDOS)
2101 /* ??? See corresponding comment in portable_no_block_spawn. */
2105 pid = waitpid (-1, &status, 0);
2106 status = status & 0xffff;
2109 *process_status = status;
2114 __gnat_os_exit (int status)
2119 /* Locate a regular file, give a Path value. */
2122 __gnat_locate_regular_file (char *file_name, char *path_val)
2125 char *file_path = alloca (strlen (file_name) + 1);
2128 /* Return immediately if file_name is empty */
2130 if (*file_name == '\0')
2133 /* Remove quotes around file_name if present */
2139 strcpy (file_path, ptr);
2141 ptr = file_path + strlen (file_path) - 1;
2146 /* Handle absolute pathnames. */
2148 absolute = __gnat_is_absolute_path (file_path, strlen (file_name));
2152 if (__gnat_is_regular_file (file_path))
2153 return xstrdup (file_path);
2158 /* If file_name include directory separator(s), try it first as
2159 a path name relative to the current directory */
2160 for (ptr = file_name; *ptr && *ptr != '/' && *ptr != DIR_SEPARATOR; ptr++)
2165 if (__gnat_is_regular_file (file_name))
2166 return xstrdup (file_name);
2173 /* The result has to be smaller than path_val + file_name. */
2174 char *file_path = alloca (strlen (path_val) + strlen (file_name) + 2);
2178 for (; *path_val == PATH_SEPARATOR; path_val++)
2184 /* Skip the starting quote */
2186 if (*path_val == '"')
2189 for (ptr = file_path; *path_val && *path_val != PATH_SEPARATOR; )
2190 *ptr++ = *path_val++;
2194 /* Skip the ending quote */
2199 if (*ptr != '/' && *ptr != DIR_SEPARATOR)
2200 *++ptr = DIR_SEPARATOR;
2202 strcpy (++ptr, file_name);
2204 if (__gnat_is_regular_file (file_path))
2205 return xstrdup (file_path);
2212 /* Locate an executable given a Path argument. This routine is only used by
2213 gnatbl and should not be used otherwise. Use locate_exec_on_path
2217 __gnat_locate_exec (char *exec_name, char *path_val)
2220 if (!strstr (exec_name, HOST_EXECUTABLE_SUFFIX))
2222 char *full_exec_name
2223 = alloca (strlen (exec_name) + strlen (HOST_EXECUTABLE_SUFFIX) + 1);
2225 strcpy (full_exec_name, exec_name);
2226 strcat (full_exec_name, HOST_EXECUTABLE_SUFFIX);
2227 ptr = __gnat_locate_regular_file (full_exec_name, path_val);
2230 return __gnat_locate_regular_file (exec_name, path_val);
2234 return __gnat_locate_regular_file (exec_name, path_val);
2237 /* Locate an executable using the Systems default PATH. */
2240 __gnat_locate_exec_on_path (char *exec_name)
2244 #if defined (_WIN32) && !defined (RTX)
2245 TCHAR *wpath_val = _tgetenv (_T("PATH"));
2247 /* In Win32 systems we expand the PATH as for XP environment
2248 variables are not automatically expanded. We also prepend the
2249 ".;" to the path to match normal NT path search semantics */
2251 #define EXPAND_BUFFER_SIZE 32767
2253 wapath_val = alloca (EXPAND_BUFFER_SIZE);
2255 wapath_val [0] = '.';
2256 wapath_val [1] = ';';
2258 DWORD res = ExpandEnvironmentStrings
2259 (wpath_val, &wapath_val[2], EXPAND_BUFFER_SIZE - 2);
2261 if (!res) wapath_val [0] = _T('\0');
2263 apath_val = alloca (EXPAND_BUFFER_SIZE);
2265 WS2SU (apath_val, wapath_val, EXPAND_BUFFER_SIZE);
2266 return __gnat_locate_exec (exec_name, apath_val);
2271 char *path_val = "/VAXC$PATH";
2273 char *path_val = getenv ("PATH");
2275 if (path_val == NULL) return NULL;
2276 apath_val = alloca (strlen (path_val) + 1);
2277 strcpy (apath_val, path_val);
2278 return __gnat_locate_exec (exec_name, apath_val);
2284 /* These functions are used to translate to and from VMS and Unix syntax
2285 file, directory and path specifications. */
2288 #define MAXNAMES 256
2289 #define NEW_CANONICAL_FILELIST_INCREMENT 64
2291 static char new_canonical_dirspec [MAXPATH];
2292 static char new_canonical_filespec [MAXPATH];
2293 static char new_canonical_pathspec [MAXNAMES*MAXPATH];
2294 static unsigned new_canonical_filelist_index;
2295 static unsigned new_canonical_filelist_in_use;
2296 static unsigned new_canonical_filelist_allocated;
2297 static char **new_canonical_filelist;
2298 static char new_host_pathspec [MAXNAMES*MAXPATH];
2299 static char new_host_dirspec [MAXPATH];
2300 static char new_host_filespec [MAXPATH];
2302 /* Routine is called repeatedly by decc$from_vms via
2303 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
2307 wildcard_translate_unix (char *name)
2310 char buff [MAXPATH];
2312 strncpy (buff, name, MAXPATH);
2313 buff [MAXPATH - 1] = (char) 0;
2314 ver = strrchr (buff, '.');
2316 /* Chop off the version. */
2320 /* Dynamically extend the allocation by the increment. */
2321 if (new_canonical_filelist_in_use == new_canonical_filelist_allocated)
2323 new_canonical_filelist_allocated += NEW_CANONICAL_FILELIST_INCREMENT;
2324 new_canonical_filelist = (char **) xrealloc
2325 (new_canonical_filelist,
2326 new_canonical_filelist_allocated * sizeof (char *));
2329 new_canonical_filelist[new_canonical_filelist_in_use++] = xstrdup (buff);
2334 /* Translate a wildcard VMS file spec into a list of Unix file specs. First do
2335 full translation and copy the results into a list (_init), then return them
2336 one at a time (_next). If onlydirs set, only expand directory files. */
2339 __gnat_to_canonical_file_list_init (char *filespec, int onlydirs)
2342 char buff [MAXPATH];
2344 len = strlen (filespec);
2345 strncpy (buff, filespec, MAXPATH);
2347 /* Only look for directories */
2348 if (onlydirs && !strstr (&buff [len-5], "*.dir"))
2349 strncat (buff, "*.dir", MAXPATH);
2351 buff [MAXPATH - 1] = (char) 0;
2353 decc$from_vms (buff, wildcard_translate_unix, 1);
2355 /* Remove the .dir extension. */
2361 for (i = 0; i < new_canonical_filelist_in_use; i++)
2363 ext = strstr (new_canonical_filelist[i], ".dir");
2369 return new_canonical_filelist_in_use;
2372 /* Return the next filespec in the list. */
2375 __gnat_to_canonical_file_list_next ()
2377 return new_canonical_filelist[new_canonical_filelist_index++];
2380 /* Free storage used in the wildcard expansion. */
2383 __gnat_to_canonical_file_list_free ()
2387 for (i = 0; i < new_canonical_filelist_in_use; i++)
2388 free (new_canonical_filelist[i]);
2390 free (new_canonical_filelist);
2392 new_canonical_filelist_in_use = 0;
2393 new_canonical_filelist_allocated = 0;
2394 new_canonical_filelist_index = 0;
2395 new_canonical_filelist = 0;
2398 /* The functional equivalent of decc$translate_vms routine.
2399 Designed to produce the same output, but is protected against
2400 malformed paths (original version ACCVIOs in this case) and
2401 does not require VMS-specific DECC RTL */
2403 #define NAM$C_MAXRSS 1024
2406 __gnat_translate_vms (char *src)
2408 static char retbuf [NAM$C_MAXRSS+1];
2409 char *srcendpos, *pos1, *pos2, *retpos;
2410 int disp, path_present = 0;
2412 if (!src) return NULL;
2414 srcendpos = strchr (src, '\0');
2417 /* Look for the node and/or device in front of the path */
2419 pos2 = strchr (pos1, ':');
2421 if (pos2 && (pos2 < srcendpos) && (*(pos2 + 1) == ':')) {
2422 /* There is a node name. "node_name::" becomes "node_name!" */
2424 strncpy (retbuf, pos1, disp);
2425 retpos [disp] = '!';
2426 retpos = retpos + disp + 1;
2428 pos2 = strchr (pos1, ':');
2432 /* There is a device name. "dev_name:" becomes "/dev_name/" */
2435 strncpy (retpos, pos1, disp);
2436 retpos = retpos + disp;
2441 /* No explicit device; we must look ahead and prepend /sys$disk/ if
2442 the path is absolute */
2443 if ((*pos1 == '[' || *pos1 == '<') && (pos1 < srcendpos)
2444 && !strchr (".-]>", *(pos1 + 1))) {
2445 strncpy (retpos, "/sys$disk/", 10);
2449 /* Process the path part */
2450 while (*pos1 == '[' || *pos1 == '<') {
2453 if (*pos1 == ']' || *pos1 == '>') {
2454 /* Special case, [] translates to '.' */
2459 /* '[000000' means root dir. It can be present in the middle of
2460 the path due to expansion of logical devices, in which case
2462 if (!strncmp (pos1, "000000", 6) && path_present > 1 &&
2463 (*(pos1 + 6) == ']' || *(pos1 + 6) == '>' || *(pos1 + 6) == '.')) {
2465 if (*pos1 == '.') pos1++;
2467 else if (*pos1 == '.') {
2472 /* There is a qualified path */
2473 while (*pos1 && *pos1 != ']' && *pos1 != '>') {
2476 /* '.' is used to separate directories. Replace it with '/' but
2477 only if there isn't already '/' just before */
2478 if (*(retpos - 1) != '/') *(retpos++) = '/';
2480 if (pos1 + 1 < srcendpos && *pos1 == '.' && *(pos1 + 1) == '.') {
2481 /* ellipsis refers to entire subtree; replace with '**' */
2482 *(retpos++) = '*'; *(retpos++) = '*'; *(retpos++) = '/';
2487 /* When after '.' '[' '<' is equivalent to Unix ".." but there
2488 may be several in a row */
2489 if (*(pos1 - 1) == '.' || *(pos1 - 1) == '[' ||
2490 *(pos1 - 1) == '<') {
2491 while (*pos1 == '-') {
2493 *(retpos++) = '.'; *(retpos++) = '.'; *(retpos++) = '/';
2498 /* otherwise fall through to default */
2500 *(retpos++) = *(pos1++);
2507 if (pos1 < srcendpos) {
2508 /* Now add the actual file name, until the version suffix if any */
2509 if (path_present) *(retpos++) = '/';
2510 pos2 = strchr (pos1, ';');
2511 disp = pos2? (pos2 - pos1) : (srcendpos - pos1);
2512 strncpy (retpos, pos1, disp);
2514 if (pos2 && pos2 < srcendpos) {
2515 /* There is a non-empty version suffix. ";<ver>" becomes ".<ver>" */
2517 disp = srcendpos - pos2 - 1;
2518 strncpy (retpos, pos2 + 1, disp);
2529 /* Translate a VMS syntax directory specification in to Unix syntax. If
2530 PREFIXFLAG is set, append an underscore "/". If no indicators of VMS syntax
2531 found, return input string. Also translate a dirname that contains no
2532 slashes, in case it's a logical name. */
2535 __gnat_to_canonical_dir_spec (char *dirspec, int prefixflag)
2539 strcpy (new_canonical_dirspec, "");
2540 if (strlen (dirspec))
2544 if (strchr (dirspec, ']') || strchr (dirspec, ':'))
2546 strncpy (new_canonical_dirspec,
2547 __gnat_translate_vms (dirspec),
2550 else if (!strchr (dirspec, '/') && (dirspec1 = getenv (dirspec)) != 0)
2552 strncpy (new_canonical_dirspec,
2553 __gnat_translate_vms (dirspec1),
2558 strncpy (new_canonical_dirspec, dirspec, MAXPATH);
2562 len = strlen (new_canonical_dirspec);
2563 if (prefixflag && new_canonical_dirspec [len-1] != '/')
2564 strncat (new_canonical_dirspec, "/", MAXPATH);
2566 new_canonical_dirspec [MAXPATH - 1] = (char) 0;
2568 return new_canonical_dirspec;
2572 /* Translate a VMS syntax file specification into Unix syntax.
2573 If no indicators of VMS syntax found, check if it's an uppercase
2574 alphanumeric_ name and if so try it out as an environment
2575 variable (logical name). If all else fails return the
2579 __gnat_to_canonical_file_spec (char *filespec)
2583 strncpy (new_canonical_filespec, "", MAXPATH);
2585 if (strchr (filespec, ']') || strchr (filespec, ':'))
2587 char *tspec = (char *) __gnat_translate_vms (filespec);
2589 if (tspec != (char *) -1)
2590 strncpy (new_canonical_filespec, tspec, MAXPATH);
2592 else if ((strlen (filespec) == strspn (filespec,
2593 "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
2594 && (filespec1 = getenv (filespec)))
2596 char *tspec = (char *) __gnat_translate_vms (filespec1);
2598 if (tspec != (char *) -1)
2599 strncpy (new_canonical_filespec, tspec, MAXPATH);
2603 strncpy (new_canonical_filespec, filespec, MAXPATH);
2606 new_canonical_filespec [MAXPATH - 1] = (char) 0;
2608 return new_canonical_filespec;
2611 /* Translate a VMS syntax path specification into Unix syntax.
2612 If no indicators of VMS syntax found, return input string. */
2615 __gnat_to_canonical_path_spec (char *pathspec)
2617 char *curr, *next, buff [MAXPATH];
2622 /* If there are /'s, assume it's a Unix path spec and return. */
2623 if (strchr (pathspec, '/'))
2626 new_canonical_pathspec[0] = 0;
2631 next = strchr (curr, ',');
2633 next = strchr (curr, 0);
2635 strncpy (buff, curr, next - curr);
2636 buff[next - curr] = 0;
2638 /* Check for wildcards and expand if present. */
2639 if (strchr (buff, '*') || strchr (buff, '%') || strstr (buff, "..."))
2643 dirs = __gnat_to_canonical_file_list_init (buff, 1);
2644 for (i = 0; i < dirs; i++)
2648 next_dir = __gnat_to_canonical_file_list_next ();
2649 strncat (new_canonical_pathspec, next_dir, MAXPATH);
2651 /* Don't append the separator after the last expansion. */
2653 strncat (new_canonical_pathspec, ":", MAXPATH);
2656 __gnat_to_canonical_file_list_free ();
2659 strncat (new_canonical_pathspec,
2660 __gnat_to_canonical_dir_spec (buff, 0), MAXPATH);
2665 strncat (new_canonical_pathspec, ":", MAXPATH);
2669 new_canonical_pathspec [MAXPATH - 1] = (char) 0;
2671 return new_canonical_pathspec;
2674 static char filename_buff [MAXPATH];
2677 translate_unix (char *name, int type)
2679 strncpy (filename_buff, name, MAXPATH);
2680 filename_buff [MAXPATH - 1] = (char) 0;
2684 /* Translate a Unix syntax path spec into a VMS style (comma separated list of
2688 to_host_path_spec (char *pathspec)
2690 char *curr, *next, buff [MAXPATH];
2695 /* Can't very well test for colons, since that's the Unix separator! */
2696 if (strchr (pathspec, ']') || strchr (pathspec, ','))
2699 new_host_pathspec[0] = 0;
2704 next = strchr (curr, ':');
2706 next = strchr (curr, 0);
2708 strncpy (buff, curr, next - curr);
2709 buff[next - curr] = 0;
2711 strncat (new_host_pathspec, __gnat_to_host_dir_spec (buff, 0), MAXPATH);
2714 strncat (new_host_pathspec, ",", MAXPATH);
2718 new_host_pathspec [MAXPATH - 1] = (char) 0;
2720 return new_host_pathspec;
2723 /* Translate a Unix syntax directory specification into VMS syntax. The
2724 PREFIXFLAG has no effect, but is kept for symmetry with
2725 to_canonical_dir_spec. If indicators of VMS syntax found, return input
2729 __gnat_to_host_dir_spec (char *dirspec, int prefixflag ATTRIBUTE_UNUSED)
2731 int len = strlen (dirspec);
2733 strncpy (new_host_dirspec, dirspec, MAXPATH);
2734 new_host_dirspec [MAXPATH - 1] = (char) 0;
2736 if (strchr (new_host_dirspec, ']') || strchr (new_host_dirspec, ':'))
2737 return new_host_dirspec;
2739 while (len > 1 && new_host_dirspec[len - 1] == '/')
2741 new_host_dirspec[len - 1] = 0;
2745 decc$to_vms (new_host_dirspec, translate_unix, 1, 2);
2746 strncpy (new_host_dirspec, filename_buff, MAXPATH);
2747 new_host_dirspec [MAXPATH - 1] = (char) 0;
2749 return new_host_dirspec;
2752 /* Translate a Unix syntax file specification into VMS syntax.
2753 If indicators of VMS syntax found, return input string. */
2756 __gnat_to_host_file_spec (char *filespec)
2758 strncpy (new_host_filespec, "", MAXPATH);
2759 if (strchr (filespec, ']') || strchr (filespec, ':'))
2761 strncpy (new_host_filespec, filespec, MAXPATH);
2765 decc$to_vms (filespec, translate_unix, 1, 1);
2766 strncpy (new_host_filespec, filename_buff, MAXPATH);
2769 new_host_filespec [MAXPATH - 1] = (char) 0;
2771 return new_host_filespec;
2775 __gnat_adjust_os_resource_limits ()
2777 SYS$ADJWSL (131072, 0);
2782 /* Dummy functions for Osint import for non-VMS systems. */
2785 __gnat_to_canonical_file_list_init
2786 (char *dirspec ATTRIBUTE_UNUSED, int onlydirs ATTRIBUTE_UNUSED)
2792 __gnat_to_canonical_file_list_next (void)
2798 __gnat_to_canonical_file_list_free (void)
2803 __gnat_to_canonical_dir_spec (char *dirspec, int prefixflag ATTRIBUTE_UNUSED)
2809 __gnat_to_canonical_file_spec (char *filespec)
2815 __gnat_to_canonical_path_spec (char *pathspec)
2821 __gnat_to_host_dir_spec (char *dirspec, int prefixflag ATTRIBUTE_UNUSED)
2827 __gnat_to_host_file_spec (char *filespec)
2833 __gnat_adjust_os_resource_limits (void)
2839 /* For EMX, we cannot include dummy in libgcc, since it is too difficult
2840 to coordinate this with the EMX distribution. Consequently, we put the
2841 definition of dummy which is used for exception handling, here. */
2843 #if defined (__EMX__)
2847 #if defined (__mips_vxworks)
2851 CACHE_USER_FLUSH (0, ENTIRE_CACHE);
2855 #if defined (CROSS_DIRECTORY_STRUCTURE) \
2856 || (! ((defined (sparc) || defined (i386)) && defined (sun) \
2857 && defined (__SVR4)) \
2858 && ! (defined (linux) && (defined (i386) || defined (__x86_64__))) \
2859 && ! (defined (linux) && defined (__ia64__)) \
2860 && ! defined (__FreeBSD__) \
2861 && ! defined (__hpux__) \
2862 && ! defined (__APPLE__) \
2863 && ! defined (_AIX) \
2864 && ! (defined (__alpha__) && defined (__osf__)) \
2865 && ! defined (VMS) \
2866 && ! defined (__MINGW32__) \
2867 && ! (defined (__mips) && defined (__sgi)))
2869 /* Dummy function to satisfy g-trasym.o. See the preprocessor conditional
2870 just above for a list of native platforms that provide a non-dummy
2871 version of this procedure in libaddr2line.a. */
2874 convert_addresses (const char *file_name ATTRIBUTE_UNUSED,
2875 void *addrs ATTRIBUTE_UNUSED,
2876 int n_addr ATTRIBUTE_UNUSED,
2877 void *buf ATTRIBUTE_UNUSED,
2878 int *len ATTRIBUTE_UNUSED)
2884 #if defined (_WIN32)
2885 int __gnat_argument_needs_quote = 1;
2887 int __gnat_argument_needs_quote = 0;
2890 /* This option is used to enable/disable object files handling from the
2891 binder file by the GNAT Project module. For example, this is disabled on
2892 Windows (prior to GCC 3.4) as it is already done by the mdll module.
2893 Stating with GCC 3.4 the shared libraries are not based on mdll
2894 anymore as it uses the GCC's -shared option */
2895 #if defined (_WIN32) \
2896 && ((__GNUC__ < 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ < 4)))
2897 int __gnat_prj_add_obj_files = 0;
2899 int __gnat_prj_add_obj_files = 1;
2902 /* char used as prefix/suffix for environment variables */
2903 #if defined (_WIN32)
2904 char __gnat_environment_char = '%';
2906 char __gnat_environment_char = '$';
2909 /* This functions copy the file attributes from a source file to a
2912 mode = 0 : In this mode copy only the file time stamps (last access and
2913 last modification time stamps).
2915 mode = 1 : In this mode, time stamps and read/write/execute attributes are
2918 Returns 0 if operation was successful and -1 in case of error. */
2921 __gnat_copy_attribs (char *from, char *to, int mode)
2923 #if defined (VMS) || defined (__vxworks) || defined (__nucleus__)
2927 struct utimbuf tbuf;
2929 if (stat (from, &fbuf) == -1)
2934 tbuf.actime = fbuf.st_atime;
2935 tbuf.modtime = fbuf.st_mtime;
2937 if (utime (to, &tbuf) == -1)
2944 if (chmod (to, fbuf.st_mode) == -1)
2955 __gnat_lseek (int fd, long offset, int whence)
2957 return (int) lseek (fd, offset, whence);
2960 /* This function returns the major version number of GCC being used. */
2962 get_gcc_version (void)
2967 return (int) (version_string[0] - '0');
2972 __gnat_set_close_on_exec (int fd ATTRIBUTE_UNUSED,
2973 int close_on_exec_p ATTRIBUTE_UNUSED)
2975 #if defined (F_GETFD) && defined (FD_CLOEXEC) && ! defined (__vxworks)
2976 int flags = fcntl (fd, F_GETFD, 0);
2979 if (close_on_exec_p)
2980 flags |= FD_CLOEXEC;
2982 flags &= ~FD_CLOEXEC;
2983 return fcntl (fd, F_SETFD, flags | FD_CLOEXEC);
2986 /* For the Windows case, we should use SetHandleInformation to remove
2987 the HANDLE_INHERIT property from fd. This is not implemented yet,
2988 but for our purposes (support of GNAT.Expect) this does not matter,
2989 as by default handles are *not* inherited. */
2993 /* Indicates if platforms supports automatic initialization through the
2994 constructor mechanism */
2996 __gnat_binder_supports_auto_init ()
3005 /* Indicates that Stand-Alone Libraries are automatically initialized through
3006 the constructor mechanism */
3008 __gnat_sals_init_using_constructors ()
3010 #if defined (__vxworks) || defined (__Lynx__) || defined (VMS)
3017 /* In RTX mode, the procedure to get the time (as file time) is different
3018 in RTSS mode and Win32 mode. In order to avoid duplicating an Ada file,
3019 we introduce an intermediate procedure to link against the corresponding
3020 one in each situation. */
3023 void GetTimeAsFileTime(LPFILETIME pTime)
3026 RtGetRtssTimeAsFileTime (pTime); /* RTSS interface */
3028 GetSystemTimeAsFileTime (pTime); /* w32 interface */
3034 /* pthread affinity support */
3036 int __gnat_pthread_setaffinity_np (pthread_t th,
3038 const void *cpuset);
3041 #include <pthread.h>
3043 __gnat_pthread_setaffinity_np (pthread_t th,
3045 const cpu_set_t *cpuset)
3047 return pthread_setaffinity_np (th, cpusetsize, cpuset);
3051 __gnat_pthread_setaffinity_np (pthread_t th ATTRIBUTE_UNUSED,
3052 size_t cpusetsize ATTRIBUTE_UNUSED,
3053 const void *cpuset ATTRIBUTE_UNUSED)