OSDN Git Service

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