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