OSDN Git Service

2012-01-23 Robert Dewar <dewar@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-2012, 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 *, const int *, long *);
648
649 static const unsigned long long w32_epoch_offset = 11644473600ULL;
650 void
651 __gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
652 {
653   TIME_ZONE_INFORMATION tzi;
654
655   BOOL  rtx_active;
656   DWORD tzi_status;
657
658 #ifdef RTX
659   rtx_active = 1;
660 #else
661   rtx_active = 0;
662 #endif
663
664   (*Lock_Task) ();
665
666   tzi_status = GetTimeZoneInformation (&tzi);
667
668   /* Processing for RTX targets or cases where we simply want to extract the
669      offset of the current time zone, regardless of the date. */
670
671   if (rtx_active || !is_historic) {
672     *off = tzi.Bias;
673
674     /* The system is operating in the range covered by the StandardDate
675        member. */
676     if (tzi_status == TIME_ZONE_ID_STANDARD) {
677        *off = *off + tzi.StandardBias;
678     }
679
680     /* The system is operating in the range covered by the DaylightDate
681        member. */
682     else if (tzi_status == TIME_ZONE_ID_DAYLIGHT) {
683        *off = *off + tzi.DaylightBias;
684     }
685
686     *off = *off * -60;
687   }
688
689   /* Time zone offset calculations for a historic or future date */
690
691   else {
692     union
693     {
694       FILETIME ft_time;
695       unsigned long long ull_time;
696     } utc_time, local_time;
697
698     SYSTEMTIME utc_sys_time, local_sys_time;
699     BOOL status;
700
701     /* First convert unix time_t structure to windows FILETIME format.  */
702     utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset)
703                         * 10000000ULL;
704
705     /* If GetTimeZoneInformation does not return a value between 0 and 2 then
706        it means that we were not able to retrieve timezone informations. Note
707        that we cannot use here FileTimeToLocalFileTime as Windows will use in
708        always in this case the current timezone setting. As suggested on MSDN
709        we use the following three system calls to get the right information.
710        Note also that starting with Windows Vista new functions are provided
711        to get timezone settings that depend on the year. We cannot use them as
712        we still support Windows XP and Windows 2003.  */
713
714     status = (tzi_status >= 0 && tzi_status <= 2)
715       && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time)
716       && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time)
717       && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time);
718
719     /* An error has occured, return invalid_tzoff */
720
721     if (!status) {
722       *off = __gnat_invalid_tzoff;
723     }
724     else {
725       if (local_time.ull_time > utc_time.ull_time) {
726         *off = (long) ((local_time.ull_time - utc_time.ull_time)
727                / 10000000ULL);
728       }
729       else {
730         *off = - (long) ((utc_time.ull_time - local_time.ull_time)
731                / 10000000ULL);
732       }
733     }
734   }
735
736   (*Unlock_Task) ();
737 }
738
739 #else
740
741 /* On Lynx, all time values are treated in GMT */
742
743 #if defined (__Lynx__)
744
745 /* As of LynxOS 3.1.0a patch level 040, LynuxWorks changes the
746    prototype to the C library function localtime_r from the POSIX.4
747    Draft 9 to the POSIX 1.c version. Before this change the following
748    spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
749    the Lynx convention when building against the legacy API. */
750
751 extern void
752 __gnat_localtime_tzoff (const time_t *, const int *, long *);
753
754 void
755 __gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
756 {
757   *off = 0;
758 }
759
760 #else
761
762 /* VMS does not need __gnat_localtime_tzoff */
763
764 #if defined (VMS)
765
766 /* Other targets except Lynx, VMS and Windows provide a standard localtime_r */
767
768 #else
769
770 #define Lock_Task system__soft_links__lock_task
771 extern void (*Lock_Task) (void);
772
773 #define Unlock_Task system__soft_links__unlock_task
774 extern void (*Unlock_Task) (void);
775
776 extern void
777 __gnat_localtime_tzoff (const time_t *, const int *, long *);
778
779 void
780 __gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
781 {
782   struct tm tp;
783
784 /* AIX, HPUX, SGI Irix, Sun Solaris */
785 #if defined (_AIX) || defined (__hpux__) || defined (sgi) || defined (sun)
786 {
787   (*Lock_Task) ();
788
789   localtime_r (timer, &tp);
790   *off = (long) -timezone;
791
792   (*Unlock_Task) ();
793
794   /* Correct the offset if Daylight Saving Time is in effect */
795
796   if (tp.tm_isdst > 0)
797     *off = *off + 3600;
798 }
799
800 /* VxWorks */
801 #elif defined (__vxworks)
802 #include <stdlib.h>
803 {
804   (*Lock_Task) ();
805
806   localtime_r (timer, &tp);
807
808   /* Try to read the environment variable TIMEZONE. The variable may not have
809      been initialize, in that case return an offset of zero (0) for UTC. */
810
811   char *tz_str = getenv ("TIMEZONE");
812
813   if ((tz_str == NULL) || (*tz_str == '\0'))
814     *off = 0;
815   else
816   {
817     char *tz_start, *tz_end;
818
819     /* The format of the data contained in TIMEZONE is N::U:S:E where N is the
820        name of the time zone, U are the minutes difference from UTC, S is the
821        start of DST in mmddhh and E is the end of DST in mmddhh. Extracting
822        the value of U involves setting two pointers, one at the beginning and
823        one at the end of the value. The end pointer is then set to null in
824        order to delimit a string slice for atol to process. */
825
826     tz_start = index (tz_str, ':') + 2;
827     tz_end = index (tz_start, ':');
828     tz_end = '\0';
829
830     /* The Ada layer expects an offset in seconds. Note that we must reverse
831        the sign of the result since west is positive and east is negative on
832        VxWorks targets. */
833
834     *off = -atol (tz_start) * 60;
835
836     /* Correct the offset if Daylight Saving Time is in effect */
837
838     if (tp.tm_isdst > 0)
839       *off = *off + 3600;
840   }
841
842   (*Unlock_Task) ();
843 }
844
845 /* Darwin, Free BSD, Linux, Tru64, where component tm_gmtoff is present in
846    struct tm */
847
848 #elif defined (__APPLE__) || defined (__FreeBSD__) || defined (linux) ||\
849      (defined (__alpha__) && defined (__osf__)) || defined (__GLIBC__)
850 {
851   localtime_r (timer, &tp);
852   *off = tp.tm_gmtoff;
853 }
854
855 /* Default: treat all time values in GMT */
856
857 #else
858   *off = 0;
859
860 #endif
861 }
862
863 #endif
864 #endif
865 #endif
866
867 #ifdef __vxworks
868
869 #include <taskLib.h>
870
871 /* __gnat_get_task_options is used by s-taprop.adb only for VxWorks. This
872    function returns the options to be set when creating a new task. It fetches
873    the options assigned to the current task (parent), so offering some user
874    level control over the options for a task hierarchy. It forces VX_FP_TASK
875    because it is almost always required. On processors with the SPE
876    category, VX_SPE_TASK should be used instead to enable the SPE. */
877 extern int __gnat_get_task_options (void);
878
879 int
880 __gnat_get_task_options (void)
881 {
882   int options;
883
884   /* Get the options for the task creator */
885   taskOptionsGet (taskIdSelf (), &options);
886
887   /* Force VX_FP_TASK or VX_SPE_TASK as needed */
888 #if defined (__SPE__)
889   options |= VX_SPE_TASK;
890 #else
891   options |= VX_FP_TASK;
892 #endif
893
894   /* Mask those bits that are not under user control */
895 #ifdef VX_USR_TASK_OPTIONS
896   return options & VX_USR_TASK_OPTIONS;
897 #else
898   return options;
899 #endif
900 }
901
902 #endif
903
904 int
905 __gnat_is_file_not_found_error (int errno_val) {
906    switch (errno_val) {
907       case ENOENT:
908 #ifdef __vxworks
909       /* In the case of VxWorks, we also have to take into account various
910        * filesystem-specific variants of this error.
911        */
912 #if ! defined (VTHREADS)
913       case S_dosFsLib_FILE_NOT_FOUND:
914 #endif
915 #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
916       case S_nfsLib_NFSERR_NOENT:
917 #endif
918 #endif
919          return 1;
920
921       default:
922          return 0;
923    }
924 }