111
|
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
|