OSDN Git Service

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