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