OSDN Git Service

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