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