OSDN Git Service

2008-08-20 Thomas Quinot <quinot@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / sysdep.c
1 /****************************************************************************
2  *                                                                          *
3  *                         GNAT COMPILER COMPONENTS                         *
4  *                                                                          *
5  *                                S Y S D E P                               *
6  *                                                                          *
7  *                          C Implementation File                           *
8  *                                                                          *
9  *         Copyright (C) 1992-2008, Free Software Foundation, Inc.          *
10  *                                                                          *
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.                                              *
21  *                                                                          *
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.                        *
27  *                                                                          *
28  * GNAT was originally developed  by the GNAT team at  New York University. *
29  * Extensive contributions were provided by Ada Core Technologies Inc.      *
30  *                                                                          *
31  ****************************************************************************/
32
33 /* This file contains system dependent symbols that are referenced in the
34    GNAT Run Time Library */
35
36 #ifdef __vxworks
37 #include "ioLib.h"
38 #include "dosFsLib.h"
39 #ifndef __RTP__
40 # include "nfsLib.h"
41 #endif
42 #include "selectLib.h"
43 #include "vxWorks.h"
44 #endif
45
46 #ifdef IN_RTS
47 #define POSIX
48 #include "tconfig.h"
49 #include "tsystem.h"
50 #include <fcntl.h>
51 #include <sys/stat.h>
52 #ifdef VMS
53 #include <unixio.h>
54 #endif
55 #else
56 #include "config.h"
57 #include "system.h"
58 #endif
59
60 #include <time.h>
61 #include <errno.h>
62
63 #if defined (sun) && defined (__SVR4) && !defined (__vxworks)
64 /* The declaration is present in <time.h> but conditionalized
65    on a couple of macros we don't define.  */
66 extern struct tm *localtime_r(const time_t *, struct tm *);
67 #endif
68
69 #include "adaint.h"
70
71 /*
72    mode_read_text
73    open text file for reading
74    rt for DOS and Windows NT, r for Unix
75
76    mode_write_text
77    truncate to zero length or create text file for writing
78    wt for DOS and Windows NT, w for Unix
79
80    mode_append_text
81    append; open or create text file for writing at end-of-file
82    at for DOS and Windows NT, a for Unix
83
84    mode_read_binary
85    open binary file for reading
86    rb for DOS and Windows NT, r for Unix
87
88    mode_write_binary
89    truncate to zero length or create binary file for writing
90    wb for DOS and Windows NT, w for Unix
91
92    mode_append_binary
93    append; open or create binary file for writing at end-of-file
94    ab for DOS and Windows NT, a for Unix
95
96    mode_read_text_plus
97    open text file for update (reading and writing)
98    r+t for DOS and Windows NT, r+ for Unix
99
100    mode_write_text_plus
101    truncate to zero length or create text file for update
102    w+t for DOS and Windows NT, w+ for Unix
103
104    mode_append_text_plus
105    append; open or create text file for update, writing at end-of-file
106    a+t for DOS and Windows NT, a+ for Unix
107
108    mode_read_binary_plus
109    open binary file for update (reading and writing)
110    r+b for DOS and Windows NT, r+ for Unix
111
112    mode_write_binary_plus
113    truncate to zero length or create binary file for update
114    w+b for DOS and Windows NT, w+ for Unix
115
116    mode_append_binary_plus
117    append; open or create binary file for update, writing at end-of-file
118    a+b for DOS and Windows NT, a+ for Unix
119
120    Notes:
121
122    (1) Opening a file with read mode fails if the file does not exist or
123    cannot be read.
124
125    (2) Opening a file with append mode causes all subsequent writes to the
126    file to be forced to the then current end-of-file, regardless of
127    intervening calls to the fseek function.
128
129    (3) When a file is opened with update mode, both input and output may be
130    performed on the associated stream.  However, output may not be directly
131    followed by input without an intervening call to the fflush function or
132    to a file positioning function (fseek, fsetpos, or rewind), and input
133    may not be directly followed by output without an intervening call to a
134    file positioning function, unless the input operation encounters
135    end-of-file.
136
137    The other target dependent declarations here are for the two functions
138    __gnat_set_binary_mode and __gnat_set_text_mode:
139
140       void __gnat_set_binary_mode (int handle);
141       void __gnat_set_text_mode   (int handle);
142
143    These functions have no effect in Unix (or similar systems where there is
144    no distinction between binary and text files), but in DOS (and similar
145    systems where text mode does CR/LF translation), these functions allow
146    the mode of the stream with the given handle (fileno can be used to get
147    the handle of a stream) to be changed dynamically. The returned result
148    is 0 if no error occurs and -1 if an error occurs.
149
150    Finally there is a boolean (character) variable
151
152       char __gnat_text_translation_required;
153
154    which is zero (false) in Unix mode, and one (true) in DOS mode, with a
155    true value indicating that text translation is required on text files
156    and that fopen supports the trailing t and b modifiers.
157
158 */
159
160 #if defined(WINNT) || defined (MSDOS) || defined (__EMX__)
161 static const char *mode_read_text = "rt";
162 static const char *mode_write_text = "wt";
163 static const char *mode_append_text = "at";
164 static const char *mode_read_binary = "rb";
165 static const char *mode_write_binary = "wb";
166 static const char *mode_append_binary = "ab";
167 static const char *mode_read_text_plus = "r+t";
168 static const char *mode_write_text_plus = "w+t";
169 static const char *mode_append_text_plus = "a+t";
170 static const char *mode_read_binary_plus = "r+b";
171 static const char *mode_write_binary_plus = "w+b";
172 static const char *mode_append_binary_plus = "a+b";
173 const char __gnat_text_translation_required = 1;
174
175 void
176 __gnat_set_binary_mode (int handle)
177 {
178   _setmode (handle, O_BINARY);
179 }
180
181 void
182 __gnat_set_text_mode (int handle)
183 {
184   _setmode (handle, O_TEXT);
185 }
186
187 #ifdef __MINGW32__
188 #include <windows.h>
189
190 /* Return the name of the tty.   Under windows there is no name for
191    the tty, so this function, if connected to a tty, returns the generic name
192    "console".  */
193
194 char *
195 __gnat_ttyname (int filedes)
196 {
197   if (isatty (filedes))
198     return "console";
199   else
200     return NULL;
201 }
202
203 /* This function is needed to fix a bug under Win95/98. Under these platforms
204    doing :
205                 ch1 = getch();
206                 ch2 = fgetc (stdin);
207
208    will put the same character into ch1 and ch2. It seem that the character
209    read by getch() is not correctly removed from the buffer. Even a
210    fflush(stdin) does not fix the bug. This bug does not appear under Window
211    NT. So we have two version of this routine below one for 95/98 and one for
212    NT/2000 version of Windows. There is also a special routine (winflushinit)
213    that will be called only the first time to check which version of Windows
214    we are running running on to set the right routine to use.
215
216    This problem occurs when using Text_IO.Get_Line after Text_IO.Get_Immediate
217    for example.
218
219    Calling FlushConsoleInputBuffer just after getch() fix the bug under
220    95/98. */
221
222 #ifdef RTX
223
224 static void winflush_nt (void);
225
226 /* winflush_function will do nothing since we only have problems with Windows
227    95/98 which are not supported by RTX. */
228
229 static void (*winflush_function) (void) = winflush_nt;
230
231 static void
232 winflush_nt (void)
233 {
234   /* Does nothing as there is no problem under NT.  */
235 }
236
237 #else
238
239 static void winflush_init (void);
240
241 static void winflush_95 (void);
242
243 static void winflush_nt (void);
244
245 int __gnat_is_windows_xp (void);
246
247 /* winflusfunction is set first to the winflushinit function which will check
248    the OS version 95/98 or NT/2000 */
249
250 static void (*winflush_function) (void) = winflush_init;
251
252 /* This function does the runtime check of the OS version and then sets
253    winflush_function to the appropriate function and then call it. */
254
255 static void
256 winflush_init (void)
257 {
258   DWORD dwVersion = GetVersion();
259
260   if (dwVersion < 0x80000000)                /* Windows NT/2000 */
261     winflush_function = winflush_nt;
262   else                                       /* Windows 95/98   */
263     winflush_function = winflush_95;
264
265   (*winflush_function)();      /* Perform the 'flush' */
266
267 }
268
269 static void
270 winflush_95 (void)
271 {
272   FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
273 }
274
275 static void
276 winflush_nt (void)
277 {
278   /* Does nothing as there is no problem under NT.  */
279 }
280
281 int
282 __gnat_is_windows_xp (void)
283 {
284   static int is_win_xp=0, is_win_xp_checked=0;
285
286   if (!is_win_xp_checked)
287     {
288       OSVERSIONINFO version;
289
290       is_win_xp_checked = 1;
291
292       memset (&version, 0, sizeof (version));
293       version.dwOSVersionInfoSize = sizeof (version);
294
295       is_win_xp = GetVersionEx (&version)
296         && version.dwPlatformId == VER_PLATFORM_WIN32_NT
297         && (version.dwMajorVersion > 5
298             || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
299     }
300   return is_win_xp;
301 }
302
303 #endif
304
305 #endif
306
307 #else
308
309 static const char *mode_read_text = "r";
310 static const char *mode_write_text = "w";
311 static const char *mode_append_text = "a";
312 static const char *mode_read_binary = "r";
313 static const char *mode_write_binary = "w";
314 static const char *mode_append_binary = "a";
315 static const char *mode_read_text_plus = "r+";
316 static const char *mode_write_text_plus = "w+";
317 static const char *mode_append_text_plus = "a+";
318 static const char *mode_read_binary_plus = "r+";
319 static const char *mode_write_binary_plus = "w+";
320 static const char *mode_append_binary_plus = "a+";
321 const char __gnat_text_translation_required = 0;
322
323 /* These functions do nothing in non-DOS systems. */
324
325 void
326 __gnat_set_binary_mode (int handle ATTRIBUTE_UNUSED)
327 {
328 }
329
330 void
331 __gnat_set_text_mode (int handle ATTRIBUTE_UNUSED)
332 {
333 }
334 char *
335 __gnat_ttyname (int filedes)
336 {
337 #if defined (__vxworks) || defined (__nucleus)
338   return "";
339 #else
340   extern char *ttyname (int);
341
342   return ttyname (filedes);
343 #endif /* defined (__vxworks) || defined (__nucleus) */
344 }
345 #endif
346 \f
347 #if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
348   || (defined (__osf__) && ! defined (__alpha_vxworks)) || defined (WINNT) \
349   || defined (__MACHTEN__) || defined (__hpux__) || defined (_AIX) \
350   || (defined (__svr4__) && defined (i386)) || defined (__Lynx__) \
351   || defined (__CYGWIN__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
352   || defined (__GLIBC__)
353
354 #ifdef __MINGW32__
355 #if OLD_MINGW
356 #include <termios.h>
357 #else
358 #include <conio.h>  /* for getch(), kbhit() */
359 #endif
360 #else
361 #include <termios.h>
362 #endif
363
364 #else
365 #if defined (VMS)
366 extern char *decc$ga_stdscr;
367 static int initted = 0;
368 #endif
369 #endif
370
371 /* Implements the common processing for getc_immediate and
372    getc_immediate_nowait. */
373
374 extern void getc_immediate (FILE *, int *, int *);
375 extern void getc_immediate_nowait (FILE *, int *, int *, int *);
376 extern void getc_immediate_common (FILE *, int *, int *, int *, int);
377
378 /* Called by Get_Immediate (Foo); */
379
380 void
381 getc_immediate (FILE *stream, int *ch, int *end_of_file)
382 {
383   int avail;
384
385   getc_immediate_common (stream, ch, end_of_file, &avail, 1);
386 }
387
388 /* Called by Get_Immediate (Foo, Available); */
389
390 void
391 getc_immediate_nowait (FILE *stream, int *ch, int *end_of_file, int *avail)
392 {
393   getc_immediate_common (stream, ch, end_of_file, avail, 0);
394 }
395
396 /* Called by getc_immediate () and getc_immediate_nowait () */
397
398 void
399 getc_immediate_common (FILE *stream,
400                        int *ch,
401                        int *end_of_file,
402                        int *avail,
403                        int waiting)
404 {
405 #if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
406     || (defined (__osf__) && ! defined (__alpha_vxworks)) \
407     || defined (__CYGWIN32__) || defined (__MACHTEN__) || defined (__hpux__) \
408     || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
409     || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
410     || defined (__GLIBC__)
411   char c;
412   int nread;
413   int good_one = 0;
414   int eof_ch = 4; /* Ctrl-D */
415   int fd = fileno (stream);
416   struct termios otermios_rec, termios_rec;
417
418   if (isatty (fd))
419     {
420       tcgetattr (fd, &termios_rec);
421       memcpy (&otermios_rec, &termios_rec, sizeof (struct termios));
422
423       /* Set RAW mode, with no echo */
424       termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON & ~ECHO;
425
426 #if defined(linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
427     || defined (__osf__) || defined (__MACHTEN__) || defined (__hpux__) \
428     || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
429     || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
430     || defined (__GLIBC__)
431       eof_ch = termios_rec.c_cc[VEOF];
432
433       /* If waiting (i.e. Get_Immediate (Char)), set MIN = 1 and wait for
434          a character forever. This doesn't seem to effect Ctrl-Z or
435          Ctrl-C processing except on OS/2 where Ctrl-C won't work right
436          unless we do a read loop. Luckily we can delay a bit between
437          iterations. If not waiting (i.e. Get_Immediate (Char, Available)),
438          don't wait for anything but timeout immediately. */
439 #ifdef __EMX__
440       termios_rec.c_cc[VMIN] = 0;
441       termios_rec.c_cc[VTIME] = waiting;
442 #else
443       termios_rec.c_cc[VMIN] = waiting;
444       termios_rec.c_cc[VTIME] = 0;
445 #endif
446 #endif
447       tcsetattr (fd, TCSANOW, &termios_rec);
448
449       while (! good_one)
450         {
451           /* Read is used here instead of fread, because fread doesn't
452              work on Solaris5 and Sunos4 in this situation.  Maybe because we
453              are mixing calls that use file descriptors and streams. */
454           nread = read (fd, &c, 1);
455           if (nread > 0)
456             {
457               /* On Unix terminals, Ctrl-D (EOT) is an End of File. */
458               if (c == eof_ch)
459                 {
460                   *avail = 0;
461                   *end_of_file = 1;
462                   good_one = 1;
463                 }
464
465               /* Everything else is ok */
466               else if (c != eof_ch)
467                 {
468                   *avail = 1;
469                   *end_of_file = 0;
470                   good_one = 1;
471                 }
472             }
473
474           else if (! waiting)
475             {
476               *avail = 0;
477               *end_of_file = 0;
478               good_one = 1;
479             }
480           else
481             good_one = 0;
482         }
483
484       tcsetattr (fd, TCSANOW, &otermios_rec);
485       *ch = c;
486     }
487
488   else
489 #elif defined (VMS)
490   int fd = fileno (stream);
491
492   if (isatty (fd))
493     {
494       if (initted == 0)
495         {
496           decc$bsd_initscr ();
497           initted = 1;
498         }
499
500       decc$bsd_cbreak ();
501       *ch = decc$bsd_wgetch (decc$ga_stdscr);
502
503       if (*ch == 4)
504         *end_of_file = 1;
505       else
506         *end_of_file = 0;
507
508       *avail = 1;
509       decc$bsd_nocbreak ();
510     }
511   else
512 #elif defined (__MINGW32__)
513   int fd = fileno (stream);
514   int char_waiting;
515   int eot_ch = 4; /* Ctrl-D */
516
517   if (isatty (fd))
518     {
519       if (waiting)
520         {
521           *ch = getch ();
522           (*winflush_function) ();
523
524           if (*ch == eot_ch)
525             *end_of_file = 1;
526           else
527             *end_of_file = 0;
528
529           *avail = 1;
530         }
531       else /* ! waiting */
532         {
533           char_waiting = kbhit();
534
535           if (char_waiting == 1)
536             {
537               *avail = 1;
538               *ch = getch ();
539               (*winflush_function) ();
540
541               if (*ch == eot_ch)
542                 *end_of_file = 1;
543               else
544                 *end_of_file = 0;
545             }
546           else
547             {
548               *avail = 0;
549               *end_of_file = 0;
550             }
551         }
552     }
553   else
554 #elif defined (__vxworks)
555   /* Bit masks of file descriptors to read from.  */
556   struct fd_set readFds;
557   /* Timeout before select returns if nothing can be read.  */
558   struct timeval timeOut;
559   char c;
560   int fd = fileno (stream);
561   int nread;
562   int option;
563   int readable;
564   int status;
565   int width;
566
567   if (isatty (fd))
568     {
569       /* If we do not want to wait, we have to set up fd in RAW mode. This
570          should be done outside this function as setting fd in RAW mode under
571          vxWorks flushes the buffer of fd. If the RAW mode was set here, the
572          buffer would be empty and we would always return that no character
573          is available */
574       if (! waiting)
575         {
576           /* Initialization of timeOut for its use with select.  */
577           timeOut.tv_sec  = 0;
578           timeOut.tv_usec = 0;
579
580           /* Initialization of readFds for its use with select;
581              FD is the only file descriptor to be monitored */
582           FD_ZERO (&readFds);
583           FD_SET (fd, &readFds);
584           width = 2;
585
586           /* We do all this processing to emulate a non blocking read.  */
587           readable = select (width, &readFds, NULL, NULL, &timeOut);
588           if (readable == ERROR)
589             *avail = -1, *end_of_file = -1;
590           /* No character available in input.  */
591           else if (readable == 0)
592             *avail = 0, *end_of_file = 0;
593           else
594             {
595               nread = read (fd, &c, 1);
596               if (nread > 0)
597                 *avail = 1, *end_of_file = 0;
598               /* End Of File. */
599               else if (nread == 0)
600                 *avail = 0, *end_of_file = 1;
601               /* Error.  */
602               else
603                 *avail = -1, *end_of_file = -1;
604             }
605         }
606
607       /* We have to wait until we get a character */
608       else
609         {
610           *avail = -1;
611           *end_of_file = -1;
612
613           /* Save the current mode of FD.  */
614           option = ioctl (fd, FIOGETOPTIONS, 0);
615
616           /* Set FD in RAW mode.  */
617           status = ioctl (fd, FIOSETOPTIONS, OPT_RAW);
618           if (status != -1)
619             {
620               nread = read (fd, &c, 1);
621               if (nread > 0)
622                 *avail = 1, *end_of_file = 0;
623               /* End of file.  */
624               else if (nread == 0)
625                 *avail = 0, *end_of_file = 1;
626               /* Else there is an ERROR.  */
627             }
628
629           /* Revert FD to its previous mode. */
630           status = ioctl (fd, FIOSETOPTIONS, option);
631         }
632
633       *ch = c;
634     }
635   else
636 #endif
637     {
638       /* If we're not on a terminal, then we don't need any fancy processing.
639          Also this is the only thing that's left if we're not on one of the
640          supported systems; which means that for non supported systems,
641          get_immediate may wait for a carriage return on terminals. */
642       *ch = fgetc (stream);
643       if (feof (stream))
644         {
645           *end_of_file = 1;
646           *avail = 0;
647         }
648       else
649         {
650           *end_of_file = 0;
651           *avail = 1;
652         }
653     }
654 }
655
656 /* The following definitions are provided in NT to support Windows based
657    Ada programs.  */
658
659 #ifdef WINNT
660 #include <windows.h>
661
662 /* Provide functions to echo the values passed to WinMain (windows bindings
663    will want to import these).  We use the same names as the routines used
664    by AdaMagic for compatibility.  */
665
666 char *rts_get_hInstance (void);
667 char *rts_get_hPrevInstance (void);
668 char *rts_get_lpCommandLine (void);
669 int   rts_get_nShowCmd (void);
670
671 char *
672 rts_get_hInstance (void)
673 {
674   return (char *)GetModuleHandleA (0);
675 }
676
677 char *
678 rts_get_hPrevInstance (void)
679 {
680   return 0;
681 }
682
683 char *
684 rts_get_lpCommandLine (void)
685 {
686   return GetCommandLineA ();
687 }
688
689 int
690 rts_get_nShowCmd (void)
691 {
692   return 1;
693 }
694
695 #endif /* WINNT */
696 #ifdef VMS
697
698 /* This gets around a problem with using the old threads library on VMS 7.0. */
699
700 extern long get_gmtoff (void);
701
702 long
703 get_gmtoff (void)
704 {
705   time_t t;
706   struct tm *ts;
707
708   t = time ((time_t) 0);
709   ts = localtime (&t);
710   return ts->tm_gmtoff;
711 }
712 #endif
713
714 /* This value is returned as the time zone offset when a valid value
715    cannot be determined. It is simply a bizarre value that will never
716    occur. It is 3 days plus 73 seconds (offset is in seconds). */
717
718 long __gnat_invalid_tzoff = 259273;
719
720 /* Definition of __gnat_localtime_r used by a-calend.adb */
721
722 #if defined (__EMX__) || defined (__MINGW32__)
723
724 #ifdef CERT
725
726 /* For the Cert run times on native Windows we use dummy functions
727    for locking and unlocking tasks since we do not support multiple
728    threads on this configuration (Cert run time on native Windows). */
729
730 void dummy (void) {}
731
732 void (*Lock_Task) ()   = &dummy;
733 void (*Unlock_Task) () = &dummy;
734
735 #else
736
737 #define Lock_Task system__soft_links__lock_task
738 extern void (*Lock_Task) (void);
739
740 #define Unlock_Task system__soft_links__unlock_task
741 extern void (*Unlock_Task) (void);
742
743 #endif
744
745 /* Reentrant localtime for Windows and OS/2. */
746
747 extern struct tm *
748 __gnat_localtime_tzoff (const time_t *, struct tm *, long *);
749
750 struct tm *
751 __gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
752 {
753   DWORD dwRet;
754   struct tm *tmp;
755   TIME_ZONE_INFORMATION tzi;
756
757   (*Lock_Task) ();
758   tmp = localtime (timer);
759   memcpy (tp, tmp, sizeof (struct tm));
760   dwRet = GetTimeZoneInformation (&tzi);
761   *off = tzi.Bias;
762   if (tp->tm_isdst > 0)
763     *off = *off + tzi.DaylightBias;
764   *off = *off * -60;
765   (*Unlock_Task) ();
766   return tp;
767 }
768
769 #else
770 #if defined (__Lynx__) && defined (___THREADS_POSIX4ad4__)
771
772 /* As of LynxOS 3.1.0a patch level 040, LynuxWorks changes the
773    prototype to the C library function localtime_r from the POSIX.4
774    Draft 9 to the POSIX 1.c version. Before this change the following
775    spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
776    the Lynx convention when building against the legacy API. */
777
778 extern struct tm *
779 __gnat_localtime_tzoff (const time_t *, struct tm *, long *);
780
781 struct tm *
782 __gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
783 {
784   /* Treat all time values in GMT */
785   localtime_r (tp, timer);
786   *off = 0;
787   return NULL;
788 }
789
790 #else
791 #if defined (VMS)
792
793 /* __gnat_localtime_tzoff is not needed on VMS */
794
795 #else
796
797 /* All other targets provide a standard localtime_r */
798
799 extern struct tm *
800 __gnat_localtime_tzoff (const time_t *, struct tm *, long *);
801
802 struct tm *
803 __gnat_localtime_tzoff (const time_t *timer, struct tm *tp, long *off)
804 {
805    localtime_r (timer, tp);
806
807 /* AIX, HPUX, SGI Irix, Sun Solaris */
808 #if defined (_AIX) || defined (__hpux__) || defined (sgi) || defined (sun)
809   /* The contents of external variable "timezone" may not always be
810      initialized. Instead of returning an incorrect offset, treat the local
811      time zone as 0 (UTC). The value of 28 hours is the maximum valid offset
812      allowed by Ada.Calendar.Time_Zones. */
813   if ((timezone < -28 * 3600) || (timezone > 28 * 3600))
814     *off = 0;
815   else
816   {
817     *off = (long) -timezone;
818     if (tp->tm_isdst > 0)
819       *off = *off + 3600;
820    }
821 /* Lynx - Treat all time values in GMT */
822 #elif defined (__Lynx__)
823   *off = 0;
824
825 /* VxWorks */
826 #elif defined (__vxworks)
827 #include <stdlib.h>
828 {
829   /* Try to read the environment variable TIMEZONE. The variable may not have
830      been initialize, in that case return an offset of zero (0) for UTC. */
831   char *tz_str = getenv ("TIMEZONE");
832
833   if ((tz_str == NULL) || (*tz_str == '\0'))
834     *off = 0;
835   else
836   {
837     char *tz_start, *tz_end;
838
839     /* The format of the data contained in TIMEZONE is N::U:S:E where N is the
840        name of the time zone, U are the minutes difference from UTC, S is the
841        start of DST in mmddhh and E is the end of DST in mmddhh. Extracting
842        the value of U involves setting two pointers, one at the beginning and
843        one at the end of the value. The end pointer is then set to null in
844        order to delimit a string slice for atol to process. */
845     tz_start = index (tz_str, ':') + 2;
846     tz_end = index (tz_start, ':');
847     tz_end = '\0';
848
849     /* The Ada layer expects an offset in seconds */
850     *off = atol (tz_start) * 60;
851   }
852 }
853
854 /* Darwin, Free BSD, Linux, Tru64, where there exists a component tm_gmtoff
855    in struct tm */
856 #elif defined (__APPLE__) || defined (__FreeBSD__) || defined (linux) ||\
857      (defined (__alpha__) && defined (__osf__)) || defined (__GLIBC__)
858   *off = tp->tm_gmtoff;
859
860 /* All other platforms: Treat all time values in GMT */
861 #else
862   *off = 0;
863 #endif
864    return NULL;
865 }
866
867 #endif
868 #endif
869 #endif
870
871 #ifdef __vxworks
872
873 #include <taskLib.h>
874
875 /* __gnat_get_task_options is used by s-taprop.adb only for VxWorks. This
876    function returns the options to be set when creating a new task. It fetches
877    the options assigned to the current task (parent), so offering some user
878    level control over the options for a task hierarchy. It forces VX_FP_TASK
879    because it is almost always required. */
880 extern int __gnat_get_task_options (void);
881
882 int
883 __gnat_get_task_options (void)
884 {
885   int options;
886
887   /* Get the options for the task creator */
888   taskOptionsGet (taskIdSelf (), &options);
889
890   /* Force VX_FP_TASK because it is almost always required */
891   options |= VX_FP_TASK;
892
893   /* Mask those bits that are not under user control */
894 #ifdef VX_USR_TASK_OPTIONS
895   return options & VX_USR_TASK_OPTIONS;
896 #else
897   return options;
898 #endif
899 }
900
901 #endif
902
903 int
904 __gnat_is_file_not_found_error (int errno_val) {
905    switch (errno_val) {
906       case ENOENT:
907 #ifdef __vxworks
908       /* In the case of VxWorks, we also have to take into account various
909        * filesystem-specific variants of this error.
910        */
911       case S_dosFsLib_FILE_NOT_FOUND:
912 #ifndef __RTP__
913       case S_nfsLib_NFSERR_NOENT:
914 #endif
915 #endif
916          return 1;
917
918       default:
919          return 0;
920    }
921 }