Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/sysdep.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /**************************************************************************** | |
2 * * | |
3 * GNAT COMPILER COMPONENTS * | |
4 * * | |
5 * S Y S D E P * | |
6 * * | |
7 * C Implementation File * | |
8 * * | |
9 * Copyright (C) 1992-2017, 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__) || defined (__DJGPP__) | |
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 #if defined (__DJGPP__) | |
141 #include <io.h> | |
142 #define _setmode setmode | |
143 #endif /* __DJGPP__ */ | |
144 | |
145 void | |
146 __gnat_set_binary_mode (int handle) | |
147 { | |
148 WIN_SETMODE (handle, O_BINARY); | |
149 } | |
150 | |
151 void | |
152 __gnat_set_text_mode (int handle) | |
153 { | |
154 WIN_SETMODE (handle, O_TEXT); | |
155 } | |
156 | |
157 #if defined (__CYGWIN__) || defined (__DJGPP__) | |
158 void | |
159 __gnat_set_mode (int handle, int mode) | |
160 { | |
161 /* the values here must be synchronized with | |
162 System.File_Control_Block.Content_Encodding: | |
163 | |
164 None = 0 | |
165 Default_Text = 1 | |
166 Text = 2 | |
167 U8text = 3 | |
168 Wtext = 4 | |
169 U16text = 5 */ | |
170 | |
171 switch (mode) { | |
172 case 0 : setmode(handle, O_BINARY); break; | |
173 case 1 : setmode(handle, O_TEXT); break; | |
174 case 2 : setmode(handle, O_TEXT); break; | |
175 case 3 : setmode(handle, O_TEXT); break; | |
176 case 4 : setmode(handle, O_BINARY); break; | |
177 case 5 : setmode(handle, O_BINARY); break; | |
178 } | |
179 } | |
180 #else | |
181 void | |
182 __gnat_set_mode (int handle, int mode) | |
183 { | |
184 /* the values here must be synchronized with | |
185 System.File_Control_Block.Content_Encodding: | |
186 | |
187 None = 0 | |
188 Default_Text = 1 | |
189 Text = 2 | |
190 U8text = 3 | |
191 Wtext = 4 | |
192 U16text = 5 */ | |
193 | |
194 switch (mode) { | |
195 case 0 : WIN_SETMODE (handle, _O_BINARY); break; | |
196 case 1 : WIN_SETMODE (handle, __gnat_current_ccs_encoding); break; | |
197 case 2 : WIN_SETMODE (handle, _O_TEXT); break; | |
198 case 3 : WIN_SETMODE (handle, _O_U8TEXT); break; | |
199 case 4 : WIN_SETMODE (handle, _O_WTEXT); break; | |
200 case 5 : WIN_SETMODE (handle, _O_U16TEXT); break; | |
201 } | |
202 } | |
203 #endif | |
204 | |
205 #ifdef __CYGWIN__ | |
206 | |
207 char * | |
208 __gnat_ttyname (int filedes) | |
209 { | |
210 extern char *ttyname (int); | |
211 | |
212 return ttyname (filedes); | |
213 } | |
214 | |
215 #endif /* __CYGWIN__ */ | |
216 | |
217 #if defined (__CYGWIN__) || defined (__MINGW32__) | |
218 #include <windows.h> | |
219 | |
220 int __gnat_is_windows_xp (void); | |
221 | |
222 int | |
223 __gnat_is_windows_xp (void) | |
224 { | |
225 static int is_win_xp=0, is_win_xp_checked=0; | |
226 | |
227 if (!is_win_xp_checked) | |
228 { | |
229 OSVERSIONINFO version; | |
230 | |
231 is_win_xp_checked = 1; | |
232 | |
233 memset (&version, 0, sizeof (version)); | |
234 version.dwOSVersionInfoSize = sizeof (version); | |
235 | |
236 is_win_xp = GetVersionEx (&version) | |
237 && version.dwPlatformId == VER_PLATFORM_WIN32_NT | |
238 && (version.dwMajorVersion > 5 | |
239 || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1)); | |
240 } | |
241 return is_win_xp; | |
242 } | |
243 | |
244 /* Get the bounds of the stack. The stack pointer is supposed to be | |
245 initialized to BASE when a thread is created and the stack can be extended | |
246 to LIMIT before reaching a guard page. | |
247 Note: for the main thread, the system automatically extend the stack, so | |
248 LIMIT is only the current limit. */ | |
249 | |
250 void | |
251 __gnat_get_stack_bounds (void **base, void **limit) | |
252 { | |
253 NT_TIB *tib; | |
254 | |
255 /* We know that the first field of the TEB is the TIB. */ | |
256 tib = (NT_TIB *)NtCurrentTeb (); | |
257 | |
258 *base = tib->StackBase; | |
259 *limit = tib->StackLimit; | |
260 } | |
261 | |
262 #endif /* __CYGWIN__ || __MINGW32__ */ | |
263 | |
264 #ifdef __MINGW32__ | |
265 | |
266 /* Return the name of the tty. Under windows there is no name for | |
267 the tty, so this function, if connected to a tty, returns the generic name | |
268 "console". */ | |
269 | |
270 char * | |
271 __gnat_ttyname (int filedes) | |
272 { | |
273 if (isatty (filedes)) | |
274 return "console"; | |
275 else | |
276 return NULL; | |
277 } | |
278 | |
279 #endif /* __MINGW32__ */ | |
280 | |
281 #else | |
282 | |
283 const char __gnat_text_translation_required = 0; | |
284 | |
285 /* These functions do nothing in non-DOS systems. */ | |
286 | |
287 void | |
288 __gnat_set_binary_mode (int handle ATTRIBUTE_UNUSED) | |
289 { | |
290 } | |
291 | |
292 void | |
293 __gnat_set_text_mode (int handle ATTRIBUTE_UNUSED) | |
294 { | |
295 } | |
296 | |
297 void | |
298 __gnat_set_mode (int handle ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED) | |
299 { | |
300 } | |
301 | |
302 char * | |
303 __gnat_ttyname (int filedes) | |
304 { | |
305 #if defined (__vxworks) | |
306 return ""; | |
307 #else | |
308 extern char *ttyname (int); | |
309 | |
310 return ttyname (filedes); | |
311 #endif /* defined (__vxworks) */ | |
312 } | |
313 #endif | |
314 | |
315 #if defined (__linux__) || defined (__sun__) \ | |
316 || defined (WINNT) \ | |
317 || defined (__MACHTEN__) || defined (__hpux__) || defined (_AIX) \ | |
318 || (defined (__svr4__) && defined (__i386__)) || defined (__Lynx__) \ | |
319 || defined (__CYGWIN__) || defined (__FreeBSD__) || defined (__OpenBSD__) \ | |
320 || defined (__GLIBC__) || defined (__APPLE__) || defined (__DragonFly__) | |
321 | |
322 # ifdef __MINGW32__ | |
323 # if OLD_MINGW | |
324 # include <termios.h> | |
325 # else | |
326 # include <conio.h> /* for getch(), kbhit() */ | |
327 # endif | |
328 # else | |
329 # include <termios.h> | |
330 # endif | |
331 | |
332 #endif | |
333 | |
334 /* Implements the common processing for getc_immediate and | |
335 getc_immediate_nowait. */ | |
336 | |
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); | |
340 | |
341 /* Called by Get_Immediate (Foo); */ | |
342 | |
343 void | |
344 getc_immediate (FILE *stream, int *ch, int *end_of_file) | |
345 { | |
346 int avail; | |
347 | |
348 getc_immediate_common (stream, ch, end_of_file, &avail, 1); | |
349 } | |
350 | |
351 /* Called by Get_Immediate (Foo, Available); */ | |
352 | |
353 void | |
354 getc_immediate_nowait (FILE *stream, int *ch, int *end_of_file, int *avail) | |
355 { | |
356 getc_immediate_common (stream, ch, end_of_file, avail, 0); | |
357 } | |
358 | |
359 /* Called by getc_immediate () and getc_immediate_nowait () */ | |
360 | |
361 void | |
362 getc_immediate_common (FILE *stream, | |
363 int *ch, | |
364 int *end_of_file, | |
365 int *avail, | |
366 int waiting ATTRIBUTE_UNUSED) | |
367 { | |
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 char c; | |
374 int nread; | |
375 int good_one = 0; | |
376 int eof_ch = 4; /* Ctrl-D */ | |
377 int fd = fileno (stream); | |
378 struct termios otermios_rec, termios_rec; | |
379 | |
380 if (isatty (fd)) | |
381 { | |
382 tcgetattr (fd, &termios_rec); | |
383 memcpy (&otermios_rec, &termios_rec, sizeof (struct termios)); | |
384 | |
385 /* Set RAW mode, with no echo */ | |
386 termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON & ~ECHO; | |
387 | |
388 #if defined (__linux__) || defined (__sun__) \ | |
389 || defined (__MACHTEN__) || defined (__hpux__) \ | |
390 || defined (_AIX) || (defined (__svr4__) && defined (__i386__)) \ | |
391 || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \ | |
392 || defined (__GLIBC__) || defined (__APPLE__) || defined (__DragonFly__) | |
393 eof_ch = termios_rec.c_cc[VEOF]; | |
394 | |
395 /* If waiting (i.e. Get_Immediate (Char)), set MIN = 1 and wait for | |
396 a character forever. This doesn't seem to effect Ctrl-Z or | |
397 Ctrl-C processing. | |
398 If not waiting (i.e. Get_Immediate (Char, Available)), | |
399 don't wait for anything but timeout immediately. */ | |
400 termios_rec.c_cc[VMIN] = waiting; | |
401 termios_rec.c_cc[VTIME] = 0; | |
402 #endif | |
403 tcsetattr (fd, TCSANOW, &termios_rec); | |
404 | |
405 while (! good_one) | |
406 { | |
407 /* Read is used here instead of fread, because fread doesn't | |
408 work on Solaris5 and Sunos4 in this situation. Maybe because we | |
409 are mixing calls that use file descriptors and streams. */ | |
410 nread = read (fd, &c, 1); | |
411 if (nread > 0) | |
412 { | |
413 /* On Unix terminals, Ctrl-D (EOT) is an End of File. */ | |
414 if (c == eof_ch) | |
415 { | |
416 *avail = 0; | |
417 *end_of_file = 1; | |
418 good_one = 1; | |
419 } | |
420 | |
421 /* Everything else is ok */ | |
422 else if (c != eof_ch) | |
423 { | |
424 *avail = 1; | |
425 *end_of_file = 0; | |
426 good_one = 1; | |
427 } | |
428 } | |
429 | |
430 else if (! waiting) | |
431 { | |
432 *avail = 0; | |
433 *end_of_file = 0; | |
434 good_one = 1; | |
435 } | |
436 else | |
437 good_one = 0; | |
438 } | |
439 | |
440 tcsetattr (fd, TCSANOW, &otermios_rec); | |
441 *ch = c; | |
442 } | |
443 | |
444 else | |
445 #elif defined (__MINGW32__) | |
446 int fd = fileno (stream); | |
447 int char_waiting; | |
448 int eot_ch = 4; /* Ctrl-D */ | |
449 | |
450 if (isatty (fd)) | |
451 { | |
452 if (waiting) | |
453 { | |
454 *ch = getch (); | |
455 | |
456 if (*ch == eot_ch) | |
457 *end_of_file = 1; | |
458 else | |
459 *end_of_file = 0; | |
460 | |
461 *avail = 1; | |
462 } | |
463 else /* ! waiting */ | |
464 { | |
465 char_waiting = kbhit(); | |
466 | |
467 if (char_waiting == 1) | |
468 { | |
469 *avail = 1; | |
470 *ch = getch (); | |
471 | |
472 if (*ch == eot_ch) | |
473 *end_of_file = 1; | |
474 else | |
475 *end_of_file = 0; | |
476 } | |
477 else | |
478 { | |
479 *avail = 0; | |
480 *end_of_file = 0; | |
481 } | |
482 } | |
483 } | |
484 else | |
485 #elif defined (__vxworks) | |
486 /* Bit masks of file descriptors to read from. */ | |
487 struct fd_set readFds; | |
488 /* Timeout before select returns if nothing can be read. */ | |
489 struct timeval timeOut; | |
490 char c; | |
491 int fd = fileno (stream); | |
492 int nread; | |
493 int option; | |
494 int readable; | |
495 int status; | |
496 int width; | |
497 | |
498 if (isatty (fd)) | |
499 { | |
500 /* If we do not want to wait, we have to set up fd in RAW mode. This | |
501 should be done outside this function as setting fd in RAW mode under | |
502 vxWorks flushes the buffer of fd. If the RAW mode was set here, the | |
503 buffer would be empty and we would always return that no character | |
504 is available */ | |
505 if (! waiting) | |
506 { | |
507 /* Initialization of timeOut for its use with select. */ | |
508 timeOut.tv_sec = 0; | |
509 timeOut.tv_usec = 0; | |
510 | |
511 /* Initialization of readFds for its use with select; | |
512 FD is the only file descriptor to be monitored */ | |
513 FD_ZERO (&readFds); | |
514 FD_SET (fd, &readFds); | |
515 width = 2; | |
516 | |
517 /* We do all this processing to emulate a non blocking read. */ | |
518 readable = select (width, &readFds, NULL, NULL, &timeOut); | |
519 if (readable == ERROR) | |
520 *avail = -1, *end_of_file = -1; | |
521 /* No character available in input. */ | |
522 else if (readable == 0) | |
523 *avail = 0, *end_of_file = 0; | |
524 else | |
525 { | |
526 nread = read (fd, &c, 1); | |
527 if (nread > 0) | |
528 *avail = 1, *end_of_file = 0; | |
529 /* End Of File. */ | |
530 else if (nread == 0) | |
531 *avail = 0, *end_of_file = 1; | |
532 /* Error. */ | |
533 else | |
534 *avail = -1, *end_of_file = -1; | |
535 } | |
536 } | |
537 | |
538 /* We have to wait until we get a character */ | |
539 else | |
540 { | |
541 *avail = -1; | |
542 *end_of_file = -1; | |
543 | |
544 /* Save the current mode of FD. */ | |
545 option = ioctl (fd, FIOGETOPTIONS, 0); | |
546 | |
547 /* Set FD in RAW mode. */ | |
548 status = ioctl (fd, FIOSETOPTIONS, OPT_RAW); | |
549 if (status != -1) | |
550 { | |
551 nread = read (fd, &c, 1); | |
552 if (nread > 0) | |
553 *avail = 1, *end_of_file = 0; | |
554 /* End of file. */ | |
555 else if (nread == 0) | |
556 *avail = 0, *end_of_file = 1; | |
557 /* Else there is an ERROR. */ | |
558 } | |
559 | |
560 /* Revert FD to its previous mode. */ | |
561 status = ioctl (fd, FIOSETOPTIONS, option); | |
562 } | |
563 | |
564 *ch = c; | |
565 } | |
566 else | |
567 #endif | |
568 { | |
569 /* If we're not on a terminal, then we don't need any fancy processing. | |
570 Also this is the only thing that's left if we're not on one of the | |
571 supported systems; which means that for non supported systems, | |
572 get_immediate may wait for a carriage return on terminals. */ | |
573 *ch = fgetc (stream); | |
574 if (feof (stream)) | |
575 { | |
576 *end_of_file = 1; | |
577 *avail = 0; | |
578 } | |
579 else | |
580 { | |
581 *end_of_file = 0; | |
582 *avail = 1; | |
583 } | |
584 } | |
585 } | |
586 | |
587 /* The following definitions are provided in NT to support Windows based | |
588 Ada programs. */ | |
589 | |
590 #ifdef WINNT | |
591 #include <windows.h> | |
592 | |
593 /* Provide functions to echo the values passed to WinMain (windows bindings | |
594 will want to import these). We use the same names as the routines used | |
595 by AdaMagic for compatibility. */ | |
596 | |
597 char *rts_get_hInstance (void); | |
598 char *rts_get_hPrevInstance (void); | |
599 char *rts_get_lpCommandLine (void); | |
600 int rts_get_nShowCmd (void); | |
601 | |
602 char * | |
603 rts_get_hInstance (void) | |
604 { | |
605 return (char *)GetModuleHandleA (0); | |
606 } | |
607 | |
608 char * | |
609 rts_get_hPrevInstance (void) | |
610 { | |
611 return 0; | |
612 } | |
613 | |
614 char * | |
615 rts_get_lpCommandLine (void) | |
616 { | |
617 return GetCommandLineA (); | |
618 } | |
619 | |
620 int | |
621 rts_get_nShowCmd (void) | |
622 { | |
623 return 1; | |
624 } | |
625 | |
626 #endif /* WINNT */ | |
627 | |
628 /* This value is returned as the time zone offset when a valid value | |
629 cannot be determined. It is simply a bizarre value that will never | |
630 occur. It is 3 days plus 73 seconds (offset is in seconds). */ | |
631 | |
632 long __gnat_invalid_tzoff = 259273; | |
633 | |
634 /* Definition of __gnat_localtime_r used by a-calend.adb */ | |
635 | |
636 #if defined (__MINGW32__) | |
637 | |
638 /* Reentrant localtime for Windows. */ | |
639 | |
640 extern void | |
641 __gnat_localtime_tzoff (const time_t *, const int *, long *); | |
642 | |
643 static const unsigned long long w32_epoch_offset = 11644473600ULL; | |
644 void | |
645 __gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off) | |
646 { | |
647 TIME_ZONE_INFORMATION tzi; | |
648 | |
649 DWORD tzi_status; | |
650 | |
651 tzi_status = GetTimeZoneInformation (&tzi); | |
652 | |
653 /* Cases where we simply want to extract the offset of the current time | |
654 zone, regardless of the date. A value of "0" for flag "is_historic" | |
655 signifies that the date is NOT historic, see the | |
656 body of Ada.Calendar.UTC_Time_Offset. */ | |
657 | |
658 if (*is_historic == 0) { | |
659 *off = tzi.Bias; | |
660 | |
661 /* The system is operating in the range covered by the StandardDate | |
662 member. */ | |
663 if (tzi_status == TIME_ZONE_ID_STANDARD) { | |
664 *off = *off + tzi.StandardBias; | |
665 } | |
666 | |
667 /* The system is operating in the range covered by the DaylightDate | |
668 member. */ | |
669 else if (tzi_status == TIME_ZONE_ID_DAYLIGHT) { | |
670 *off = *off + tzi.DaylightBias; | |
671 } | |
672 | |
673 *off = *off * -60; | |
674 } | |
675 | |
676 /* Time zone offset calculations for a historic or future date */ | |
677 | |
678 else { | |
679 union | |
680 { | |
681 FILETIME ft_time; | |
682 unsigned long long ull_time; | |
683 } utc_time, local_time; | |
684 | |
685 SYSTEMTIME utc_sys_time, local_sys_time; | |
686 BOOL status; | |
687 | |
688 /* First convert unix time_t structure to windows FILETIME format. */ | |
689 utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset) | |
690 * 10000000ULL; | |
691 | |
692 /* If GetTimeZoneInformation does not return a value between 0 and 2 then | |
693 it means that we were not able to retrieve timezone information. Note | |
694 that we cannot use here FileTimeToLocalFileTime as Windows will use in | |
695 always in this case the current timezone setting. As suggested on MSDN | |
696 we use the following three system calls to get the right information. | |
697 Note also that starting with Windows Vista new functions are provided | |
698 to get timezone settings that depend on the year. We cannot use them as | |
699 we still support Windows XP and Windows 2003. */ | |
700 | |
701 status = (tzi_status >= 0 && tzi_status <= 2) | |
702 && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time) | |
703 && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time) | |
704 && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time); | |
705 | |
706 /* An error has occurred, return invalid_tzoff */ | |
707 | |
708 if (!status) { | |
709 *off = __gnat_invalid_tzoff; | |
710 } | |
711 else { | |
712 if (local_time.ull_time > utc_time.ull_time) { | |
713 *off = (long) ((local_time.ull_time - utc_time.ull_time) | |
714 / 10000000ULL); | |
715 } | |
716 else { | |
717 *off = - (long) ((utc_time.ull_time - local_time.ull_time) | |
718 / 10000000ULL); | |
719 } | |
720 } | |
721 } | |
722 } | |
723 | |
724 #elif defined (__Lynx__) | |
725 | |
726 /* On Lynx, all time values are treated in GMT */ | |
727 | |
728 /* As of LynxOS 3.1.0a patch level 040, LynuxWorks changes the | |
729 prototype to the C library function localtime_r from the POSIX.4 | |
730 Draft 9 to the POSIX 1.c version. Before this change the following | |
731 spec is required. Only use when ___THREADS_POSIX4ad4__ is defined, | |
732 the Lynx convention when building against the legacy API. */ | |
733 | |
734 extern void | |
735 __gnat_localtime_tzoff (const time_t *, const int *, long *); | |
736 | |
737 void | |
738 __gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off) | |
739 { | |
740 *off = 0; | |
741 } | |
742 | |
743 #else | |
744 | |
745 /* Other targets except Lynx and Windows provide a standard localtime_r */ | |
746 | |
747 #define Lock_Task system__soft_links__lock_task | |
748 extern void (*Lock_Task) (void); | |
749 | |
750 #define Unlock_Task system__soft_links__unlock_task | |
751 extern void (*Unlock_Task) (void); | |
752 | |
753 extern void | |
754 __gnat_localtime_tzoff (const time_t *, const int *, long *); | |
755 | |
756 void | |
757 __gnat_localtime_tzoff (const time_t *timer ATTRIBUTE_UNUSED, | |
758 const int *is_historic ATTRIBUTE_UNUSED, | |
759 long *off ATTRIBUTE_UNUSED) | |
760 { | |
761 struct tm tp ATTRIBUTE_UNUSED; | |
762 | |
763 /* AIX, HPUX, Sun Solaris */ | |
764 #if defined (_AIX) || defined (__hpux__) || defined (__sun__) | |
765 { | |
766 (*Lock_Task) (); | |
767 | |
768 localtime_r (timer, &tp); | |
769 *off = (long) -timezone; | |
770 | |
771 (*Unlock_Task) (); | |
772 | |
773 /* Correct the offset if Daylight Saving Time is in effect */ | |
774 | |
775 if (tp.tm_isdst > 0) | |
776 *off = *off + 3600; | |
777 } | |
778 | |
779 /* VxWorks */ | |
780 #elif defined (__vxworks) | |
781 #include <stdlib.h> | |
782 { | |
783 (*Lock_Task) (); | |
784 | |
785 localtime_r (timer, &tp); | |
786 | |
787 /* Try to read the environment variable TIMEZONE. The variable may not have | |
788 been initialize, in that case return an offset of zero (0) for UTC. */ | |
789 | |
790 char *tz_str = getenv ("TIMEZONE"); | |
791 | |
792 if ((tz_str == NULL) || (*tz_str == '\0')) | |
793 *off = 0; | |
794 else | |
795 { | |
796 char *tz_start, *tz_end; | |
797 | |
798 /* The format of the data contained in TIMEZONE is N::U:S:E where N is the | |
799 name of the time zone, U are the minutes difference from UTC, S is the | |
800 start of DST in mmddhh and E is the end of DST in mmddhh. Extracting | |
801 the value of U involves setting two pointers, one at the beginning and | |
802 one at the end of the value. The end pointer is then set to null in | |
803 order to delimit a string slice for atol to process. */ | |
804 | |
805 tz_start = index (tz_str, ':') + 2; | |
806 tz_end = index (tz_start, ':'); | |
807 *tz_end = '\0'; | |
808 | |
809 /* The Ada layer expects an offset in seconds. Note that we must reverse | |
810 the sign of the result since west is positive and east is negative on | |
811 VxWorks targets. */ | |
812 | |
813 *off = -atol (tz_start) * 60; | |
814 | |
815 /* Correct the offset if Daylight Saving Time is in effect */ | |
816 | |
817 if (tp.tm_isdst > 0) | |
818 *off = *off + 3600; | |
819 } | |
820 | |
821 (*Unlock_Task) (); | |
822 } | |
823 | |
824 /* Darwin, Free BSD, Linux, where component tm_gmtoff is present in | |
825 struct tm */ | |
826 | |
827 #elif defined (__APPLE__) || defined (__FreeBSD__) || defined (__linux__) \ | |
828 || defined (__GLIBC__) || defined (__DragonFly__) || defined (__OpenBSD__) \ | |
829 || defined (__DJGPP__) | |
830 { | |
831 localtime_r (timer, &tp); | |
832 *off = tp.tm_gmtoff; | |
833 } | |
834 | |
835 /* Default: treat all time values in GMT */ | |
836 | |
837 #else | |
838 *off = 0; | |
839 | |
840 #endif /* defined(_AIX) ... */ | |
841 } | |
842 | |
843 #endif | |
844 | |
845 #ifdef __vxworks | |
846 | |
847 #include <taskLib.h> | |
848 | |
849 /* __gnat_get_task_options is used by s-taprop.adb only for VxWorks. This | |
850 function returns the options to be set when creating a new task. It fetches | |
851 the options assigned to the current task (parent), so offering some user | |
852 level control over the options for a task hierarchy. It forces VX_FP_TASK | |
853 because it is almost always required. On processors with the SPE | |
854 category, VX_SPE_TASK should be used instead to enable the SPE. */ | |
855 extern int __gnat_get_task_options (void); | |
856 | |
857 int | |
858 __gnat_get_task_options (void) | |
859 { | |
860 int options; | |
861 | |
862 /* Get the options for the task creator */ | |
863 taskOptionsGet (taskIdSelf (), &options); | |
864 | |
865 /* Force VX_FP_TASK or VX_SPE_TASK as needed */ | |
866 #if defined (__SPE__) | |
867 options |= VX_SPE_TASK; | |
868 #else | |
869 options |= VX_FP_TASK; | |
870 #endif | |
871 | |
872 /* Mask those bits that are not under user control */ | |
873 #ifdef VX_USR_TASK_OPTIONS | |
874 /* O810-007, TSR 00043679: | |
875 Workaround a bug in Vx-7 where VX_DEALLOC_TCB == VX_PRIVATE_UMASK and: | |
876 - VX_DEALLOC_TCB is an internal option not to be used by users | |
877 - VX_PRIVATE_UMASK as a user-definable option | |
878 This leads to VX_USR_TASK_OPTIONS allowing 0x8000 as VX_PRIVATE_UMASK but | |
879 taskCreate refusing this option (VX_DEALLOC_TCB is not allowed) | |
880 | |
881 Note that the same error occurs in both RTP and Kernel mode, but | |
882 VX_DEALLOC_TCB is not defined in the RTP headers, so we need to | |
883 explicitely check if VX_PRIVATE_UMASK has value 0x8000 | |
884 */ | |
885 # if defined (VX_PRIVATE_UMASK) && (0x8000 == VX_PRIVATE_UMASK) | |
886 options &= ~VX_PRIVATE_UMASK; | |
887 # endif | |
888 options &= VX_USR_TASK_OPTIONS; | |
889 #endif | |
890 return options; | |
891 } | |
892 | |
893 #endif | |
894 | |
895 int | |
896 __gnat_is_file_not_found_error (int errno_val) { | |
897 switch (errno_val) { | |
898 case ENOENT: | |
899 #ifdef __vxworks | |
900 /* In the case of VxWorks, we also have to take into account various | |
901 * filesystem-specific variants of this error. | |
902 */ | |
903 #if ! defined (VTHREADS) && (_WRS_VXWORKS_MAJOR < 7) | |
904 case S_dosFsLib_FILE_NOT_FOUND: | |
905 #endif | |
906 #if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__)) | |
907 case S_nfsLib_NFSERR_NOENT: | |
908 #endif | |
909 #if defined (__RTP__) | |
910 /* An RTP can return an NFS file not found, and the NFS bits must | |
911 first be masked on to check the errno. */ | |
912 case M_nfsStat | ENOENT: | |
913 #endif | |
914 #endif | |
915 return 1; | |
916 | |
917 default: | |
918 return 0; | |
919 } | |
920 } | |
921 | |
922 #if defined (__linux__) | |
923 | |
924 /* Note well: If this code is modified, it should be tested by hand, | |
925 because automated testing doesn't exercise it. | |
926 */ | |
927 | |
928 /* HAVE_CAPABILITY is supposed to be defined if sys/capability.h exists on the | |
929 system where this is being compiled. If this macro is defined, we #include | |
930 the header. Otherwise we have the relevant declarations textually here. | |
931 */ | |
932 | |
933 #if defined (HAVE_CAPABILITY) | |
934 #include <sys/capability.h> | |
935 #else | |
936 | |
937 /* HAVE_CAPABILITY is not defined, so sys/capability.h does might not exist. */ | |
938 | |
939 typedef struct _cap_struct *cap_t; | |
940 typedef enum { | |
941 CAP_CLEAR=0, | |
942 CAP_SET=1 | |
943 } cap_flag_value_t; | |
944 #define CAP_SYS_NICE 23 | |
945 typedef enum { | |
946 CAP_EFFECTIVE=0, /* Specifies the effective flag */ | |
947 CAP_PERMITTED=1, /* Specifies the permitted flag */ | |
948 CAP_INHERITABLE=2 /* Specifies the inheritable flag */ | |
949 } cap_flag_t; | |
950 | |
951 typedef int cap_value_t; | |
952 | |
953 extern cap_t cap_get_proc(void); | |
954 extern int cap_get_flag(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *); | |
955 extern int cap_free(void *); | |
956 | |
957 #endif | |
958 | |
959 /* __gnat_has_cap_sys_nice returns 1 if the current process has the | |
960 CAP_SYS_NICE capability. This capability is necessary to use the | |
961 Ceiling_Locking policy. Returns 0 otherwise. Note that this is | |
962 defined only for Linux. | |
963 */ | |
964 | |
965 /* Define these as weak symbols, so if support for capabilities is not present, | |
966 programs can still link. On Ubuntu, support for capabilities can be | |
967 installed via "sudo apt-get --assume-yes install libcap-dev". | |
968 In addition, the user must link with "-lcap", or else these | |
969 symbols will be 0, and __gnat_has_cap_sys_nice will return 0. | |
970 */ | |
971 | |
972 static cap_t cap_get_proc_weak(void) | |
973 __attribute__ ((weakref ("cap_get_proc"))); | |
974 static int cap_get_flag_weak(cap_t, cap_value_t, cap_flag_t, cap_flag_value_t *) | |
975 __attribute__ ((weakref ("cap_get_flag"))); | |
976 static int cap_free_weak(void *) | |
977 __attribute__ ((weakref ("cap_free"))); | |
978 | |
979 int | |
980 __gnat_has_cap_sys_nice () { | |
981 /* If the address of cap_get_proc_weak is 0, this means support for | |
982 capabilities is not present, so we return 0. */ | |
983 if (&cap_get_proc_weak == 0) | |
984 return 0; | |
985 | |
986 cap_t caps = cap_get_proc_weak(); | |
987 if (caps == NULL) | |
988 return 0; | |
989 | |
990 cap_flag_value_t value; | |
991 | |
992 if (cap_get_flag_weak(caps, CAP_SYS_NICE, CAP_EFFECTIVE, &value) == -1) | |
993 return 0; | |
994 | |
995 if (cap_free_weak(caps) == -1) | |
996 return 0; | |
997 | |
998 if (value == CAP_SET) | |
999 return 1; | |
1000 | |
1001 return 0; | |
1002 } | |
1003 #endif | |
1004 | |
1005 #ifdef __ANDROID__ | |
1006 | |
1007 /* Provide extern symbols for sig* as needed by the tasking run-time, instead | |
1008 of static inline functions. */ | |
1009 | |
1010 #include <signal.h> | |
1011 | |
1012 int | |
1013 _sigismember (sigset_t *set, int signum) | |
1014 { | |
1015 return sigismember (set, signum); | |
1016 } | |
1017 | |
1018 int | |
1019 _sigaddset (sigset_t *set, int signum) | |
1020 { | |
1021 return sigaddset (set, signum); | |
1022 } | |
1023 | |
1024 int | |
1025 _sigdelset (sigset_t *set, int signum) | |
1026 { | |
1027 return sigdelset (set, signum); | |
1028 } | |
1029 | |
1030 int | |
1031 _sigemptyset (sigset_t *set) | |
1032 { | |
1033 return sigemptyset (set); | |
1034 } | |
1035 | |
1036 int | |
1037 _sigfillset (sigset_t *set) | |
1038 { | |
1039 return sigfillset (set); | |
1040 } | |
1041 | |
1042 #include <unistd.h> | |
1043 int | |
1044 _getpagesize (void) | |
1045 { | |
1046 return getpagesize (); | |
1047 } | |
1048 #endif |