48d66c79f3db0f0299a4d6e049a0a81e7395cb56
[gcc.git] / gcc / ada / adaint.c
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * A D A I N T *
6 * *
7 * $Revision$
8 * *
9 * C Implementation File *
10 * *
11 * Copyright (C) 1992-2001, Free Software Foundation, Inc. *
12 * *
13 * GNAT is free software; you can redistribute it and/or modify it under *
14 * terms of the GNU General Public License as published by the Free Soft- *
15 * ware Foundation; either version 2, or (at your option) any later ver- *
16 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
17 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
19 * for more details. You should have received a copy of the GNU General *
20 * Public License distributed with GNAT; see file COPYING. If not, write *
21 * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
22 * MA 02111-1307, USA. *
23 * *
24 * As a special exception, if you link this file with other files to *
25 * produce an executable, this file does not by itself cause the resulting *
26 * executable to be covered by the GNU General Public License. This except- *
27 * ion does not however invalidate any other reasons why the executable *
28 * file might be covered by the GNU Public License. *
29 * *
30 * GNAT was originally developed by the GNAT team at New York University. *
31 * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
32 * *
33 ****************************************************************************/
34
35 /* This file contains those routines named by Import pragmas in packages */
36 /* in the GNAT hierarchy (especially GNAT.OS_Lib) and in package Osint. */
37 /* Many of the subprograms in OS_Lib import standard library calls */
38 /* directly. This file contains all other routines. */
39
40 #ifdef __vxworks
41 /* No need to redefine exit here */
42 #ifdef exit
43 #undef exit
44 #endif
45 /* We want to use the POSIX variants of include files. */
46 #define POSIX
47 #include "vxWorks.h"
48
49 #if defined (__mips_vxworks)
50 #include "cacheLib.h"
51 #endif /* __mips_vxworks */
52
53 #endif /* VxWorks */
54
55 #ifdef IN_RTS
56 #include "tconfig.h"
57 #include "tsystem.h"
58 #include <sys/stat.h>
59 #include <fcntl.h>
60 #include <time.h>
61
62 /* We don't have libiberty, so us malloc. */
63 #define xmalloc(S) malloc (S)
64 #else
65 #include "config.h"
66 #include "system.h"
67 #endif
68 #include <sys/wait.h>
69
70 #if defined (__EMX__) || defined (MSDOS) || defined (_WIN32)
71 #include <process.h>
72 #endif
73
74 #if defined (_WIN32)
75 #include <dir.h>
76 #include <windows.h>
77 #endif
78
79 #include "adaint.h"
80
81 /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
82 defined in the current system. On DOS-like systems these flags control
83 whether the file is opened/created in text-translation mode (CR/LF in
84 external file mapped to LF in internal file), but in Unix-like systems,
85 no text translation is required, so these flags have no effect. */
86
87 #if defined (__EMX__)
88 #include <os2.h>
89 #endif
90
91 #if defined (MSDOS)
92 #include <dos.h>
93 #endif
94
95 #ifndef O_BINARY
96 #define O_BINARY 0
97 #endif
98
99 #ifndef O_TEXT
100 #define O_TEXT 0
101 #endif
102
103 #ifndef HOST_EXECUTABLE_SUFFIX
104 #define HOST_EXECUTABLE_SUFFIX ""
105 #endif
106
107 #ifndef HOST_OBJECT_SUFFIX
108 #define HOST_OBJECT_SUFFIX ".o"
109 #endif
110
111 #ifndef PATH_SEPARATOR
112 #define PATH_SEPARATOR ':'
113 #endif
114
115 #ifndef DIR_SEPARATOR
116 #define DIR_SEPARATOR '/'
117 #endif
118
119 char __gnat_dir_separator = DIR_SEPARATOR;
120
121 char __gnat_path_separator = PATH_SEPARATOR;
122
123 /* The GNAT_LIBRARY_TEMPLATE contains a list of expressions that define
124 the base filenames that libraries specified with -lsomelib options
125 may have. This is used by GNATMAKE to check whether an executable
126 is up-to-date or not. The syntax is
127
128 library_template ::= { pattern ; } pattern NUL
129 pattern ::= [ prefix ] * [ postfix ]
130
131 These should only specify names of static libraries as it makes
132 no sense to determine at link time if dynamic-link libraries are
133 up to date or not. Any libraries that are not found are supposed
134 to be up-to-date:
135
136 * if they are needed but not present, the link
137 will fail,
138
139 * otherwise they are libraries in the system paths and so
140 they are considered part of the system and not checked
141 for that reason.
142
143 ??? This should be part of a GNAT host-specific compiler
144 file instead of being included in all user applications
145 as well. This is only a temporary work-around for 3.11b. */
146
147 #ifndef GNAT_LIBRARY_TEMPLATE
148 #if defined(__EMX__)
149 #define GNAT_LIBRARY_TEMPLATE "*.a"
150 #elif defined(VMS)
151 #define GNAT_LIBRARY_TEMPLATE "*.olb"
152 #else
153 #define GNAT_LIBRARY_TEMPLATE "lib*.a"
154 #endif
155 #endif
156
157 const char *__gnat_library_template = GNAT_LIBRARY_TEMPLATE;
158
159 /* The following macro HAVE_READDIR_R should be defined if the
160 system provides the routine readdir_r */
161 #undef HAVE_READDIR_R
162 \f
163 void
164 __gnat_to_gm_time (p_time, p_year, p_month, p_day, p_hours, p_mins, p_secs)
165 time_t *p_time;
166 int *p_year, *p_month, *p_day, *p_hours, *p_mins, *p_secs;
167 {
168 struct tm *res;
169 time_t time = *p_time;
170
171 #ifdef _WIN32
172 /* On Windows systems, the time is sometimes rounded up to the nearest
173 even second, so if the number of seconds is odd, increment it. */
174 if (time & 1)
175 time++;
176 #endif
177
178 res = gmtime (&time);
179
180 if (res)
181 {
182 *p_year = res->tm_year;
183 *p_month = res->tm_mon;
184 *p_day = res->tm_mday;
185 *p_hours = res->tm_hour;
186 *p_mins = res->tm_min;
187 *p_secs = res->tm_sec;
188 }
189 else
190 *p_year = *p_month = *p_day = *p_hours = *p_mins = *p_secs = 0;
191 }
192
193 /* Place the contents of the symbolic link named PATH in the buffer BUF,
194 which has size BUFSIZ. If PATH is a symbolic link, then return the number
195 of characters of its content in BUF. Otherwise, return -1. For Windows,
196 OS/2 and vxworks, always return -1. */
197
198 int
199 __gnat_readlink (path, buf, bufsiz)
200 char *path;
201 char *buf;
202 size_t bufsiz;
203 {
204 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__)
205 return -1;
206 #elif defined (__INTERIX) || defined (VMS)
207 return -1;
208 #elif defined (__vxworks)
209 return -1;
210 #else
211 return readlink (path, buf, bufsiz);
212 #endif
213 }
214
215 /* Creates a symbolic link named newpath
216 which contains the string oldpath.
217 If newpath exists it will NOT be overwritten.
218 For Windows, OS/2, vxworks, Interix and VMS, always retur -1. */
219
220 int
221 __gnat_symlink (oldpath, newpath)
222 char *oldpath;
223 char *newpath;
224 {
225 #if defined (MSDOS) || defined (_WIN32) || defined (__EMX__)
226 return -1;
227 #elif defined (__INTERIX) || defined (VMS)
228 return -1;
229 #elif defined (__vxworks)
230 return -1;
231 #else
232 return symlink (oldpath, newpath);
233 #endif
234 }
235
236 /* Try to lock a file, return 1 if success */
237
238 #if defined (__vxworks) || defined (MSDOS) || defined (_WIN32)
239
240 /* Version that does not use link. */
241
242 int
243 __gnat_try_lock (dir, file)
244 char *dir;
245 char *file;
246 {
247 char full_path [256];
248 int fd;
249
250 sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
251 fd = open (full_path, O_CREAT | O_EXCL, 0600);
252 if (fd < 0) {
253 return 0;
254 }
255 close (fd);
256 return 1;
257 }
258
259 #elif defined (__EMX__) || defined (VMS)
260
261 /* More cases that do not use link; identical code, to solve too long
262 line problem ??? */
263
264 int
265 __gnat_try_lock (dir, file)
266 char *dir;
267 char *file;
268 {
269 char full_path [256];
270 int fd;
271
272 sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
273 fd = open (full_path, O_CREAT | O_EXCL, 0600);
274 if (fd < 0)
275 return 0;
276
277 close (fd);
278 return 1;
279 }
280
281 #else
282 /* Version using link(), more secure over NFS. */
283
284 int
285 __gnat_try_lock (dir, file)
286 char *dir;
287 char *file;
288 {
289 char full_path [256];
290 char temp_file [256];
291 struct stat stat_result;
292 int fd;
293
294 sprintf (full_path, "%s%c%s", dir, DIR_SEPARATOR, file);
295 sprintf (temp_file, "%s-%d-%d", dir, getpid(), getppid ());
296
297 /* Create the temporary file and write the process number */
298 fd = open (temp_file, O_CREAT | O_WRONLY, 0600);
299 if (fd < 0)
300 return 0;
301
302 close (fd);
303
304 /* Link it with the new file */
305 link (temp_file, full_path);
306
307 /* Count the references on the old one. If we have a count of two, then
308 the link did succeed. Remove the temporary file before returning. */
309 __gnat_stat (temp_file, &stat_result);
310 unlink (temp_file);
311 return stat_result.st_nlink == 2;
312 }
313 #endif
314
315 /* Return the maximum file name length. */
316
317 int
318 __gnat_get_maximum_file_name_length ()
319 {
320 #if defined(MSDOS)
321 return 8;
322 #elif defined (VMS)
323 if (getenv ("GNAT$EXTENDED_FILE_SPECIFICATIONS"))
324 return -1;
325 else
326 return 39;
327 #else
328 return -1;
329 #endif
330 }
331
332 /* Return the default switch character. */
333
334 char
335 __gnat_get_switch_character ()
336 {
337 /* Under MSDOS, the switch character is not normally a hyphen, but this is
338 the convention DJGPP uses. Similarly under OS2, the switch character is
339 not normally a hypen, but this is the convention EMX uses. */
340
341 return '-';
342 }
343
344 /* Return nonzero if file names are case sensitive. */
345
346 int
347 __gnat_get_file_names_case_sensitive ()
348 {
349 #if defined (__EMX__) || defined (MSDOS) || defined (VMS) || defined(WINNT)
350 return 0;
351 #else
352 return 1;
353 #endif
354 }
355
356 char
357 __gnat_get_default_identifier_character_set ()
358 {
359 #if defined (__EMX__) || defined (MSDOS)
360 return 'p';
361 #else
362 return '1';
363 #endif
364 }
365
366 /* Return the current working directory */
367
368 void
369 __gnat_get_current_dir (dir, length)
370 char *dir;
371 int *length;
372 {
373 #ifdef VMS
374 /* Force Unix style, which is what GNAT uses internally. */
375 getcwd (dir, *length, 0);
376 #else
377 getcwd (dir, *length);
378 #endif
379
380 *length = strlen (dir);
381
382 dir [*length] = DIR_SEPARATOR;
383 ++(*length);
384 dir [*length] = '\0';
385 }
386
387 /* Return the suffix for object files. */
388
389 void
390 __gnat_get_object_suffix_ptr (len, value)
391 int *len;
392 const char **value;
393 {
394 *value = HOST_OBJECT_SUFFIX;
395
396 if (*value == 0)
397 *len = 0;
398 else
399 *len = strlen (*value);
400
401 return;
402 }
403
404 /* Return the suffix for executable files */
405
406 void
407 __gnat_get_executable_suffix_ptr (len, value)
408 int *len;
409 const char **value;
410 {
411 *value = HOST_EXECUTABLE_SUFFIX;
412 if (!*value)
413 *len = 0;
414 else
415 *len = strlen (*value);
416
417 return;
418 }
419
420 /* Return the suffix for debuggable files. Usually this is the same as the
421 executable extension. */
422
423 void
424 __gnat_get_debuggable_suffix_ptr (len, value)
425 int *len;
426 const char **value;
427 {
428 #ifndef MSDOS
429 *value = HOST_EXECUTABLE_SUFFIX;
430 #else
431 /* On DOS, the extensionless COFF file is what gdb likes. */
432 *value = "";
433 #endif
434
435 if (*value == 0)
436 *len = 0;
437 else
438 *len = strlen (*value);
439
440 return;
441 }
442
443 int
444 __gnat_open_read (path, fmode)
445 char *path;
446 int fmode;
447 {
448 int fd;
449 int o_fmode = O_BINARY;
450
451 if (fmode)
452 o_fmode = O_TEXT;
453
454 #if defined(VMS)
455 /* Optional arguments mbc,deq,fop increase read performance */
456 fd = open (path, O_RDONLY | o_fmode, 0444,
457 "mbc=16", "deq=64", "fop=tef");
458 #elif defined(__vxworks)
459 fd = open (path, O_RDONLY | o_fmode, 0444);
460 #else
461 fd = open (path, O_RDONLY | o_fmode);
462 #endif
463 return fd < 0 ? -1 : fd;
464 }
465
466 #if defined (__EMX__)
467 #define PERM (S_IREAD | S_IWRITE)
468 #else
469 #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
470 #endif
471
472 int
473 __gnat_open_rw (path, fmode)
474 char *path;
475 int fmode;
476 {
477 int fd;
478 int o_fmode = O_BINARY;
479
480 if (fmode)
481 o_fmode = O_TEXT;
482
483 #if defined(VMS)
484 fd = open (path, O_RDWR | o_fmode, PERM,
485 "mbc=16", "deq=64", "fop=tef");
486 #else
487 fd = open (path, O_RDWR | o_fmode, PERM);
488 #endif
489
490 return fd < 0 ? -1 : fd;
491 }
492
493 int
494 __gnat_open_create (path, fmode)
495 char *path;
496 int fmode;
497 {
498 int fd;
499 int o_fmode = O_BINARY;
500
501 if (fmode)
502 o_fmode = O_TEXT;
503
504 #if defined(VMS)
505 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM,
506 "mbc=16", "deq=64", "fop=tef");
507 #else
508 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | o_fmode, PERM);
509 #endif
510
511 return fd < 0 ? -1 : fd;
512 }
513
514 int
515 __gnat_open_append (path, fmode)
516 char *path;
517 int fmode;
518 {
519 int fd;
520 int o_fmode = O_BINARY;
521
522 if (fmode)
523 o_fmode = O_TEXT;
524
525 #if defined(VMS)
526 fd = open (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM,
527 "mbc=16", "deq=64", "fop=tef");
528 #else
529 fd = open (path, O_WRONLY | O_CREAT | O_APPEND | o_fmode, PERM);
530 #endif
531
532 return fd < 0 ? -1 : fd;
533 }
534
535 /* Open a new file. Return error (-1) if the file already exists. */
536
537 int
538 __gnat_open_new (path, fmode)
539 char *path;
540 int fmode;
541 {
542 int fd;
543 int o_fmode = O_BINARY;
544
545 if (fmode)
546 o_fmode = O_TEXT;
547
548 #if defined(VMS)
549 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM,
550 "mbc=16", "deq=64", "fop=tef");
551 #else
552 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
553 #endif
554
555 return fd < 0 ? -1 : fd;
556 }
557
558 /* Open a new temp file. Return error (-1) if the file already exists.
559 Special options for VMS allow the file to be shared between parent and
560 child processes, however they really slow down output. Used in
561 gnatchop. */
562
563 int
564 __gnat_open_new_temp (path, fmode)
565 char *path;
566 int fmode;
567 {
568 int fd;
569 int o_fmode = O_BINARY;
570
571 strcpy (path, "GNAT-XXXXXX");
572
573 #if defined (linux) && !defined (__vxworks)
574 return mkstemp (path);
575
576 #else
577 if (mktemp (path) == NULL)
578 return -1;
579 #endif
580
581 if (fmode)
582 o_fmode = O_TEXT;
583
584 #if defined(VMS)
585 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM,
586 "rfm=stmlf", "ctx=rec", "rat=none", "shr=del,get,put,upd",
587 "mbc=16", "deq=64", "fop=tef");
588 #else
589 fd = open (path, O_WRONLY | O_CREAT | O_EXCL | o_fmode, PERM);
590 #endif
591
592 return fd < 0 ? -1 : fd;
593 }
594
595 int
596 __gnat_mkdir (dir_name)
597 char *dir_name;
598 {
599 /* On some systems, mkdir has two args and on some it has one. If we
600 are being built as part of the compiler, autoconf has figured that out
601 for us. Otherwise, we have to do it ourselves. */
602 #ifndef IN_RTS
603 return mkdir (dir_name, S_IRWXU | S_IRWXG | S_IRWXO);
604 #else
605 #if defined (_WIN32) || defined (__vxworks)
606 return mkdir (dir_name);
607 #else
608 return mkdir (dir_name, S_IRWXU | S_IRWXG | S_IRWXO);
609 #endif
610 #endif
611 }
612
613 /* Return the number of bytes in the specified file. */
614
615 long
616 __gnat_file_length (fd)
617 int fd;
618 {
619 int ret;
620 struct stat statbuf;
621
622 ret = fstat (fd, &statbuf);
623 if (ret || !S_ISREG (statbuf.st_mode))
624 return 0;
625
626 return (statbuf.st_size);
627 }
628
629 /* Create a temporary filename and put it in string pointed to by
630 tmp_filename */
631
632 void
633 __gnat_tmp_name (tmp_filename)
634 char *tmp_filename;
635 {
636 #ifdef __MINGW32__
637 {
638 char *pname;
639
640 /* tempnam tries to create a temporary file in directory pointed to by
641 TMP environment variable, in c:\temp if TMP is not set, and in
642 directory specified by P_tmpdir in stdio.h if c:\temp does not
643 exist. The filename will be created with the prefix "gnat-". */
644
645 pname = (char *) tempnam ("c:\\temp", "gnat-");
646
647 /* if pname start with a back slash and not path information it means that
648 the filename is valid for the current working directory */
649
650 if (pname[0] == '\\')
651 {
652 strcpy (tmp_filename, ".\\");
653 strcat (tmp_filename, pname+1);
654 }
655 else
656 strcpy (tmp_filename, pname);
657
658 free (pname);
659 }
660 #elif defined (linux)
661 char *tmpdir = getenv ("TMPDIR");
662
663 if (tmpdir == NULL)
664 strcpy (tmp_filename, "/tmp/gnat-XXXXXX");
665 else
666 sprintf (tmp_filename, "%s/gnat-XXXXXX", tmpdir);
667
668 close (mkstemp(tmp_filename));
669 #else
670 tmpnam (tmp_filename);
671 #endif
672 }
673
674 /* Read the next entry in a directory. The returned string points somewhere
675 in the buffer. */
676
677 char *
678 __gnat_readdir (dirp, buffer)
679 DIR *dirp;
680 char* buffer;
681 {
682 /* If possible, try to use the thread-safe version. */
683 #ifdef HAVE_READDIR_R
684 if (readdir_r (dirp, buffer) != NULL)
685 return ((struct dirent*) buffer)->d_name;
686 else
687 return NULL;
688
689 #else
690 struct dirent *dirent = readdir (dirp);
691
692 if (dirent != NULL)
693 {
694 strcpy (buffer, dirent->d_name);
695 return buffer;
696 }
697 else
698 return NULL;
699
700 #endif
701 }
702
703 /* Returns 1 if readdir is thread safe, 0 otherwise. */
704
705 int
706 __gnat_readdir_is_thread_safe ()
707 {
708 #ifdef HAVE_READDIR_R
709 return 1;
710 #else
711 return 0;
712 #endif
713 }
714
715 #ifdef _WIN32
716
717 /* Returns the file modification timestamp using Win32 routines which are
718 immune against daylight saving time change. It is in fact not possible to
719 use fstat for this purpose as the DST modify the st_mtime field of the
720 stat structure. */
721
722 static time_t
723 win32_filetime (h)
724 HANDLE h;
725 {
726 BOOL res;
727 FILETIME t_create;
728 FILETIME t_access;
729 FILETIME t_write;
730 unsigned long long timestamp;
731
732 /* Number of seconds between <Jan 1st 1601> and <Jan 1st 1970> */
733 unsigned long long offset = 11644473600;
734
735 /* GetFileTime returns FILETIME data which are the number of 100 nanosecs
736 since <Jan 1st 1601>. This function must return the number of seconds
737 since <Jan 1st 1970>. */
738
739 res = GetFileTime (h, &t_create, &t_access, &t_write);
740
741 timestamp = (((long long) t_write.dwHighDateTime << 32)
742 + t_write.dwLowDateTime);
743
744 timestamp = timestamp / 10000000 - offset;
745
746 return (time_t) timestamp;
747 }
748 #endif
749
750 /* Return a GNAT time stamp given a file name. */
751
752 time_t
753 __gnat_file_time_name (name)
754 char *name;
755 {
756 struct stat statbuf;
757
758 #if defined (__EMX__) || defined (MSDOS)
759 int fd = open (name, O_RDONLY | O_BINARY);
760 time_t ret = __gnat_file_time_fd (fd);
761 close (fd);
762 return ret;
763
764 #elif defined (_WIN32)
765 HANDLE h = CreateFile (name, GENERIC_READ, FILE_SHARE_READ, 0,
766 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
767 time_t ret = win32_filetime (h);
768 CloseHandle (h);
769 return ret;
770 #else
771
772 (void) __gnat_stat (name, &statbuf);
773 #ifdef VMS
774 /* VMS has file versioning */
775 return statbuf.st_ctime;
776 #else
777 return statbuf.st_mtime;
778 #endif
779 #endif
780 }
781
782 /* Return a GNAT time stamp given a file descriptor. */
783
784 time_t
785 __gnat_file_time_fd (fd)
786 int fd;
787 {
788 /* The following workaround code is due to the fact that under EMX and
789 DJGPP fstat attempts to convert time values to GMT rather than keep the
790 actual OS timestamp of the file. By using the OS2/DOS functions directly
791 the GNAT timestamp are independent of this behavior, which is desired to
792 facilitate the distribution of GNAT compiled libraries. */
793
794 #if defined (__EMX__) || defined (MSDOS)
795 #ifdef __EMX__
796
797 FILESTATUS fs;
798 int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
799 sizeof (FILESTATUS));
800
801 unsigned file_year = fs.fdateLastWrite.year;
802 unsigned file_month = fs.fdateLastWrite.month;
803 unsigned file_day = fs.fdateLastWrite.day;
804 unsigned file_hour = fs.ftimeLastWrite.hours;
805 unsigned file_min = fs.ftimeLastWrite.minutes;
806 unsigned file_tsec = fs.ftimeLastWrite.twosecs;
807
808 #else
809 struct ftime fs;
810 int ret = getftime (fd, &fs);
811
812 unsigned file_year = fs.ft_year;
813 unsigned file_month = fs.ft_month;
814 unsigned file_day = fs.ft_day;
815 unsigned file_hour = fs.ft_hour;
816 unsigned file_min = fs.ft_min;
817 unsigned file_tsec = fs.ft_tsec;
818 #endif
819
820 /* Calculate the seconds since epoch from the time components. First count
821 the whole days passed. The value for years returned by the DOS and OS2
822 functions count years from 1980, so to compensate for the UNIX epoch which
823 begins in 1970 start with 10 years worth of days and add days for each
824 four year period since then. */
825
826 time_t tot_secs;
827 int cum_days [12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
828 int days_passed = 3652 + (file_year / 4) * 1461;
829 int years_since_leap = file_year % 4;
830
831 if (years_since_leap == 1)
832 days_passed += 366;
833 else if (years_since_leap == 2)
834 days_passed += 731;
835 else if (years_since_leap == 3)
836 days_passed += 1096;
837
838 if (file_year > 20)
839 days_passed -= 1;
840
841 days_passed += cum_days [file_month - 1];
842 if (years_since_leap == 0 && file_year != 20 && file_month > 2)
843 days_passed++;
844
845 days_passed += file_day - 1;
846
847 /* OK - have whole days. Multiply -- then add in other parts. */
848
849 tot_secs = days_passed * 86400;
850 tot_secs += file_hour * 3600;
851 tot_secs += file_min * 60;
852 tot_secs += file_tsec * 2;
853 return tot_secs;
854
855 #elif defined (_WIN32)
856 HANDLE h = (HANDLE) _get_osfhandle (fd);
857 time_t ret = win32_filetime (h);
858 CloseHandle (h);
859 return ret;
860
861 #else
862 struct stat statbuf;
863
864 (void) fstat (fd, &statbuf);
865
866 #ifdef VMS
867 /* VMS has file versioning */
868 return statbuf.st_ctime;
869 #else
870 return statbuf.st_mtime;
871 #endif
872 #endif
873 }
874
875 void
876 __gnat_get_env_value_ptr (name, len, value)
877 char *name;
878 int *len;
879 char **value;
880 {
881 *value = getenv (name);
882 if (!*value)
883 *len = 0;
884 else
885 *len = strlen (*value);
886
887 return;
888 }
889
890 /* VMS specific declarations for set_env_value. */
891
892 #ifdef VMS
893
894 static char *to_host_path_spec PROTO ((char *));
895
896 struct descriptor_s
897 {
898 unsigned short len, mbz;
899 char *adr;
900 };
901
902 typedef struct _ile3
903 {
904 unsigned short len, code;
905 char *adr;
906 unsigned short *retlen_adr;
907 } ile_s;
908
909 #endif
910
911 void
912 __gnat_set_env_value (name, value)
913 char *name;
914 char *value;
915 {
916 #ifdef MSDOS
917
918 #elif defined (VMS)
919 struct descriptor_s name_desc;
920 /* Put in JOB table for now, so that the project stuff at least works */
921 struct descriptor_s table_desc = {7, 0, "LNM$JOB"};
922 char *host_pathspec = to_host_path_spec (value);
923 char *copy_pathspec;
924 int num_dirs_in_pathspec = 1;
925 char *ptr;
926
927 if (*host_pathspec == 0)
928 return;
929
930 name_desc.len = strlen (name);
931 name_desc.mbz = 0;
932 name_desc.adr = name;
933
934 ptr = host_pathspec;
935 while (*ptr++)
936 if (*ptr == ',')
937 num_dirs_in_pathspec++;
938
939 {
940 int i, status;
941 ile_s *ile_array = alloca (sizeof (ile_s) * (num_dirs_in_pathspec + 1));
942 char *copy_pathspec = alloca (strlen (host_pathspec) + 1);
943 char *curr, *next;
944
945 strcpy (copy_pathspec, host_pathspec);
946 curr = copy_pathspec;
947 for (i = 0; i < num_dirs_in_pathspec; i++)
948 {
949 next = strchr (curr, ',');
950 if (next == 0)
951 next = strchr (curr, 0);
952
953 *next = 0;
954 ile_array [i].len = strlen (curr);
955
956 /* Code 2 from lnmdef.h means its a string */
957 ile_array [i].code = 2;
958 ile_array [i].adr = curr;
959
960 /* retlen_adr is ignored */
961 ile_array [i].retlen_adr = 0;
962 curr = next + 1;
963 }
964
965 /* Terminating item must be zero */
966 ile_array [i].len = 0;
967 ile_array [i].code = 0;
968 ile_array [i].adr = 0;
969 ile_array [i].retlen_adr = 0;
970
971 status = LIB$SET_LOGICAL (&name_desc, 0, &table_desc, 0, ile_array);
972 if ((status & 1) != 1)
973 LIB$SIGNAL (status);
974 }
975
976 #else
977 int size = strlen (name) + strlen (value) + 2;
978 char *expression;
979
980 expression = (char *) xmalloc (size * sizeof (char));
981
982 sprintf (expression, "%s=%s", name, value);
983 putenv (expression);
984 #endif
985 }
986
987 #ifdef _WIN32
988 #include <windows.h>
989 #endif
990
991 /* Get the list of installed standard libraries from the
992 HKEY_LOCAL_MACHINE\SOFTWARE\Ada Core Technologies\GNAT\Standard Libraries
993 key. */
994
995 char *
996 __gnat_get_libraries_from_registry ()
997 {
998 char *result = (char *) "";
999
1000 #if defined (_WIN32) && ! defined (__vxworks) && ! defined (CROSS_COMPILE)
1001
1002 HKEY reg_key;
1003 DWORD name_size, value_size;
1004 char name[256];
1005 char value[256];
1006 DWORD type;
1007 DWORD index;
1008 LONG res;
1009
1010 /* First open the key. */
1011 res = RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE", 0, KEY_READ, &reg_key);
1012
1013 if (res == ERROR_SUCCESS)
1014 res = RegOpenKeyExA (reg_key, "Ada Core Technologies", 0,
1015 KEY_READ, &reg_key);
1016
1017 if (res == ERROR_SUCCESS)
1018 res = RegOpenKeyExA (reg_key, "GNAT", 0, KEY_READ, &reg_key);
1019
1020 if (res == ERROR_SUCCESS)
1021 res = RegOpenKeyExA (reg_key, "Standard Libraries", 0, KEY_READ, &reg_key);
1022
1023 /* If the key exists, read out all the values in it and concatenate them
1024 into a path. */
1025 for (index = 0; res == ERROR_SUCCESS; index++)
1026 {
1027 value_size = name_size = 256;
1028 res = RegEnumValue (reg_key, index, name, &name_size, 0,
1029 &type, value, &value_size);
1030
1031 if (res == ERROR_SUCCESS && type == REG_SZ)
1032 {
1033 char *old_result = result;
1034
1035 result = (char *) xmalloc (strlen (old_result) + value_size + 2);
1036 strcpy (result, old_result);
1037 strcat (result, value);
1038 strcat (result, ";");
1039 }
1040 }
1041
1042 /* Remove the trailing ";". */
1043 if (result[0] != 0)
1044 result[strlen (result) - 1] = 0;
1045
1046 #endif
1047 return result;
1048 }
1049
1050 int
1051 __gnat_stat (name, statbuf)
1052 char *name;
1053 struct stat *statbuf;
1054 {
1055 #ifdef _WIN32
1056 /* Under Windows the directory name for the stat function must not be
1057 terminated by a directory separator except if just after a drive name. */
1058 int name_len = strlen (name);
1059 char last_char = name [name_len - 1];
1060 char win32_name [4096];
1061
1062 strcpy (win32_name, name);
1063
1064 while (name_len > 1 && (last_char == '\\' || last_char == '/'))
1065 {
1066 win32_name [name_len - 1] = '\0';
1067 name_len--;
1068 last_char = win32_name[name_len - 1];
1069 }
1070
1071 if (name_len == 2 && win32_name [1] == ':')
1072 strcat (win32_name, "\\");
1073
1074 return stat (win32_name, statbuf);
1075
1076 #else
1077 return stat (name, statbuf);
1078 #endif
1079 }
1080
1081 int
1082 __gnat_file_exists (name)
1083 char *name;
1084 {
1085 struct stat statbuf;
1086
1087 return !__gnat_stat (name, &statbuf);
1088 }
1089
1090 int
1091 __gnat_is_absolute_path (name)
1092 char *name;
1093 {
1094 return (*name == '/' || *name == DIR_SEPARATOR
1095 #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
1096 || strlen (name) > 1 && isalpha (name [0]) && name [1] == ':'
1097 #endif
1098 );
1099 }
1100
1101 int
1102 __gnat_is_regular_file (name)
1103 char *name;
1104 {
1105 int ret;
1106 struct stat statbuf;
1107
1108 ret = __gnat_stat (name, &statbuf);
1109 return (!ret && S_ISREG (statbuf.st_mode));
1110 }
1111
1112 int
1113 __gnat_is_directory (name)
1114 char *name;
1115 {
1116 int ret;
1117 struct stat statbuf;
1118
1119 ret = __gnat_stat (name, &statbuf);
1120 return (!ret && S_ISDIR (statbuf.st_mode));
1121 }
1122
1123 int
1124 __gnat_is_writable_file (name)
1125 char *name;
1126 {
1127 int ret;
1128 int mode;
1129 struct stat statbuf;
1130
1131 ret = __gnat_stat (name, &statbuf);
1132 mode = statbuf.st_mode & S_IWUSR;
1133 return (!ret && mode);
1134 }
1135
1136 #ifdef VMS
1137 /* Defined in VMS header files */
1138 #define fork() (decc$$alloc_vfork_blocks() >= 0 ? \
1139 LIB$GET_CURRENT_INVO_CONTEXT (decc$$get_vfork_jmpbuf()) : -1)
1140 #endif
1141
1142 #if defined (sun) && defined (__SVR4)
1143 /* Using fork on Solaris will duplicate all the threads. fork1, which
1144 duplicates only the active thread, must be used instead, or spawning
1145 subprocess from a program with tasking will lead into numerous problems. */
1146 #define fork fork1
1147 #endif
1148
1149 int
1150 __gnat_portable_spawn (args)
1151 char *args[];
1152 {
1153 int status = 0;
1154 int finished;
1155 int pid;
1156
1157 #if defined (MSDOS) || defined (_WIN32)
1158 status = spawnvp (P_WAIT, args [0], args);
1159 if (status < 0)
1160 return 4;
1161 else
1162 return status;
1163
1164 #elif defined(__vxworks) /* Mods for VxWorks */
1165 pid = sp (args[0], args); /* Spawn process and save pid */
1166 if (pid == -1)
1167 return (4);
1168
1169 while (taskIdVerify(pid) >= 0)
1170 /* Wait until spawned task is complete then continue. */
1171 ;
1172 #else
1173
1174 #ifdef __EMX__
1175 pid = spawnvp (P_NOWAIT, args [0], args);
1176 if (pid == -1)
1177 return (4);
1178 #else
1179 pid = fork ();
1180 if (pid == -1)
1181 return (4);
1182
1183 if (pid == 0 && execv (args [0], args) != 0)
1184 _exit (1);
1185 #endif
1186
1187 /* The parent */
1188 finished = waitpid (pid, &status, 0);
1189
1190 if (finished != pid || WIFEXITED (status) == 0)
1191 return 4;
1192
1193 return WEXITSTATUS (status);
1194 #endif
1195 return 0;
1196 }
1197
1198 /* WIN32 code to implement a wait call that wait for any child process */
1199 #ifdef _WIN32
1200
1201 /* Synchronization code, to be thread safe. */
1202
1203 static CRITICAL_SECTION plist_cs;
1204
1205 void
1206 __gnat_plist_init ()
1207 {
1208 InitializeCriticalSection (&plist_cs);
1209 }
1210
1211 static void
1212 plist_enter ()
1213 {
1214 EnterCriticalSection (&plist_cs);
1215 }
1216
1217 void
1218 plist_leave ()
1219 {
1220 LeaveCriticalSection (&plist_cs);
1221 }
1222
1223 typedef struct _process_list
1224 {
1225 HANDLE h;
1226 struct _process_list *next;
1227 } Process_List;
1228
1229 static Process_List *PLIST = NULL;
1230
1231 static int plist_length = 0;
1232
1233 static void
1234 add_handle (h)
1235 HANDLE h;
1236 {
1237 Process_List *pl;
1238
1239 pl = (Process_List *) xmalloc (sizeof (Process_List));
1240
1241 plist_enter();
1242
1243 /* -------------------- critical section -------------------- */
1244 pl->h = h;
1245 pl->next = PLIST;
1246 PLIST = pl;
1247 ++plist_length;
1248 /* -------------------- critical section -------------------- */
1249
1250 plist_leave();
1251 }
1252
1253 void remove_handle (h)
1254 HANDLE h;
1255 {
1256 Process_List *pl, *prev;
1257
1258 plist_enter();
1259
1260 /* -------------------- critical section -------------------- */
1261 pl = PLIST;
1262 while (pl)
1263 {
1264 if (pl->h == h)
1265 {
1266 if (pl == PLIST)
1267 PLIST = pl->next;
1268 else
1269 prev->next = pl->next;
1270 free (pl);
1271 break;
1272 }
1273 else
1274 {
1275 prev = pl;
1276 pl = pl->next;
1277 }
1278 }
1279
1280 --plist_length;
1281 /* -------------------- critical section -------------------- */
1282
1283 plist_leave();
1284 }
1285
1286 static int
1287 win32_no_block_spawn (command, args)
1288 char *command;
1289 char *args[];
1290 {
1291 BOOL result;
1292 STARTUPINFO SI;
1293 PROCESS_INFORMATION PI;
1294 SECURITY_ATTRIBUTES SA;
1295
1296 char full_command [2000];
1297 int k;
1298
1299 /* Startup info. */
1300 SI.cb = sizeof (STARTUPINFO);
1301 SI.lpReserved = NULL;
1302 SI.lpReserved2 = NULL;
1303 SI.lpDesktop = NULL;
1304 SI.cbReserved2 = 0;
1305 SI.lpTitle = NULL;
1306 SI.dwFlags = 0;
1307 SI.wShowWindow = SW_HIDE;
1308
1309 /* Security attributes. */
1310 SA.nLength = sizeof (SECURITY_ATTRIBUTES);
1311 SA.bInheritHandle = TRUE;
1312 SA.lpSecurityDescriptor = NULL;
1313
1314 /* Prepare the command string. */
1315 strcpy (full_command, command);
1316 strcat (full_command, " ");
1317
1318 k = 1;
1319 while (args[k])
1320 {
1321 strcat (full_command, args[k]);
1322 strcat (full_command, " ");
1323 k++;
1324 }
1325
1326 result = CreateProcess (NULL, (char *) full_command, &SA, NULL, TRUE,
1327 NORMAL_PRIORITY_CLASS, NULL, NULL, &SI, &PI);
1328
1329 if (result == TRUE)
1330 {
1331 add_handle (PI.hProcess);
1332 CloseHandle (PI.hThread);
1333 return (int) PI.hProcess;
1334 }
1335 else
1336 return -1;
1337 }
1338
1339 static int
1340 win32_wait (status)
1341 int *status;
1342 {
1343 DWORD exitcode;
1344 HANDLE *hl;
1345 HANDLE h;
1346 DWORD res;
1347 int k;
1348 Process_List *pl;
1349
1350 if (plist_length == 0)
1351 {
1352 errno = ECHILD;
1353 return -1;
1354 }
1355
1356 hl = (HANDLE *) xmalloc (sizeof (HANDLE) * plist_length);
1357
1358 k = 0;
1359 plist_enter();
1360
1361 /* -------------------- critical section -------------------- */
1362 pl = PLIST;
1363 while (pl)
1364 {
1365 hl[k++] = pl->h;
1366 pl = pl->next;
1367 }
1368 /* -------------------- critical section -------------------- */
1369
1370 plist_leave();
1371
1372 res = WaitForMultipleObjects (plist_length, hl, FALSE, INFINITE);
1373 h = hl [res - WAIT_OBJECT_0];
1374 free (hl);
1375
1376 remove_handle (h);
1377
1378 GetExitCodeProcess (h, &exitcode);
1379 CloseHandle (h);
1380
1381 *status = (int) exitcode;
1382 return (int) h;
1383 }
1384
1385 #endif
1386
1387 int
1388 __gnat_portable_no_block_spawn (args)
1389 char *args[];
1390 {
1391 int pid = 0;
1392
1393 #if defined (__EMX__) || defined (MSDOS)
1394
1395 /* ??? For PC machines I (Franco) don't know the system calls to implement
1396 this routine. So I'll fake it as follows. This routine will behave
1397 exactly like the blocking portable_spawn and will systematically return
1398 a pid of 0 unless the spawned task did not complete successfully, in
1399 which case we return a pid of -1. To synchronize with this the
1400 portable_wait below systematically returns a pid of 0 and reports that
1401 the subprocess terminated successfully. */
1402
1403 if (spawnvp (P_WAIT, args [0], args) != 0)
1404 return -1;
1405
1406 #elif defined (_WIN32)
1407
1408 pid = win32_no_block_spawn (args[0], args);
1409 return pid;
1410
1411 #elif defined (__vxworks) /* Mods for VxWorks */
1412 pid = sp (args[0], args); /* Spawn task and then return (no waiting) */
1413 if (pid == -1)
1414 return (4);
1415
1416 return pid;
1417
1418 #else
1419 pid = fork ();
1420
1421 if (pid == 0 && execv (args [0], args) != 0)
1422 _exit (1);
1423 #endif
1424
1425 return pid;
1426 }
1427
1428 int
1429 __gnat_portable_wait (process_status)
1430 int *process_status;
1431 {
1432 int status = 0;
1433 int pid = 0;
1434
1435 #if defined (_WIN32)
1436
1437 pid = win32_wait (&status);
1438
1439 #elif defined (__EMX__) || defined (MSDOS)
1440 /* ??? See corresponding comment in portable_no_block_spawn. */
1441
1442 #elif defined (__vxworks)
1443 /* Not sure what to do here, so do same as __EMX__ case, i.e., nothing but
1444 return zero. */
1445 #else
1446
1447 #ifdef VMS
1448 /* Wait doesn't do the right thing on VMS */
1449 pid = waitpid (-1, &status, 0);
1450 #else
1451 pid = wait (&status);
1452 #endif
1453 status = status & 0xffff;
1454 #endif
1455
1456 *process_status = status;
1457 return pid;
1458 }
1459
1460 void
1461 __gnat_os_exit (status)
1462 int status;
1463 {
1464 #ifdef VMS
1465 /* Exit without changing 0 to 1 */
1466 __posix_exit (status);
1467 #else
1468 exit (status);
1469 #endif
1470 }
1471
1472 /* Locate a regular file, give a Path value */
1473
1474 char *
1475 __gnat_locate_regular_file (file_name, path_val)
1476 char *file_name;
1477 char *path_val;
1478 {
1479 char *ptr;
1480
1481 /* Handle absolute pathnames. */
1482 for (ptr = file_name; *ptr && *ptr != '/' && *ptr != DIR_SEPARATOR; ptr++)
1483 ;
1484
1485 if (*ptr != 0
1486 #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
1487 || isalpha (file_name [0]) && file_name [1] == ':'
1488 #endif
1489 )
1490 {
1491 if (__gnat_is_regular_file (file_name))
1492 return xstrdup (file_name);
1493
1494 return 0;
1495 }
1496
1497 if (path_val == 0)
1498 return 0;
1499
1500 {
1501 /* The result has to be smaller than path_val + file_name. */
1502 char *file_path = alloca (strlen (path_val) + strlen (file_name) + 2);
1503
1504 for (;;)
1505 {
1506 for (; *path_val == PATH_SEPARATOR; path_val++)
1507 ;
1508
1509 if (*path_val == 0)
1510 return 0;
1511
1512 for (ptr = file_path; *path_val && *path_val != PATH_SEPARATOR; )
1513 *ptr++ = *path_val++;
1514
1515 ptr--;
1516 if (*ptr != '/' && *ptr != DIR_SEPARATOR)
1517 *++ptr = DIR_SEPARATOR;
1518
1519 strcpy (++ptr, file_name);
1520
1521 if (__gnat_is_regular_file (file_path))
1522 return xstrdup (file_path);
1523 }
1524 }
1525
1526 return 0;
1527 }
1528
1529
1530 /* Locate an executable given a Path argument. This routine is only used by
1531 gnatbl and should not be used otherwise. Use locate_exec_on_path
1532 instead. */
1533
1534 char *
1535 __gnat_locate_exec (exec_name, path_val)
1536 char *exec_name;
1537 char *path_val;
1538 {
1539 if (!strstr (exec_name, HOST_EXECUTABLE_SUFFIX))
1540 {
1541 char *full_exec_name
1542 = alloca (strlen (exec_name) + strlen (HOST_EXECUTABLE_SUFFIX) + 1);
1543
1544 strcpy (full_exec_name, exec_name);
1545 strcat (full_exec_name, HOST_EXECUTABLE_SUFFIX);
1546 return __gnat_locate_regular_file (full_exec_name, path_val);
1547 }
1548 else
1549 return __gnat_locate_regular_file (exec_name, path_val);
1550 }
1551
1552 /* Locate an executable using the Systems default PATH */
1553
1554 char *
1555 __gnat_locate_exec_on_path (exec_name)
1556 char *exec_name;
1557 {
1558 #ifdef VMS
1559 char *path_val = "/VAXC$PATH";
1560 #else
1561 char *path_val = getenv ("PATH");
1562 #endif
1563 char *apath_val = alloca (strlen (path_val) + 1);
1564
1565 strcpy (apath_val, path_val);
1566 return __gnat_locate_exec (exec_name, apath_val);
1567 }
1568
1569 #ifdef VMS
1570
1571 /* These functions are used to translate to and from VMS and Unix syntax
1572 file, directory and path specifications. */
1573
1574 #define MAXNAMES 256
1575 #define NEW_CANONICAL_FILELIST_INCREMENT 64
1576
1577 static char new_canonical_dirspec [255];
1578 static char new_canonical_filespec [255];
1579 static char new_canonical_pathspec [MAXNAMES*255];
1580 static unsigned new_canonical_filelist_index;
1581 static unsigned new_canonical_filelist_in_use;
1582 static unsigned new_canonical_filelist_allocated;
1583 static char **new_canonical_filelist;
1584 static char new_host_pathspec [MAXNAMES*255];
1585 static char new_host_dirspec [255];
1586 static char new_host_filespec [255];
1587
1588 /* Routine is called repeatedly by decc$from_vms via
1589 __gnat_to_canonical_file_list_init until it returns 0 or the expansion
1590 runs out. */
1591
1592 static int
1593 wildcard_translate_unix (name)
1594 char *name;
1595 {
1596 char *ver;
1597 char buff [256];
1598
1599 strcpy (buff, name);
1600 ver = strrchr (buff, '.');
1601
1602 /* Chop off the version */
1603 if (ver)
1604 *ver = 0;
1605
1606 /* Dynamically extend the allocation by the increment */
1607 if (new_canonical_filelist_in_use == new_canonical_filelist_allocated)
1608 {
1609 new_canonical_filelist_allocated += NEW_CANONICAL_FILELIST_INCREMENT;
1610 new_canonical_filelist = (char **) realloc
1611 (new_canonical_filelist,
1612 new_canonical_filelist_allocated * sizeof (char *));
1613 }
1614
1615 new_canonical_filelist[new_canonical_filelist_in_use++] = xstrdup (buff);
1616
1617 return 1;
1618 }
1619
1620 /* Translate a wildcard VMS file spec into a list of Unix file
1621 specs. First do full translation and copy the results into a list (_init),
1622 then return them one at a time (_next). If onlydirs set, only expand
1623 directory files. */
1624
1625 int
1626 __gnat_to_canonical_file_list_init (filespec, onlydirs)
1627 char *filespec;
1628 int onlydirs;
1629 {
1630 int len;
1631 char buff [256];
1632
1633 len = strlen (filespec);
1634 strcpy (buff, filespec);
1635
1636 /* Only look for directories */
1637 if (onlydirs && !strstr (&buff [len-5], "*.dir"))
1638 strcat (buff, "*.dir");
1639
1640 decc$from_vms (buff, wildcard_translate_unix, 1);
1641
1642 /* Remove the .dir extension */
1643 if (onlydirs)
1644 {
1645 int i;
1646 char *ext;
1647
1648 for (i = 0; i < new_canonical_filelist_in_use; i++)
1649 {
1650 ext = strstr (new_canonical_filelist [i], ".dir");
1651 if (ext)
1652 *ext = 0;
1653 }
1654 }
1655
1656 return new_canonical_filelist_in_use;
1657 }
1658
1659 /* Return the next filespec in the list */
1660
1661 char *
1662 __gnat_to_canonical_file_list_next ()
1663 {
1664 return new_canonical_filelist [new_canonical_filelist_index++];
1665 }
1666
1667 /* Free up storage used in the wildcard expansion */
1668
1669 void
1670 __gnat_to_canonical_file_list_free ()
1671 {
1672 int i;
1673
1674 for (i = 0; i < new_canonical_filelist_in_use; i++)
1675 free (new_canonical_filelist [i]);
1676
1677 free (new_canonical_filelist);
1678
1679 new_canonical_filelist_in_use = 0;
1680 new_canonical_filelist_allocated = 0;
1681 new_canonical_filelist_index = 0;
1682 new_canonical_filelist = 0;
1683 }
1684
1685 /* Translate a VMS syntax directory specification in to Unix syntax.
1686 If prefixflag is set, append an underscore "/". If no indicators
1687 of VMS syntax found, return input string. Also translate a dirname
1688 that contains no slashes, in case it's a logical name. */
1689
1690 char *
1691 __gnat_to_canonical_dir_spec (dirspec,prefixflag)
1692 char *dirspec;
1693 int prefixflag;
1694 {
1695 int len;
1696
1697 strcpy (new_canonical_dirspec, "");
1698 if (strlen (dirspec))
1699 {
1700 char *dirspec1;
1701
1702 if (strchr (dirspec, ']') || strchr (dirspec, ':'))
1703 strcpy (new_canonical_dirspec, (char *) decc$translate_vms (dirspec));
1704 else if (!strchr (dirspec, '/') && (dirspec1 = getenv (dirspec)) != 0)
1705 strcpy (new_canonical_dirspec, (char *) decc$translate_vms (dirspec1));
1706 else
1707 strcpy (new_canonical_dirspec, dirspec);
1708 }
1709
1710 len = strlen (new_canonical_dirspec);
1711 if (prefixflag && new_canonical_dirspec [len-1] != '/')
1712 strcat (new_canonical_dirspec, "/");
1713
1714 return new_canonical_dirspec;
1715
1716 }
1717
1718 /* Translate a VMS syntax file specification into Unix syntax.
1719 If no indicators of VMS syntax found, return input string. */
1720
1721 char *
1722 __gnat_to_canonical_file_spec (filespec)
1723 char *filespec;
1724 {
1725 strcpy (new_canonical_filespec, "");
1726 if (strchr (filespec, ']') || strchr (filespec, ':'))
1727 strcpy (new_canonical_filespec, (char *) decc$translate_vms (filespec));
1728 else
1729 strcpy (new_canonical_filespec, filespec);
1730
1731 return new_canonical_filespec;
1732 }
1733
1734 /* Translate a VMS syntax path specification into Unix syntax.
1735 If no indicators of VMS syntax found, return input string. */
1736
1737 char *
1738 __gnat_to_canonical_path_spec (pathspec)
1739 char *pathspec;
1740 {
1741 char *curr, *next, buff [256];
1742
1743 if (pathspec == 0)
1744 return pathspec;
1745
1746 /* If there are /'s, assume it's a Unix path spec and return */
1747 if (strchr (pathspec, '/'))
1748 return pathspec;
1749
1750 new_canonical_pathspec [0] = 0;
1751 curr = pathspec;
1752
1753 for (;;)
1754 {
1755 next = strchr (curr, ',');
1756 if (next == 0)
1757 next = strchr (curr, 0);
1758
1759 strncpy (buff, curr, next - curr);
1760 buff [next - curr] = 0;
1761
1762 /* Check for wildcards and expand if present */
1763 if (strchr (buff, '*') || strchr (buff, '%') || strstr (buff, "..."))
1764 {
1765 int i, dirs;
1766
1767 dirs = __gnat_to_canonical_file_list_init (buff, 1);
1768 for (i = 0; i < dirs; i++)
1769 {
1770 char *next_dir;
1771
1772 next_dir = __gnat_to_canonical_file_list_next ();
1773 strcat (new_canonical_pathspec, next_dir);
1774
1775 /* Don't append the separator after the last expansion */
1776 if (i+1 < dirs)
1777 strcat (new_canonical_pathspec, ":");
1778 }
1779
1780 __gnat_to_canonical_file_list_free ();
1781 }
1782 else
1783 strcat (new_canonical_pathspec,
1784 __gnat_to_canonical_dir_spec (buff, 0));
1785
1786 if (*next == 0)
1787 break;
1788
1789 strcat (new_canonical_pathspec, ":");
1790 curr = next + 1;
1791 }
1792
1793 return new_canonical_pathspec;
1794 }
1795
1796 static char filename_buff [256];
1797
1798 static int
1799 translate_unix (name, type)
1800 char *name;
1801 int type;
1802 {
1803 strcpy (filename_buff, name);
1804 return 0;
1805 }
1806
1807 /* Translate a Unix syntax path spec into a VMS style (comma separated
1808 list of directories. Only used in this file so make it static */
1809
1810 static char *
1811 to_host_path_spec (pathspec)
1812 char *pathspec;
1813 {
1814 char *curr, *next, buff [256];
1815
1816 if (pathspec == 0)
1817 return pathspec;
1818
1819 /* Can't very well test for colons, since that's the Unix separator! */
1820 if (strchr (pathspec, ']') || strchr (pathspec, ','))
1821 return pathspec;
1822
1823 new_host_pathspec [0] = 0;
1824 curr = pathspec;
1825
1826 for (;;)
1827 {
1828 next = strchr (curr, ':');
1829 if (next == 0)
1830 next = strchr (curr, 0);
1831
1832 strncpy (buff, curr, next - curr);
1833 buff [next - curr] = 0;
1834
1835 strcat (new_host_pathspec, __gnat_to_host_dir_spec (buff, 0));
1836 if (*next == 0)
1837 break;
1838 strcat (new_host_pathspec, ",");
1839 curr = next + 1;
1840 }
1841
1842 return new_host_pathspec;
1843 }
1844
1845 /* Translate a Unix syntax directory specification into VMS syntax.
1846 The prefixflag has no effect, but is kept for symmetry with
1847 to_canonical_dir_spec.
1848 If indicators of VMS syntax found, return input string. */
1849
1850 char *
1851 __gnat_to_host_dir_spec (dirspec, prefixflag)
1852 char *dirspec;
1853 int prefixflag;
1854 {
1855 int len = strlen (dirspec);
1856
1857 strcpy (new_host_dirspec, dirspec);
1858
1859 if (strchr (new_host_dirspec, ']') || strchr (new_host_dirspec, ':'))
1860 return new_host_dirspec;
1861
1862 while (len > 1 && new_host_dirspec [len-1] == '/')
1863 {
1864 new_host_dirspec [len-1] = 0;
1865 len--;
1866 }
1867
1868 decc$to_vms (new_host_dirspec, translate_unix, 1, 2);
1869 strcpy (new_host_dirspec, filename_buff);
1870
1871 return new_host_dirspec;
1872
1873 }
1874
1875 /* Translate a Unix syntax file specification into VMS syntax.
1876 If indicators of VMS syntax found, return input string. */
1877
1878 char *
1879 __gnat_to_host_file_spec (filespec)
1880 char *filespec;
1881 {
1882 strcpy (new_host_filespec, "");
1883 if (strchr (filespec, ']') || strchr (filespec, ':'))
1884 strcpy (new_host_filespec, filespec);
1885 else
1886 {
1887 decc$to_vms (filespec, translate_unix, 1, 1);
1888 strcpy (new_host_filespec, filename_buff);
1889 }
1890
1891 return new_host_filespec;
1892 }
1893
1894 void
1895 __gnat_adjust_os_resource_limits ()
1896 {
1897 SYS$ADJWSL (131072, 0);
1898 }
1899
1900 #else
1901
1902 /* Dummy functions for Osint import for non-VMS systems */
1903
1904 int
1905 __gnat_to_canonical_file_list_init (dirspec, onlydirs)
1906 char *dirspec ATTRIBUTE_UNUSED;
1907 int onlydirs ATTRIBUTE_UNUSED;
1908 {
1909 return 0;
1910 }
1911
1912 char *
1913 __gnat_to_canonical_file_list_next ()
1914 {
1915 return (char *) "";
1916 }
1917
1918 void
1919 __gnat_to_canonical_file_list_free ()
1920 {
1921 }
1922
1923 char *
1924 __gnat_to_canonical_dir_spec (dirspec, prefixflag)
1925 char *dirspec;
1926 int prefixflag ATTRIBUTE_UNUSED;
1927 {
1928 return dirspec;
1929 }
1930
1931 char *
1932 __gnat_to_canonical_file_spec (filespec)
1933 char *filespec;
1934 {
1935 return filespec;
1936 }
1937
1938 char *
1939 __gnat_to_canonical_path_spec (pathspec)
1940 char *pathspec;
1941 {
1942 return pathspec;
1943 }
1944
1945 char *
1946 __gnat_to_host_dir_spec (dirspec, prefixflag)
1947 char *dirspec;
1948 int prefixflag ATTRIBUTE_UNUSED;
1949 {
1950 return dirspec;
1951 }
1952
1953 char *
1954 __gnat_to_host_file_spec (filespec)
1955 char *filespec;
1956 {
1957 return filespec;
1958 }
1959
1960 void
1961 __gnat_adjust_os_resource_limits ()
1962 {
1963 }
1964
1965 #endif
1966
1967 /* for EMX, we cannot include dummy in libgcc, since it is too difficult
1968 to coordinate this with the EMX distribution. Consequently, we put the
1969 definition of dummy() which is used for exception handling, here */
1970
1971 #if defined (__EMX__)
1972 void __dummy () {}
1973 #endif
1974
1975 #if defined (__mips_vxworks)
1976 int _flush_cache()
1977 {
1978 CACHE_USER_FLUSH (0, ENTIRE_CACHE);
1979 }
1980 #endif
1981
1982 #if defined (CROSS_COMPILE) \
1983 || (! (defined (sparc) && defined (sun) && defined (__SVR4)) \
1984 && ! defined (linux) \
1985 && ! defined (sgi) \
1986 && ! defined (hpux) \
1987 && ! (defined (__alpha__) && defined (__osf__)) \
1988 && ! defined (__MINGW32__))
1989 /* Dummy function to satisfy g-trasym.o.
1990 Currently Solaris sparc, HP/UX, IRIX, GNU/Linux, Tru64 & Windows provide a
1991 non-dummy version of this procedure in libaddr2line.a */
1992
1993 void
1994 convert_addresses (addrs, n_addr, buf, len)
1995 void *addrs ATTRIBUTE_UNUSED;
1996 int n_addr ATTRIBUTE_UNUSED;
1997 void *buf ATTRIBUTE_UNUSED;
1998 int *len;
1999 {
2000 *len = 0;
2001 }
2002 #endif