1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
7 * C Implementation File *
9 * Copyright (C) 1992-2014, Free Software Foundation, Inc. *
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. *
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. *
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/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
32 /* This file contains system dependent symbols that are referenced in the
33 GNAT Run Time Library */
37 #if ! defined (VTHREADS)
40 #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
43 #include "selectLib.h"
47 # include "vwModNum.h"
72 #if defined (sun) && defined (__SVR4) && !defined (__vxworks)
73 /* The declaration is present in <time.h> but conditionalized
74 on a couple of macros we don't define. */
75 extern struct tm
*localtime_r(const time_t *, struct tm
*);
80 /* Don't use macros versions of this functions on VxWorks since they cause
81 imcompatible changes in some VxWorks versions */
93 (1) Opening a file with read mode fails if the file does not exist or
96 (2) Opening a file with append mode causes all subsequent writes to the
97 file to be forced to the then current end-of-file, regardless of
98 intervening calls to the fseek function.
100 (3) When a file is opened with update mode, both input and output may be
101 performed on the associated stream. However, output may not be directly
102 followed by input without an intervening call to the fflush function or
103 to a file positioning function (fseek, fsetpos, or rewind), and input
104 may not be directly followed by output without an intervening call to a
105 file positioning function, unless the input operation encounters
108 The other target dependent declarations here are for the three functions
109 __gnat_set_binary_mode, __gnat_set_text_mode and __gnat_set_mode:
111 void __gnat_set_binary_mode (int handle);
112 void __gnat_set_text_mode (int handle);
113 void __gnat_set_mode (int handle, int mode);
115 These functions have no effect in Unix (or similar systems where there is
116 no distinction between binary and text files), but in DOS (and similar
117 systems where text mode does CR/LF translation), these functions allow
118 the mode of the stream with the given handle (fileno can be used to get
119 the handle of a stream) to be changed dynamically. The returned result
120 is 0 if no error occurs and -1 if an error occurs.
122 Finally there is a boolean (character) variable
124 char __gnat_text_translation_required;
126 which is zero (false) in Unix mode, and one (true) in DOS mode, with a
127 true value indicating that text translation is required on text files
128 and that fopen supports the trailing t and b modifiers.
132 #if defined (WINNT) || defined (__CYGWIN__)
134 const char __gnat_text_translation_required
= 1;
137 #define WIN_SETMODE setmode
140 #define WIN_SETMODE _setmode
144 __gnat_set_binary_mode (int handle
)
146 WIN_SETMODE (handle
, O_BINARY
);
150 __gnat_set_text_mode (int handle
)
152 WIN_SETMODE (handle
, O_TEXT
);
156 __gnat_set_mode (int handle
, int mode
)
158 /* the values here must be synchronized with
159 System.File_Control_Block.Content_Encodding:
169 case 0 : WIN_SETMODE (handle
, _O_BINARY
); break;
170 case 1 : WIN_SETMODE (handle
, CurrentCCSEncoding
); break;
171 case 2 : WIN_SETMODE (handle
, _O_TEXT
); break;
172 case 3 : WIN_SETMODE (handle
, _O_U8TEXT
); break;
173 case 4 : WIN_SETMODE (handle
, _O_WTEXT
); break;
174 case 5 : WIN_SETMODE (handle
, _O_U16TEXT
); break;
181 __gnat_ttyname (int filedes
)
183 extern char *ttyname (int);
185 return ttyname (filedes
);
188 #endif /* __CYGWIN__ */
190 #if defined (__CYGWIN__) || defined (__MINGW32__)
195 int __gnat_is_windows_xp (void);
198 __gnat_is_windows_xp (void)
200 static int is_win_xp
=0, is_win_xp_checked
=0;
202 if (!is_win_xp_checked
)
204 OSVERSIONINFO version
;
206 is_win_xp_checked
= 1;
208 memset (&version
, 0, sizeof (version
));
209 version
.dwOSVersionInfoSize
= sizeof (version
);
211 is_win_xp
= GetVersionEx (&version
)
212 && version
.dwPlatformId
== VER_PLATFORM_WIN32_NT
213 && (version
.dwMajorVersion
> 5
214 || (version
.dwMajorVersion
== 5 && version
.dwMinorVersion
>= 1));
221 /* Get the bounds of the stack. The stack pointer is supposed to be
222 initialized to BASE when a thread is created and the stack can be extended
223 to LIMIT before reaching a guard page.
224 Note: for the main thread, the system automatically extend the stack, so
225 LIMIT is only the current limit. */
228 __gnat_get_stack_bounds (void **base
, void **limit
)
232 /* We know that the first field of the TEB is the TIB. */
233 tib
= (NT_TIB
*)NtCurrentTeb ();
235 *base
= tib
->StackBase
;
236 *limit
= tib
->StackLimit
;
239 #endif /* __CYGWIN__ || __MINGW32__ */
243 /* Return the name of the tty. Under windows there is no name for
244 the tty, so this function, if connected to a tty, returns the generic name
248 __gnat_ttyname (int filedes
)
250 if (isatty (filedes
))
256 #endif /* __MINGW32__ */
260 const char __gnat_text_translation_required
= 0;
262 /* These functions do nothing in non-DOS systems. */
265 __gnat_set_binary_mode (int handle ATTRIBUTE_UNUSED
)
270 __gnat_set_text_mode (int handle ATTRIBUTE_UNUSED
)
275 __gnat_set_mode (int handle ATTRIBUTE_UNUSED
, int mode ATTRIBUTE_UNUSED
)
280 __gnat_ttyname (int filedes
)
282 #if defined (__vxworks) || defined (__nucleus)
285 extern char *ttyname (int);
287 return ttyname (filedes
);
288 #endif /* defined (__vxworks) || defined (__nucleus) */
292 #if defined (linux) || defined (sun) \
294 || defined (__MACHTEN__) || defined (__hpux__) || defined (_AIX) \
295 || (defined (__svr4__) && defined (i386)) || defined (__Lynx__) \
296 || defined (__CYGWIN__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
297 || defined (__GLIBC__) || defined (__APPLE__)
301 # include <termios.h>
303 # include <conio.h> /* for getch(), kbhit() */
306 # include <termios.h>
311 extern char *decc$ga_stdscr
;
312 static int initted
= 0;
316 /* Implements the common processing for getc_immediate and
317 getc_immediate_nowait. */
319 extern void getc_immediate (FILE *, int *, int *);
320 extern void getc_immediate_nowait (FILE *, int *, int *, int *);
321 extern void getc_immediate_common (FILE *, int *, int *, int *, int);
323 /* Called by Get_Immediate (Foo); */
326 getc_immediate (FILE *stream
, int *ch
, int *end_of_file
)
330 getc_immediate_common (stream
, ch
, end_of_file
, &avail
, 1);
333 /* Called by Get_Immediate (Foo, Available); */
336 getc_immediate_nowait (FILE *stream
, int *ch
, int *end_of_file
, int *avail
)
338 getc_immediate_common (stream
, ch
, end_of_file
, avail
, 0);
341 /* Called by getc_immediate () and getc_immediate_nowait () */
344 getc_immediate_common (FILE *stream
,
348 int waiting ATTRIBUTE_UNUSED
)
350 #if defined (linux) || defined (sun) \
351 || defined (__CYGWIN32__) || defined (__MACHTEN__) || defined (__hpux__) \
352 || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
353 || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
354 || defined (__GLIBC__) || defined (__APPLE__)
358 int eof_ch
= 4; /* Ctrl-D */
359 int fd
= fileno (stream
);
360 struct termios otermios_rec
, termios_rec
;
364 tcgetattr (fd
, &termios_rec
);
365 memcpy (&otermios_rec
, &termios_rec
, sizeof (struct termios
));
367 /* Set RAW mode, with no echo */
368 termios_rec
.c_lflag
= termios_rec
.c_lflag
& ~ICANON
& ~ECHO
;
370 #if defined(linux) || defined (sun) \
371 || defined (__MACHTEN__) || defined (__hpux__) \
372 || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
373 || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
374 || defined (__GLIBC__) || defined (__APPLE__)
375 eof_ch
= termios_rec
.c_cc
[VEOF
];
377 /* If waiting (i.e. Get_Immediate (Char)), set MIN = 1 and wait for
378 a character forever. This doesn't seem to effect Ctrl-Z or
380 If not waiting (i.e. Get_Immediate (Char, Available)),
381 don't wait for anything but timeout immediately. */
382 termios_rec
.c_cc
[VMIN
] = waiting
;
383 termios_rec
.c_cc
[VTIME
] = 0;
385 tcsetattr (fd
, TCSANOW
, &termios_rec
);
389 /* Read is used here instead of fread, because fread doesn't
390 work on Solaris5 and Sunos4 in this situation. Maybe because we
391 are mixing calls that use file descriptors and streams. */
392 nread
= read (fd
, &c
, 1);
395 /* On Unix terminals, Ctrl-D (EOT) is an End of File. */
403 /* Everything else is ok */
404 else if (c
!= eof_ch
)
422 tcsetattr (fd
, TCSANOW
, &otermios_rec
);
428 int fd
= fileno (stream
);
439 *ch
= decc$
bsd_wgetch (decc$ga_stdscr
);
447 decc$
bsd_nocbreak ();
450 #elif defined (__MINGW32__)
451 int fd
= fileno (stream
);
453 int eot_ch
= 4; /* Ctrl-D */
470 char_waiting
= kbhit();
472 if (char_waiting
== 1)
490 #elif defined (__vxworks)
491 /* Bit masks of file descriptors to read from. */
492 struct fd_set readFds
;
493 /* Timeout before select returns if nothing can be read. */
494 struct timeval timeOut
;
496 int fd
= fileno (stream
);
505 /* If we do not want to wait, we have to set up fd in RAW mode. This
506 should be done outside this function as setting fd in RAW mode under
507 vxWorks flushes the buffer of fd. If the RAW mode was set here, the
508 buffer would be empty and we would always return that no character
512 /* Initialization of timeOut for its use with select. */
516 /* Initialization of readFds for its use with select;
517 FD is the only file descriptor to be monitored */
519 FD_SET (fd
, &readFds
);
522 /* We do all this processing to emulate a non blocking read. */
523 readable
= select (width
, &readFds
, NULL
, NULL
, &timeOut
);
524 if (readable
== ERROR
)
525 *avail
= -1, *end_of_file
= -1;
526 /* No character available in input. */
527 else if (readable
== 0)
528 *avail
= 0, *end_of_file
= 0;
531 nread
= read (fd
, &c
, 1);
533 *avail
= 1, *end_of_file
= 0;
536 *avail
= 0, *end_of_file
= 1;
539 *avail
= -1, *end_of_file
= -1;
543 /* We have to wait until we get a character */
549 /* Save the current mode of FD. */
550 option
= ioctl (fd
, FIOGETOPTIONS
, 0);
552 /* Set FD in RAW mode. */
553 status
= ioctl (fd
, FIOSETOPTIONS
, OPT_RAW
);
556 nread
= read (fd
, &c
, 1);
558 *avail
= 1, *end_of_file
= 0;
561 *avail
= 0, *end_of_file
= 1;
562 /* Else there is an ERROR. */
565 /* Revert FD to its previous mode. */
566 status
= ioctl (fd
, FIOSETOPTIONS
, option
);
574 /* If we're not on a terminal, then we don't need any fancy processing.
575 Also this is the only thing that's left if we're not on one of the
576 supported systems; which means that for non supported systems,
577 get_immediate may wait for a carriage return on terminals. */
578 *ch
= fgetc (stream
);
592 /* The following definitions are provided in NT to support Windows based
598 /* Provide functions to echo the values passed to WinMain (windows bindings
599 will want to import these). We use the same names as the routines used
600 by AdaMagic for compatibility. */
602 char *rts_get_hInstance (void);
603 char *rts_get_hPrevInstance (void);
604 char *rts_get_lpCommandLine (void);
605 int rts_get_nShowCmd (void);
608 rts_get_hInstance (void)
610 return (char *)GetModuleHandleA (0);
614 rts_get_hPrevInstance (void)
620 rts_get_lpCommandLine (void)
622 return GetCommandLineA ();
626 rts_get_nShowCmd (void)
634 /* This gets around a problem with using the old threads library on VMS 7.0. */
636 extern long get_gmtoff (void);
644 t
= time ((time_t) 0);
646 return ts
->tm_gmtoff
;
650 /* This value is returned as the time zone offset when a valid value
651 cannot be determined. It is simply a bizarre value that will never
652 occur. It is 3 days plus 73 seconds (offset is in seconds). */
654 long __gnat_invalid_tzoff
= 259273;
656 /* Definition of __gnat_localtime_r used by a-calend.adb */
658 #if defined (__MINGW32__)
662 /* For the Cert run times on native Windows we use dummy functions
663 for locking and unlocking tasks since we do not support multiple
664 threads on this configuration (Cert run time on native Windows). */
668 void (*Lock_Task
) () = &dummy
;
669 void (*Unlock_Task
) () = &dummy
;
673 #define Lock_Task system__soft_links__lock_task
674 extern void (*Lock_Task
) (void);
676 #define Unlock_Task system__soft_links__unlock_task
677 extern void (*Unlock_Task
) (void);
681 /* Reentrant localtime for Windows. */
684 __gnat_localtime_tzoff (const time_t *, const int *, long *);
686 static const unsigned long long w32_epoch_offset
= 11644473600ULL;
688 __gnat_localtime_tzoff (const time_t *timer
, const int *is_historic
, long *off
)
690 TIME_ZONE_INFORMATION tzi
;
703 tzi_status
= GetTimeZoneInformation (&tzi
);
705 /* Processing for RTX targets or cases where we simply want to extract the
706 offset of the current time zone, regardless of the date. A value of "0"
707 for flag "is_historic" signifies that the date is NOT historic, see the
708 body of Ada.Calendar.UTC_Time_Offset. */
710 if (rtx_active
|| *is_historic
== 0) {
713 /* The system is operating in the range covered by the StandardDate
715 if (tzi_status
== TIME_ZONE_ID_STANDARD
) {
716 *off
= *off
+ tzi
.StandardBias
;
719 /* The system is operating in the range covered by the DaylightDate
721 else if (tzi_status
== TIME_ZONE_ID_DAYLIGHT
) {
722 *off
= *off
+ tzi
.DaylightBias
;
728 /* Time zone offset calculations for a historic or future date */
734 unsigned long long ull_time
;
735 } utc_time
, local_time
;
737 SYSTEMTIME utc_sys_time
, local_sys_time
;
740 /* First convert unix time_t structure to windows FILETIME format. */
741 utc_time
.ull_time
= ((unsigned long long) *timer
+ w32_epoch_offset
)
744 /* If GetTimeZoneInformation does not return a value between 0 and 2 then
745 it means that we were not able to retrieve timezone information. Note
746 that we cannot use here FileTimeToLocalFileTime as Windows will use in
747 always in this case the current timezone setting. As suggested on MSDN
748 we use the following three system calls to get the right information.
749 Note also that starting with Windows Vista new functions are provided
750 to get timezone settings that depend on the year. We cannot use them as
751 we still support Windows XP and Windows 2003. */
753 status
= (tzi_status
>= 0 && tzi_status
<= 2)
754 && FileTimeToSystemTime (&utc_time
.ft_time
, &utc_sys_time
)
755 && SystemTimeToTzSpecificLocalTime (&tzi
, &utc_sys_time
, &local_sys_time
)
756 && SystemTimeToFileTime (&local_sys_time
, &local_time
.ft_time
);
758 /* An error has occurred, return invalid_tzoff */
761 *off
= __gnat_invalid_tzoff
;
764 if (local_time
.ull_time
> utc_time
.ull_time
) {
765 *off
= (long) ((local_time
.ull_time
- utc_time
.ull_time
)
769 *off
= - (long) ((utc_time
.ull_time
- local_time
.ull_time
)
780 /* On Lynx, all time values are treated in GMT */
782 #if defined (__Lynx__)
784 /* As of LynxOS 3.1.0a patch level 040, LynuxWorks changes the
785 prototype to the C library function localtime_r from the POSIX.4
786 Draft 9 to the POSIX 1.c version. Before this change the following
787 spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
788 the Lynx convention when building against the legacy API. */
791 __gnat_localtime_tzoff (const time_t *, const int *, long *);
794 __gnat_localtime_tzoff (const time_t *timer
, const int *is_historic
, long *off
)
801 /* VMS does not need __gnat_localtime_tzoff */
805 /* Other targets except Lynx, VMS and Windows provide a standard localtime_r */
809 #define Lock_Task system__soft_links__lock_task
810 extern void (*Lock_Task
) (void);
812 #define Unlock_Task system__soft_links__unlock_task
813 extern void (*Unlock_Task
) (void);
816 __gnat_localtime_tzoff (const time_t *, const int *, long *);
819 __gnat_localtime_tzoff (const time_t *timer ATTRIBUTE_UNUSED
,
820 const int *is_historic ATTRIBUTE_UNUSED
,
821 long *off ATTRIBUTE_UNUSED
)
823 struct tm tp ATTRIBUTE_UNUSED
;
825 /* AIX, HPUX, Sun Solaris */
826 #if defined (_AIX) || defined (__hpux__) || defined (sun)
830 localtime_r (timer
, &tp
);
831 *off
= (long) -timezone
;
835 /* Correct the offset if Daylight Saving Time is in effect */
842 #elif defined (__vxworks)
847 localtime_r (timer
, &tp
);
849 /* Try to read the environment variable TIMEZONE. The variable may not have
850 been initialize, in that case return an offset of zero (0) for UTC. */
852 char *tz_str
= getenv ("TIMEZONE");
854 if ((tz_str
== NULL
) || (*tz_str
== '\0'))
858 char *tz_start
, *tz_end
;
860 /* The format of the data contained in TIMEZONE is N::U:S:E where N is the
861 name of the time zone, U are the minutes difference from UTC, S is the
862 start of DST in mmddhh and E is the end of DST in mmddhh. Extracting
863 the value of U involves setting two pointers, one at the beginning and
864 one at the end of the value. The end pointer is then set to null in
865 order to delimit a string slice for atol to process. */
867 tz_start
= index (tz_str
, ':') + 2;
868 tz_end
= index (tz_start
, ':');
871 /* The Ada layer expects an offset in seconds. Note that we must reverse
872 the sign of the result since west is positive and east is negative on
875 *off
= -atol (tz_start
) * 60;
877 /* Correct the offset if Daylight Saving Time is in effect */
886 /* Darwin, Free BSD, Linux, where component tm_gmtoff is present in
889 #elif defined (__APPLE__) || defined (__FreeBSD__) || defined (linux) \
890 || defined (__GLIBC__)
892 localtime_r (timer
, &tp
);
896 /* Default: treat all time values in GMT */
912 /* __gnat_get_task_options is used by s-taprop.adb only for VxWorks. This
913 function returns the options to be set when creating a new task. It fetches
914 the options assigned to the current task (parent), so offering some user
915 level control over the options for a task hierarchy. It forces VX_FP_TASK
916 because it is almost always required. On processors with the SPE
917 category, VX_SPE_TASK should be used instead to enable the SPE. */
918 extern int __gnat_get_task_options (void);
921 __gnat_get_task_options (void)
925 /* Get the options for the task creator */
926 taskOptionsGet (taskIdSelf (), &options
);
928 /* Force VX_FP_TASK or VX_SPE_TASK as needed */
929 #if defined (__SPE__)
930 options
|= VX_SPE_TASK
;
932 options
|= VX_FP_TASK
;
935 /* Mask those bits that are not under user control */
936 #ifdef VX_USR_TASK_OPTIONS
937 return options
& VX_USR_TASK_OPTIONS
;
946 __gnat_is_file_not_found_error (int errno_val
) {
950 /* In the case of VxWorks, we also have to take into account various
951 * filesystem-specific variants of this error.
953 #if ! defined (VTHREADS) && (_WRS_VXWORKS_MAJOR < 7)
954 case S_dosFsLib_FILE_NOT_FOUND
:
956 #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
957 case S_nfsLib_NFSERR_NOENT
:
959 #if defined (__RTP__)
960 /* An RTP can return an NFS file not found, and the NFS bits must
961 first be masked on to check the errno. */
962 case M_nfsStat
| ENOENT
:
974 /* Provide extern symbols for sig* as needed by the tasking run-time, instead
975 of static inline functions. */
980 _sigismember (sigset_t
*set
, int signum
)
982 return sigismember (set
, signum
);
986 _sigaddset (sigset_t
*set
, int signum
)
988 return sigaddset (set
, signum
);
992 _sigdelset (sigset_t
*set
, int signum
)
994 return sigdelset (set
, signum
);
998 _sigemptyset (sigset_t
*set
)
1000 return sigemptyset (set
);
1004 _sigfillset (sigset_t
*set
)
1006 return sigfillset (set
);
1013 return getpagesize ();