tree-ssa-pre.c/115214(ICE in find_or_generate_expression, at tree-ssa-pre.c:2780...
[official-gcc.git] / gcc / ada / sysdep.c
blob443b11f430236a68ffdb50ac3f090a339b9c22dc
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * S Y S D E P *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 1992-2024, 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 ****************************************************************************/
32 /* This file contains system dependent symbols that are referenced in the
33 GNAT Run Time Library */
35 #ifdef __vxworks
36 #include "vxWorks.h"
37 #include "ioLib.h"
38 #if ! defined (VTHREADS)
39 #include "dosFsLib.h"
40 #endif
41 #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
42 # include "nfsLib.h"
43 #endif
44 #include "selectLib.h"
45 #include "version.h"
46 #if defined (__RTP__)
47 # include "vwModNum.h"
48 #endif /* __RTP__ */
49 #endif
51 #ifdef __ANDROID__
52 #undef __linux__
53 #endif
55 #ifdef IN_RTS
56 #define POSIX
57 #include "runtime.h"
58 #include <string.h>
59 #include <unistd.h>
61 #include <fcntl.h>
62 #include <sys/stat.h>
63 #else
64 #include "config.h"
65 #include "system.h"
66 #endif
68 #include <time.h>
69 #include <errno.h>
71 #if defined (__sun__) && !defined (__vxworks)
72 /* The declaration is present in <time.h> but conditionalized
73 on a couple of macros we don't define. */
74 extern struct tm *localtime_r(const time_t *, struct tm *);
75 #endif
77 #include "adaint.h"
79 /* Don't use macros versions of this functions on VxWorks since they cause
80 imcompatible changes in some VxWorks versions */
81 #ifdef __vxworks
82 #undef getchar
83 #undef putchar
84 #undef feof
85 #undef ferror
86 #undef fileno
87 #endif
90 Notes:
92 (1) Opening a file with read mode fails if the file does not exist or
93 cannot be read.
95 (2) Opening a file with append mode causes all subsequent writes to the
96 file to be forced to the then current end-of-file, regardless of
97 intervening calls to the fseek function.
99 (3) When a file is opened with update mode, both input and output may be
100 performed on the associated stream. However, output may not be directly
101 followed by input without an intervening call to the fflush function or
102 to a file positioning function (fseek, fsetpos, or rewind), and input
103 may not be directly followed by output without an intervening call to a
104 file positioning function, unless the input operation encounters
105 end-of-file.
107 The other target dependent declarations here are for the three functions
108 __gnat_set_binary_mode, __gnat_set_text_mode and __gnat_set_mode:
110 void __gnat_set_binary_mode (int handle);
111 void __gnat_set_text_mode (int handle);
112 void __gnat_set_mode (int handle, int mode);
114 These functions have no effect in Unix (or similar systems where there is
115 no distinction between binary and text files), but in DOS (and similar
116 systems where text mode does CR/LF translation), these functions allow
117 the mode of the stream with the given handle (fileno can be used to get
118 the handle of a stream) to be changed dynamically. The returned result
119 is 0 if no error occurs and -1 if an error occurs.
121 Finally there is a boolean (character) variable
123 char __gnat_text_translation_required;
125 which is zero (false) in Unix mode, and one (true) in DOS mode, with a
126 true value indicating that text translation is required on text files
127 and that fopen supports the trailing t and b modifiers.
131 #if defined (WINNT) || defined (__CYGWIN__) || defined (__DJGPP__)
133 const char __gnat_text_translation_required = 1;
135 #ifdef __CYGWIN__
136 #define WIN_SETMODE setmode
137 #include <io.h>
138 #else
139 #define WIN_SETMODE _setmode
140 #endif
142 #if defined (__DJGPP__)
143 #include <io.h>
144 #define _setmode setmode
145 #endif /* __DJGPP__ */
147 void
148 __gnat_set_binary_mode (int handle)
150 WIN_SETMODE (handle, O_BINARY);
153 void
154 __gnat_set_text_mode (int handle)
156 WIN_SETMODE (handle, O_TEXT);
159 #if defined (__CYGWIN__) || defined (__DJGPP__)
160 void
161 __gnat_set_mode (int handle, int mode)
163 /* the values here must be synchronized with
164 System.File_Control_Block.Content_Encodding:
166 None = 0
167 Default_Text = 1
168 Text = 2
169 U8text = 3
170 Wtext = 4
171 U16text = 5 */
173 switch (mode) {
174 case 0 : setmode(handle, O_BINARY); break;
175 case 1 : setmode(handle, O_TEXT); break;
176 case 2 : setmode(handle, O_TEXT); break;
177 case 3 : setmode(handle, O_TEXT); break;
178 case 4 : setmode(handle, O_BINARY); break;
179 case 5 : setmode(handle, O_BINARY); break;
182 #else
183 void
184 __gnat_set_mode (int handle, int mode)
186 /* the values here must be synchronized with
187 System.File_Control_Block.Content_Encodding:
189 None = 0
190 Default_Text = 1
191 Text = 2
192 U8text = 3
193 Wtext = 4
194 U16text = 5 */
196 switch (mode) {
197 case 0 : WIN_SETMODE (handle, _O_BINARY); break;
198 case 1 : WIN_SETMODE (handle, __gnat_current_ccs_encoding); break;
199 case 2 : WIN_SETMODE (handle, _O_TEXT); break;
200 case 3 : WIN_SETMODE (handle, _O_U8TEXT); break;
201 case 4 : WIN_SETMODE (handle, _O_WTEXT); break;
202 case 5 : WIN_SETMODE (handle, _O_U16TEXT); break;
205 #endif
207 #ifdef __CYGWIN__
209 char *
210 __gnat_ttyname (int filedes)
212 extern char *ttyname (int);
214 return ttyname (filedes);
217 #endif /* __CYGWIN__ */
219 #if defined (__CYGWIN__) || defined (__MINGW32__)
220 #define WIN32_LEAN_AND_MEAN
221 #include <windows.h>
223 int __gnat_is_windows_xp (void);
226 __gnat_is_windows_xp (void)
228 static int is_win_xp=0, is_win_xp_checked=0;
230 if (!is_win_xp_checked)
232 OSVERSIONINFO version;
234 is_win_xp_checked = 1;
236 memset (&version, 0, sizeof (version));
237 version.dwOSVersionInfoSize = sizeof (version);
239 is_win_xp = GetVersionEx (&version)
240 && version.dwPlatformId == VER_PLATFORM_WIN32_NT
241 && (version.dwMajorVersion > 5
242 || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
244 return is_win_xp;
247 /* Get the bounds of the stack. The stack pointer is supposed to be
248 initialized to BASE when a thread is created and the stack can be extended
249 to LIMIT before reaching a guard page.
250 Note: for the main thread, the system automatically extend the stack, so
251 LIMIT is only the current limit. */
253 void
254 __gnat_get_stack_bounds (void **base, void **limit)
256 NT_TIB *tib;
258 /* We know that the first field of the TEB is the TIB. */
259 tib = (NT_TIB *)NtCurrentTeb ();
261 *base = tib->StackBase;
262 *limit = tib->StackLimit;
265 #endif /* __CYGWIN__ || __MINGW32__ */
267 #ifdef __MINGW32__
269 /* Return the name of the tty. Under windows there is no name for
270 the tty, so this function, if connected to a tty, returns the generic name
271 "console". */
273 char *
274 __gnat_ttyname (int filedes)
276 if (isatty (filedes))
277 return "console";
278 else
279 return NULL;
282 #endif /* __MINGW32__ */
284 #else
286 const char __gnat_text_translation_required = 0;
288 /* These functions do nothing in non-DOS systems. */
290 void
291 __gnat_set_binary_mode (int handle ATTRIBUTE_UNUSED)
295 void
296 __gnat_set_text_mode (int handle ATTRIBUTE_UNUSED)
300 void
301 __gnat_set_mode (int handle ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
305 char *
306 __gnat_ttyname (int filedes ATTRIBUTE_UNUSED)
308 #if defined (__vxworks)
309 return "";
310 #else
311 extern char *ttyname (int);
313 return ttyname (filedes);
314 #endif /* defined (__vxworks) */
316 #endif
318 #if defined (__linux__) || defined (__sun__) \
319 || defined (WINNT) \
320 || defined (__MACHTEN__) || defined (__hpux__) || defined (_AIX) \
321 || (defined (__svr4__) && defined (__i386__)) || defined (__Lynx__) \
322 || defined (__CYGWIN__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
323 || defined (__GLIBC__) || defined (__APPLE__) || defined (__DragonFly__) \
324 || defined (__QNX__)
326 # ifdef __MINGW32__
327 # include <conio.h> /* for getch(), kbhit() */
328 # else
329 # include <termios.h>
330 # endif
332 #endif
334 /* Implements the common processing for getc_immediate and
335 getc_immediate_nowait. */
337 extern void getc_immediate (FILE *, int *, int *);
338 extern void getc_immediate_nowait (FILE *, int *, int *, int *);
339 extern void getc_immediate_common (FILE *, int *, int *, int *, int);
341 /* Called by Get_Immediate (Foo); */
343 void
344 getc_immediate (FILE *stream, int *ch, int *end_of_file)
346 int avail;
348 getc_immediate_common (stream, ch, end_of_file, &avail, 1);
351 /* Called by Get_Immediate (Foo, Available); */
353 void
354 getc_immediate_nowait (FILE *stream, int *ch, int *end_of_file, int *avail)
356 getc_immediate_common (stream, ch, end_of_file, avail, 0);
359 /* Called by getc_immediate () and getc_immediate_nowait () */
361 void
362 getc_immediate_common (FILE *stream,
363 int *ch,
364 int *end_of_file,
365 int *avail,
366 int waiting ATTRIBUTE_UNUSED)
368 #if defined (__linux__) || defined (__sun__) \
369 || defined (__CYGWIN32__) || defined (__MACHTEN__) || defined (__hpux__) \
370 || defined (_AIX) || (defined (__svr4__) && defined (__i386__)) \
371 || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
372 || defined (__GLIBC__) || defined (__APPLE__) || defined (__DragonFly__) \
373 || defined (__QNX__)
374 char c;
375 int nread;
376 int good_one = 0;
377 int eof_ch = 4; /* Ctrl-D */
378 int fd = fileno (stream);
379 struct termios otermios_rec, termios_rec;
381 if (isatty (fd))
383 tcgetattr (fd, &termios_rec);
384 memcpy (&otermios_rec, &termios_rec, sizeof (struct termios));
386 /* Set RAW mode, with no echo */
387 termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON & ~ECHO;
389 #if defined (__linux__) || defined (__sun__) \
390 || defined (__MACHTEN__) || defined (__hpux__) \
391 || defined (_AIX) || (defined (__svr4__) && defined (__i386__)) \
392 || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
393 || defined (__GLIBC__) || defined (__APPLE__) || defined (__DragonFly__) \
394 || defined (__QNX__)
395 eof_ch = termios_rec.c_cc[VEOF];
397 /* If waiting (i.e. Get_Immediate (Char)), set MIN = 1 and wait for
398 a character forever. This doesn't seem to effect Ctrl-Z or
399 Ctrl-C processing.
400 If not waiting (i.e. Get_Immediate (Char, Available)),
401 don't wait for anything but timeout immediately. */
402 termios_rec.c_cc[VMIN] = waiting;
403 termios_rec.c_cc[VTIME] = 0;
404 #endif
405 tcsetattr (fd, TCSANOW, &termios_rec);
407 while (! good_one)
409 /* Read is used here instead of fread, because fread doesn't
410 work on Solaris5 and Sunos4 in this situation. Maybe because we
411 are mixing calls that use file descriptors and streams. */
412 nread = read (fd, &c, 1);
413 if (nread > 0)
415 /* On Unix terminals, Ctrl-D (EOT) is an End of File. */
416 if (c == eof_ch)
418 *avail = 0;
419 *end_of_file = 1;
420 good_one = 1;
423 /* Everything else is ok */
424 else if (c != eof_ch)
426 *avail = 1;
427 *end_of_file = 0;
428 good_one = 1;
432 else if (! waiting)
434 *avail = 0;
435 *end_of_file = 0;
436 good_one = 1;
438 else
439 good_one = 0;
442 tcsetattr (fd, TCSANOW, &otermios_rec);
443 *ch = c;
446 else
447 #elif defined (__MINGW32__)
448 int fd = fileno (stream);
449 int char_waiting;
450 int eot_ch = 4; /* Ctrl-D */
452 if (isatty (fd))
454 if (waiting)
456 *ch = getch ();
458 if (*ch == eot_ch)
459 *end_of_file = 1;
460 else
461 *end_of_file = 0;
463 *avail = 1;
465 else /* ! waiting */
467 char_waiting = kbhit();
469 if (char_waiting == 1)
471 *avail = 1;
472 *ch = getch ();
474 if (*ch == eot_ch)
475 *end_of_file = 1;
476 else
477 *end_of_file = 0;
479 else
481 *avail = 0;
482 *end_of_file = 0;
486 else
487 #elif defined (__vxworks)
488 /* Bit masks of file descriptors to read from. */
489 struct fd_set readFds;
490 /* Timeout before select returns if nothing can be read. */
491 struct timeval timeOut;
492 char c;
493 int fd = fileno (stream);
494 int nread;
495 int option;
496 int readable;
497 int status;
498 int width;
500 if (isatty (fd))
502 /* If we do not want to wait, we have to set up fd in RAW mode. This
503 should be done outside this function as setting fd in RAW mode under
504 vxWorks flushes the buffer of fd. If the RAW mode was set here, the
505 buffer would be empty and we would always return that no character
506 is available */
507 if (! waiting)
509 /* Initialization of timeOut for its use with select. */
510 timeOut.tv_sec = 0;
511 timeOut.tv_usec = 0;
513 /* Initialization of readFds for its use with select;
514 FD is the only file descriptor to be monitored */
515 FD_ZERO (&readFds);
516 FD_SET (fd, &readFds);
517 width = 2;
519 /* We do all this processing to emulate a non blocking read. */
520 readable = select (width, &readFds, NULL, NULL, &timeOut);
521 if (readable == ERROR)
522 *avail = -1, *end_of_file = -1;
523 /* No character available in input. */
524 else if (readable == 0)
525 *avail = 0, *end_of_file = 0;
526 else
528 nread = read (fd, &c, 1);
529 if (nread > 0)
530 *avail = 1, *end_of_file = 0;
531 /* End Of File. */
532 else if (nread == 0)
533 *avail = 0, *end_of_file = 1;
534 /* Error. */
535 else
536 *avail = -1, *end_of_file = -1;
540 /* We have to wait until we get a character */
541 else
543 *avail = -1;
544 *end_of_file = -1;
546 /* Save the current mode of FD. */
547 option = ioctl (fd, FIOGETOPTIONS, 0);
549 /* Set FD in RAW mode. */
550 status = ioctl (fd, FIOSETOPTIONS, OPT_RAW);
551 if (status != -1)
553 nread = read (fd, &c, 1);
554 if (nread > 0)
555 *avail = 1, *end_of_file = 0;
556 /* End of file. */
557 else if (nread == 0)
558 *avail = 0, *end_of_file = 1;
559 /* Else there is an ERROR. */
562 /* Revert FD to its previous mode. */
563 status = ioctl (fd, FIOSETOPTIONS, option);
566 *ch = c;
568 else
569 #endif
571 /* If we're not on a terminal, then we don't need any fancy processing.
572 Also this is the only thing that's left if we're not on one of the
573 supported systems; which means that for non supported systems,
574 get_immediate may wait for a carriage return on terminals. */
575 *ch = fgetc (stream);
576 if (feof (stream))
578 *end_of_file = 1;
579 *avail = 0;
581 else
583 *end_of_file = 0;
584 *avail = 1;
589 /* The following definitions are provided in NT to support Windows based
590 Ada programs. */
592 #ifdef WINNT
593 #define WIN32_LEAN_AND_MEAN
594 #include <windows.h>
596 /* Provide functions to echo the values passed to WinMain (windows bindings
597 will want to import these). We use the same names as the routines used
598 by AdaMagic for compatibility. */
600 char *rts_get_hInstance (void);
601 char *rts_get_hPrevInstance (void);
602 char *rts_get_lpCommandLine (void);
603 int rts_get_nShowCmd (void);
605 char *
606 rts_get_hInstance (void)
608 return (char *)GetModuleHandleA (0);
611 char *
612 rts_get_hPrevInstance (void)
614 return 0;
617 char *
618 rts_get_lpCommandLine (void)
620 return GetCommandLineA ();
624 rts_get_nShowCmd (void)
626 return 1;
629 #endif /* WINNT */
631 /* This value is returned as the time zone offset when a valid value
632 cannot be determined. It is simply a bizarre value that will never
633 occur. It is 3 days plus 73 seconds (offset is in seconds). */
635 long __gnat_invalid_tzoff = 259273;
637 /* Definition of __gnat_localtime_r used by a-calend.adb */
639 #if defined (__MINGW32__)
641 /* Reentrant localtime for Windows. */
643 extern void
644 __gnat_localtime_tzoff (const OS_Time *, const int *, long *);
646 static const unsigned long long w32_epoch_offset = 11644473600ULL;
647 void
648 __gnat_localtime_tzoff (const OS_Time *timer, const int *is_historic, long *off)
650 TIME_ZONE_INFORMATION tzi;
652 DWORD tzi_status;
654 tzi_status = GetTimeZoneInformation (&tzi);
656 /* Cases where we simply want to extract the offset of the current time
657 zone, regardless of the date. A value of "0" for flag "is_historic"
658 signifies that the date is NOT historic, see the
659 body of Ada.Calendar.UTC_Time_Offset. */
661 if (*is_historic == 0) {
662 *off = tzi.Bias;
664 /* The system is operating in the range covered by the StandardDate
665 member. */
666 if (tzi_status == TIME_ZONE_ID_STANDARD) {
667 *off = *off + tzi.StandardBias;
670 /* The system is operating in the range covered by the DaylightDate
671 member. */
672 else if (tzi_status == TIME_ZONE_ID_DAYLIGHT) {
673 *off = *off + tzi.DaylightBias;
676 *off = *off * -60;
679 /* Time zone offset calculations for a historic or future date */
681 else {
682 union
684 FILETIME ft_time;
685 unsigned long long ull_time;
686 } utc_time, local_time;
688 SYSTEMTIME utc_sys_time, local_sys_time;
689 BOOL status;
691 /* First convert unix time_t structure to windows FILETIME format. */
692 utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset)
693 * 10000000ULL;
695 /* If GetTimeZoneInformation does not return a value between 0 and 2 then
696 it means that we were not able to retrieve timezone information. Note
697 that we cannot use here FileTimeToLocalFileTime as Windows will use in
698 always in this case the current timezone setting. As suggested on MSDN
699 we use the following three system calls to get the right information.
700 Note also that starting with Windows Vista new functions are provided
701 to get timezone settings that depend on the year. We cannot use them as
702 we still support Windows XP and Windows 2003. */
704 status = tzi_status <= 2
705 && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time)
706 && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time)
707 && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time);
709 /* An error has occurred, return invalid_tzoff */
711 if (!status) {
712 *off = __gnat_invalid_tzoff;
714 else {
715 if (local_time.ull_time > utc_time.ull_time) {
716 *off = (long) ((local_time.ull_time - utc_time.ull_time)
717 / 10000000ULL);
719 else {
720 *off = - (long) ((utc_time.ull_time - local_time.ull_time)
721 / 10000000ULL);
727 #elif defined (__Lynx__)
729 /* On Lynx, all time values are treated in GMT */
731 /* As of LynxOS 3.1.0a patch level 040, LynuxWorks changes the
732 prototype to the C library function localtime_r from the POSIX.4
733 Draft 9 to the POSIX 1.c version. Before this change the following
734 spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
735 the Lynx convention when building against the legacy API. */
737 extern void
738 __gnat_localtime_tzoff (const OS_Time *, const int *, long *);
740 void
741 __gnat_localtime_tzoff (const OS_Time *timer, const int *is_historic, long *off)
743 *off = 0;
746 #else
748 /* Other targets except Lynx and Windows provide a standard localtime_r */
750 #define Lock_Task system__soft_links__lock_task
751 extern void (*Lock_Task) (void);
753 #define Unlock_Task system__soft_links__unlock_task
754 extern void (*Unlock_Task) (void);
756 extern void
757 __gnat_localtime_tzoff (const OS_Time *, const int *, long *);
759 void
760 __gnat_localtime_tzoff (const OS_Time *timer ATTRIBUTE_UNUSED,
761 const int *is_historic ATTRIBUTE_UNUSED,
762 long *off ATTRIBUTE_UNUSED)
764 struct tm tp ATTRIBUTE_UNUSED;
765 const time_t time = (time_t) *timer;
767 /* AIX, HPUX, Sun Solaris */
768 #if defined (_AIX) || defined (__hpux__) || defined (__sun__)
770 (*Lock_Task) ();
772 localtime_r (&time, &tp);
773 *off = (long) -timezone;
775 (*Unlock_Task) ();
777 /* Correct the offset if Daylight Saving Time is in effect */
779 if (tp.tm_isdst > 0)
780 *off = *off + 3600;
783 /* VxWorks */
784 #elif defined (__vxworks)
785 #include <stdlib.h>
787 (*Lock_Task) ();
789 localtime_r (&time, &tp);
791 /* Try to read the environment variable TIMEZONE. The variable may not have
792 been initialize, in that case return an offset of zero (0) for UTC. */
794 char *tz_str = getenv ("TIMEZONE");
796 if ((tz_str == NULL) || (*tz_str == '\0'))
797 *off = 0;
798 else
800 char *tz_start, *tz_end;
802 /* The format of the data contained in TIMEZONE is N::U:S:E where N is the
803 name of the time zone, U are the minutes difference from UTC, S is the
804 start of DST in mmddhh and E is the end of DST in mmddhh. Extracting
805 the value of U involves setting two pointers, one at the beginning and
806 one at the end of the value. The end pointer is then set to null in
807 order to delimit a string slice for atol to process. */
809 tz_start = index (tz_str, ':') + 2;
810 tz_end = index (tz_start, ':');
811 *tz_end = '\0';
813 /* The Ada layer expects an offset in seconds. Note that we must reverse
814 the sign of the result since west is positive and east is negative on
815 VxWorks targets. */
817 *off = -atol (tz_start) * 60;
819 /* Correct the offset if Daylight Saving Time is in effect */
821 if (tp.tm_isdst > 0)
822 *off = *off + 3600;
825 (*Unlock_Task) ();
828 /* Darwin, Free BSD, Linux, where component tm_gmtoff is present in
829 struct tm */
831 #elif defined (__APPLE__) || defined (__FreeBSD__) || defined (__linux__) \
832 || defined (__GLIBC__) || defined (__DragonFly__) || defined (__OpenBSD__) \
833 || defined (__DJGPP__) || defined (__QNX__)
835 localtime_r (&time, &tp);
836 *off = tp.tm_gmtoff;
839 /* Default: treat all time values in GMT */
841 #else
842 *off = 0;
844 #endif /* defined(_AIX) ... */
847 #endif
849 #ifdef __vxworks
851 #include <taskLib.h>
853 /* __gnat_get_task_options is used by s-taprop.adb only for VxWorks. This
854 function returns the options to be set when creating a new task. It fetches
855 the options assigned to the current task (parent), so offering some user
856 level control over the options for a task hierarchy. It forces VX_FP_TASK
857 because it is almost always required. On processors with the SPE
858 category, VX_SPE_TASK should be used instead to enable the SPE. */
859 extern int __gnat_get_task_options (void);
862 __gnat_get_task_options (void)
864 int options;
866 /* Get the options for the task creator */
867 taskOptionsGet (taskIdSelf (), &options);
869 /* Force VX_FP_TASK or VX_SPE_TASK as needed */
870 #if defined (__SPE__)
871 options |= VX_SPE_TASK;
872 #else
873 options |= VX_FP_TASK;
874 #endif
876 /* Mask those bits that are not under user control */
877 #ifdef VX_USR_TASK_OPTIONS
878 /* O810-007, TSR 00043679:
879 Workaround a bug in Vx-7 where VX_DEALLOC_TCB == VX_PRIVATE_UMASK and:
880 - VX_DEALLOC_TCB is an internal option not to be used by users
881 - VX_PRIVATE_UMASK as a user-definable option
882 This leads to VX_USR_TASK_OPTIONS allowing 0x8000 as VX_PRIVATE_UMASK but
883 taskCreate refusing this option (VX_DEALLOC_TCB is not allowed)
885 Note that the same error occurs in both RTP and Kernel mode, but
886 VX_DEALLOC_TCB is not defined in the RTP headers, so we need to
887 explicitely check if VX_PRIVATE_UMASK has value 0x8000
889 # if defined (VX_PRIVATE_UMASK) && (0x8000 == VX_PRIVATE_UMASK)
890 options &= ~VX_PRIVATE_UMASK;
891 # endif
892 options &= VX_USR_TASK_OPTIONS;
893 #endif
894 return options;
897 #endif
900 __gnat_is_file_not_found_error (int errno_val)
902 /* WARNING: Do not rewrite this as a switch/case statement.
903 * Some of the "cases" are duplicated in some versions of
904 * Vxworks, notably VxWorks7r2 SR0610. */
905 if (errno_val == ENOENT)
906 return 1;
907 #ifdef __vxworks
908 /* Starting with VxWorks 21.03, the fopen() function can set errno to
909 * ENODEV when the prefix of the path does not match any known device. */
910 else if (errno_val == ENODEV)
911 return 1;
912 /* In the case of VxWorks, we also have to take into account various
913 * filesystem-specific variants of this error.
915 #if ! defined (VTHREADS) && (_WRS_VXWORKS_MAJOR < 7)
916 else if (errno_val == S_dosFsLib_FILE_NOT_FOUND)
917 return 1;
918 #endif
919 #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
920 else if (errno_val == S_nfsLib_NFSERR_NOENT)
921 return 1;
922 #endif
923 #if defined (__RTP__)
924 /* An RTP can return an NFS file not found, and the NFS bits must
925 first be masked on to check the errno. */
926 else if (errno_val == (M_nfsStat | ENOENT))
927 return 1;
928 #endif
929 #endif
930 else
931 return 0;
934 #if defined (__linux__)
936 /* Note well: If this code is modified, it should be tested by hand,
937 because automated testing doesn't exercise it.
940 /* HAVE_CAPABILITY is supposed to be defined if sys/capability.h exists on the
941 system where this is being compiled. If this macro is defined, we #include
942 the header. Otherwise we have the relevant declarations textually here.
945 #if defined (HAVE_CAPABILITY)
946 #include <sys/capability.h>
947 #else
949 /* HAVE_CAPABILITY is not defined, so sys/capability.h does might not exist. */
951 typedef struct _cap_struct *cap_t;
952 typedef enum {
953 CAP_CLEAR=0,
954 CAP_SET=1
955 } cap_flag_value_t;
956 #define CAP_SYS_NICE 23
957 typedef enum {
958 CAP_EFFECTIVE=0, /* Specifies the effective flag */
959 CAP_PERMITTED=1, /* Specifies the permitted flag */
960 CAP_INHERITABLE=2 /* Specifies the inheritable flag */
961 } cap_flag_t;
963 typedef int cap_value_t;
965 extern cap_t cap_get_proc(void);
966 extern int cap_get_flag(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *);
967 extern int cap_free(void *);
969 #endif
971 /* __gnat_has_cap_sys_nice returns 1 if the current process has the
972 CAP_SYS_NICE capability. This capability is necessary to use the
973 Ceiling_Locking policy. Returns 0 otherwise. Note that this is
974 defined only for Linux.
977 /* Define these as weak symbols, so if support for capabilities is not present,
978 programs can still link. On Ubuntu, support for capabilities can be
979 installed via "sudo apt-get --assume-yes install libcap-dev".
980 In addition, the user must link with "-lcap", or else these
981 symbols will be 0, and __gnat_has_cap_sys_nice will return 0.
984 static cap_t cap_get_proc_weak(void)
985 __attribute__ ((weakref ("cap_get_proc")));
986 static int cap_get_flag_weak(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *)
987 __attribute__ ((weakref ("cap_get_flag")));
988 static int cap_free_weak(void *)
989 __attribute__ ((weakref ("cap_free")));
992 __gnat_has_cap_sys_nice () {
993 /* If the address of cap_get_proc_weak is 0, this means support for
994 capabilities is not present, so we return 0. */
995 if (&cap_get_proc_weak == 0)
996 return 0;
998 cap_t caps = cap_get_proc_weak();
999 if (caps == NULL)
1000 return 0;
1002 cap_flag_value_t value;
1004 if (cap_get_flag_weak(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &value) == -1)
1005 return 0;
1007 if (cap_free_weak(caps) == -1)
1008 return 0;
1010 if (value == CAP_SET)
1011 return 1;
1013 return 0;
1015 #endif
1017 #ifdef __ANDROID__
1019 /* Provide extern symbols for sig* as needed by the tasking run-time, instead
1020 of static inline functions. */
1022 #include <signal.h>
1025 _sigismember (sigset_t *set, int signum)
1027 return sigismember (set, signum);
1031 _sigaddset (sigset_t *set, int signum)
1033 return sigaddset (set, signum);
1037 _sigdelset (sigset_t *set, int signum)
1039 return sigdelset (set, signum);
1043 _sigemptyset (sigset_t *set)
1045 return sigemptyset (set);
1049 _sigfillset (sigset_t *set)
1051 return sigfillset (set);
1054 #include <unistd.h>
1056 _getpagesize (void)
1058 return getpagesize ();
1060 #endif
1063 __gnat_name_case_equivalence ()
1065 /* the values here must be synchronized with Ada.Directories.Name_Case_Kind:
1067 Unknown = 0
1068 Case_Sensitive = 1
1069 Case_Insensitive = 2
1070 Case_Preserving = 3 */
1072 #if defined (__APPLE__) || defined (WIN32)
1073 return 3;
1074 #else
1075 return 1;
1076 #endif