OSDN Git Service

PR other/52438
[pf3gnuchains/gcc-fork.git] / gcc / ada / sysdep.c
index ffda3ab..bfe7bce 100644 (file)
@@ -6,7 +6,7 @@
  *                                                                          *
  *                          C Implementation File                           *
  *                                                                          *
- *         Copyright (C) 1992-2009, Free Software Foundation, Inc.          *
+ *         Copyright (C) 1992-2012, Free Software Foundation, Inc.          *
  *                                                                          *
  * GNAT is free software;  you can  redistribute it  and/or modify it under *
  * terms of the  GNU General Public License as published  by the Free Soft- *
 
 #ifdef __vxworks
 #include "ioLib.h"
+#if ! defined (VTHREADS)
 #include "dosFsLib.h"
-#if ! defined ( __RTP__) && ! defined (VTHREADS)
+#endif
+#if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
 # include "nfsLib.h"
 #endif
 #include "selectLib.h"
@@ -67,55 +69,17 @@ extern struct tm *localtime_r(const time_t *, struct tm *);
 
 #include "adaint.h"
 
-/*
-   mode_read_text
-   open text file for reading
-   rt for DOS and Windows NT, r for Unix
-
-   mode_write_text
-   truncate to zero length or create text file for writing
-   wt for DOS and Windows NT, w for Unix
-
-   mode_append_text
-   append; open or create text file for writing at end-of-file
-   at for DOS and Windows NT, a for Unix
-
-   mode_read_binary
-   open binary file for reading
-   rb for DOS and Windows NT, r for Unix
-
-   mode_write_binary
-   truncate to zero length or create binary file for writing
-   wb for DOS and Windows NT, w for Unix
-
-   mode_append_binary
-   append; open or create binary file for writing at end-of-file
-   ab for DOS and Windows NT, a for Unix
-
-   mode_read_text_plus
-   open text file for update (reading and writing)
-   r+t for DOS and Windows NT, r+ for Unix
-
-   mode_write_text_plus
-   truncate to zero length or create text file for update
-   w+t for DOS and Windows NT, w+ for Unix
-
-   mode_append_text_plus
-   append; open or create text file for update, writing at end-of-file
-   a+t for DOS and Windows NT, a+ for Unix
-
-   mode_read_binary_plus
-   open binary file for update (reading and writing)
-   r+b for DOS and Windows NT, r+ for Unix
-
-   mode_write_binary_plus
-   truncate to zero length or create binary file for update
-   w+b for DOS and Windows NT, w+ for Unix
-
-   mode_append_binary_plus
-   append; open or create binary file for update, writing at end-of-file
-   a+b for DOS and Windows NT, a+ for Unix
+/* Don't use macros versions of this functions on VxWorks since they cause
+   imcompatible changes in some VxWorks versions */
+#ifdef __vxworks
+#undef getchar
+#undef putchar
+#undef feof
+#undef ferror
+#undef fileno
+#endif
 
+/*
    Notes:
 
    (1) Opening a file with read mode fails if the file does not exist or
@@ -156,127 +120,48 @@ extern struct tm *localtime_r(const time_t *, struct tm *);
 
 */
 
-#if defined(WINNT) || defined (MSDOS) || defined (__EMX__)
-static const char *mode_read_text = "rt";
-static const char *mode_write_text = "wt";
-static const char *mode_append_text = "at";
-static const char *mode_read_binary = "rb";
-static const char *mode_write_binary = "wb";
-static const char *mode_append_binary = "ab";
-static const char *mode_read_text_plus = "r+t";
-static const char *mode_write_text_plus = "w+t";
-static const char *mode_append_text_plus = "a+t";
-static const char *mode_read_binary_plus = "r+b";
-static const char *mode_write_binary_plus = "w+b";
-static const char *mode_append_binary_plus = "a+b";
+#if defined (WINNT) || defined (__CYGWIN__)
+
 const char __gnat_text_translation_required = 1;
 
+#ifdef __CYGWIN__
+#define WIN_SETMODE setmode
+#include <io.h>
+#else
+#define WIN_SETMODE _setmode
+#endif
+
 void
 __gnat_set_binary_mode (int handle)
 {
-  _setmode (handle, O_BINARY);
+  WIN_SETMODE (handle, O_BINARY);
 }
 
 void
 __gnat_set_text_mode (int handle)
 {
-  _setmode (handle, O_TEXT);
+  WIN_SETMODE (handle, O_TEXT);
 }
 
-#ifdef __MINGW32__
-#include <windows.h>
-
-/* Return the name of the tty.   Under windows there is no name for
-   the tty, so this function, if connected to a tty, returns the generic name
-   "console".  */
+#ifdef __CYGWIN__
 
 char *
 __gnat_ttyname (int filedes)
 {
-  if (isatty (filedes))
-    return "console";
-  else
-    return NULL;
-}
-
-/* This function is needed to fix a bug under Win95/98. Under these platforms
-   doing :
-                ch1 = getch();
-               ch2 = fgetc (stdin);
-
-   will put the same character into ch1 and ch2. It seem that the character
-   read by getch() is not correctly removed from the buffer. Even a
-   fflush(stdin) does not fix the bug. This bug does not appear under Window
-   NT. So we have two version of this routine below one for 95/98 and one for
-   NT/2000 version of Windows. There is also a special routine (winflushinit)
-   that will be called only the first time to check which version of Windows
-   we are running running on to set the right routine to use.
-
-   This problem occurs when using Text_IO.Get_Line after Text_IO.Get_Immediate
-   for example.
-
-   Calling FlushConsoleInputBuffer just after getch() fix the bug under
-   95/98. */
-
-#ifdef RTX
-
-static void winflush_nt (void);
-
-/* winflush_function will do nothing since we only have problems with Windows
-   95/98 which are not supported by RTX. */
-
-static void (*winflush_function) (void) = winflush_nt;
+  extern char *ttyname (int);
 
-static void
-winflush_nt (void)
-{
-  /* Does nothing as there is no problem under NT.  */
+  return ttyname (filedes);
 }
 
-#else
+#endif /* __CYGWIN__ */
 
-static void winflush_init (void);
-
-static void winflush_95 (void);
+#if defined (__CYGWIN__) || defined (__MINGW32__)
+#include <windows.h>
 
-static void winflush_nt (void);
+#ifndef RTX
 
 int __gnat_is_windows_xp (void);
 
-/* winflusfunction is set first to the winflushinit function which will check
-   the OS version 95/98 or NT/2000 */
-
-static void (*winflush_function) (void) = winflush_init;
-
-/* This function does the runtime check of the OS version and then sets
-   winflush_function to the appropriate function and then call it. */
-
-static void
-winflush_init (void)
-{
-  DWORD dwVersion = GetVersion();
-
-  if (dwVersion < 0x80000000)                /* Windows NT/2000 */
-    winflush_function = winflush_nt;
-  else                                       /* Windows 95/98   */
-    winflush_function = winflush_95;
-
-  (*winflush_function)();      /* Perform the 'flush' */
-
-}
-
-static void
-winflush_95 (void)
-{
-  FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
-}
-
-static void
-winflush_nt (void)
-{
-  /* Does nothing as there is no problem under NT.  */
-}
-
 int
 __gnat_is_windows_xp (void)
 {
@@ -299,24 +184,47 @@ __gnat_is_windows_xp (void)
   return is_win_xp;
 }
 
-#endif
+#endif /* !RTX */
 
-#endif
+/* Get the bounds of the stack.  The stack pointer is supposed to be
+   initialized to BASE when a thread is created and the stack can be extended
+   to LIMIT before reaching a guard page.
+   Note: for the main thread, the system automatically extend the stack, so
+   LIMIT is only the current limit.  */
+
+void
+__gnat_get_stack_bounds (void **base, void **limit)
+{
+  NT_TIB *tib;
+
+  /* We know that the first field of the TEB is the TIB.  */
+  tib = (NT_TIB *)NtCurrentTeb ();
+
+  *base = tib->StackBase;
+  *limit = tib->StackLimit;
+}
+
+#endif /* __CYGWIN__ || __MINGW32__ */
+
+#ifdef __MINGW32__
+
+/* Return the name of the tty.   Under windows there is no name for
+   the tty, so this function, if connected to a tty, returns the generic name
+   "console".  */
+
+char *
+__gnat_ttyname (int filedes)
+{
+  if (isatty (filedes))
+    return "console";
+  else
+    return NULL;
+}
+
+#endif /* __MINGW32__ */
 
 #else
 
-static const char *mode_read_text = "r";
-static const char *mode_write_text = "w";
-static const char *mode_append_text = "a";
-static const char *mode_read_binary = "r";
-static const char *mode_write_binary = "w";
-static const char *mode_append_binary = "a";
-static const char *mode_read_text_plus = "r+";
-static const char *mode_write_text_plus = "w+";
-static const char *mode_append_text_plus = "a+";
-static const char *mode_read_binary_plus = "r+";
-static const char *mode_write_binary_plus = "w+";
-static const char *mode_append_binary_plus = "a+";
 const char __gnat_text_translation_required = 0;
 
 /* These functions do nothing in non-DOS systems. */
@@ -343,7 +251,7 @@ __gnat_ttyname (int filedes)
 }
 #endif
 \f
-#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+#if defined (linux) || defined (sun) || defined (sgi) \
   || (defined (__osf__) && ! defined (__alpha_vxworks)) || defined (WINNT) \
   || defined (__MACHTEN__) || defined (__hpux__) || defined (_AIX) \
   || (defined (__svr4__) && defined (i386)) || defined (__Lynx__) \
@@ -401,7 +309,7 @@ getc_immediate_common (FILE *stream,
                        int *avail,
                        int waiting)
 {
-#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+#if defined (linux) || defined (sun) || defined (sgi) \
     || (defined (__osf__) && ! defined (__alpha_vxworks)) \
     || defined (__CYGWIN32__) || defined (__MACHTEN__) || defined (__hpux__) \
     || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
@@ -422,7 +330,7 @@ getc_immediate_common (FILE *stream,
       /* Set RAW mode, with no echo */
       termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON & ~ECHO;
 
-#if defined(linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+#if defined(linux) || defined (sun) || defined (sgi) \
     || defined (__osf__) || defined (__MACHTEN__) || defined (__hpux__) \
     || defined (_AIX) || (defined (__svr4__) && defined (i386)) \
     || defined (__Lynx__) || defined (__FreeBSD__) || defined (__OpenBSD__) \
@@ -431,18 +339,12 @@ getc_immediate_common (FILE *stream,
 
       /* If waiting (i.e. Get_Immediate (Char)), set MIN = 1 and wait for
          a character forever. This doesn't seem to effect Ctrl-Z or
-         Ctrl-C processing except on OS/2 where Ctrl-C won't work right
-         unless we do a read loop. Luckily we can delay a bit between
-         iterations. If not waiting (i.e. Get_Immediate (Char, Available)),
+         Ctrl-C processing.
+         If not waiting (i.e. Get_Immediate (Char, Available)),
          don't wait for anything but timeout immediately. */
-#ifdef __EMX__
-      termios_rec.c_cc[VMIN] = 0;
-      termios_rec.c_cc[VTIME] = waiting;
-#else
       termios_rec.c_cc[VMIN] = waiting;
       termios_rec.c_cc[VTIME] = 0;
 #endif
-#endif
       tcsetattr (fd, TCSANOW, &termios_rec);
 
       while (! good_one)
@@ -518,7 +420,6 @@ getc_immediate_common (FILE *stream,
       if (waiting)
        {
          *ch = getch ();
-         (*winflush_function) ();
 
          if (*ch == eot_ch)
            *end_of_file = 1;
@@ -535,7 +436,6 @@ getc_immediate_common (FILE *stream,
            {
              *avail = 1;
              *ch = getch ();
-             (*winflush_function) ();
 
              if (*ch == eot_ch)
                *end_of_file = 1;
@@ -718,7 +618,7 @@ long __gnat_invalid_tzoff = 259273;
 
 /* Definition of __gnat_localtime_r used by a-calend.adb */
 
-#if defined (__EMX__) || defined (__MINGW32__)
+#if defined (__MINGW32__)
 
 #ifdef CERT
 
@@ -741,74 +641,97 @@ extern void (*Unlock_Task) (void);
 
 #endif
 
-/* Reentrant localtime for Windows and OS/2. */
+/* Reentrant localtime for Windows. */
 
 extern void
-__gnat_localtime_tzoff (const time_t *, long *);
+__gnat_localtime_tzoff (const time_t *, const int *, long *);
 
 static const unsigned long long w32_epoch_offset = 11644473600ULL;
 void
-__gnat_localtime_tzoff (const time_t *timer, long *off)
+__gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
 {
-  union
-  {
-    FILETIME ft_time;
-    unsigned long long ull_time;
-  } utc_time, local_time;
-
-  SYSTEMTIME utc_sys_time, local_sys_time;
   TIME_ZONE_INFORMATION tzi;
 
-  BOOL  status = 1;
+  BOOL  rtx_active;
   DWORD tzi_status;
 
-  (*Lock_Task) ();
-
 #ifdef RTX
+  rtx_active = 1;
+#else
+  rtx_active = 0;
+#endif
+
+  (*Lock_Task) ();
 
   tzi_status = GetTimeZoneInformation (&tzi);
-  *off = tzi.Bias;
-  if (tzi_status == TIME_ZONE_ID_STANDARD)
-     /* The system is operating in the range covered by the StandardDate
-        member. */
-     *off = *off + tzi.StandardBias;
-  else if (tzi_status == TIME_ZONE_ID_DAYLIGHT)
-     /* The system is operating in the range covered by the DaylightDate
-        member. */
-     *off = *off + tzi.DaylightBias;
-  *off = *off * -60;
 
-#else
+  /* Processing for RTX targets or cases where we simply want to extract the
+     offset of the current time zone, regardless of the date. */
 
-  /* First convert unix time_t structure to windows FILETIME format.  */
-  utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset)
-                      * 10000000ULL;
+  if (rtx_active || !is_historic) {
+    *off = tzi.Bias;
 
-  tzi_status = GetTimeZoneInformation (&tzi);
+    /* The system is operating in the range covered by the StandardDate
+       member. */
+    if (tzi_status == TIME_ZONE_ID_STANDARD) {
+       *off = *off + tzi.StandardBias;
+    }
 
-  /* If GetTimeZoneInformation does not return a value between 0 and 2 then
-     it means that we were not able to retrieve timezone informations.
-     Note that we cannot use here FileTimeToLocalFileTime as Windows will use
-     in always in this case the current timezone setting. As suggested on
-     MSDN we use the following three system calls to get the right information.
-     Note also that starting with Windows Vista new functions are provided to
-     get timezone settings that depend on the year. We cannot use them as we
-     still support Windows XP and Windows 2003.  */
-  status = (tzi_status >= 0 && tzi_status <= 2)
-     && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time)
-     && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time)
-     && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time);
-
-  if (!status)
-     /* An error occurs so return invalid_tzoff.  */
-     *off = __gnat_invalid_tzoff;
-  else
-     if (local_time.ull_time > utc_time.ull_time)
-        *off = (long) ((local_time.ull_time - utc_time.ull_time) / 10000000ULL);
-     else
-        *off = - (long) ((utc_time.ull_time - local_time.ull_time) / 10000000ULL);
+    /* The system is operating in the range covered by the DaylightDate
+       member. */
+    else if (tzi_status == TIME_ZONE_ID_DAYLIGHT) {
+       *off = *off + tzi.DaylightBias;
+    }
 
-#endif
+    *off = *off * -60;
+  }
+
+  /* Time zone offset calculations for a historic or future date */
+
+  else {
+    union
+    {
+      FILETIME ft_time;
+      unsigned long long ull_time;
+    } utc_time, local_time;
+
+    SYSTEMTIME utc_sys_time, local_sys_time;
+    BOOL status;
+
+    /* First convert unix time_t structure to windows FILETIME format.  */
+    utc_time.ull_time = ((unsigned long long) *timer + w32_epoch_offset)
+                        * 10000000ULL;
+
+    /* If GetTimeZoneInformation does not return a value between 0 and 2 then
+       it means that we were not able to retrieve timezone informations. Note
+       that we cannot use here FileTimeToLocalFileTime as Windows will use in
+       always in this case the current timezone setting. As suggested on MSDN
+       we use the following three system calls to get the right information.
+       Note also that starting with Windows Vista new functions are provided
+       to get timezone settings that depend on the year. We cannot use them as
+       we still support Windows XP and Windows 2003.  */
+
+    status = (tzi_status >= 0 && tzi_status <= 2)
+      && FileTimeToSystemTime (&utc_time.ft_time, &utc_sys_time)
+      && SystemTimeToTzSpecificLocalTime (&tzi, &utc_sys_time, &local_sys_time)
+      && SystemTimeToFileTime (&local_sys_time, &local_time.ft_time);
+
+    /* An error has occured, return invalid_tzoff */
+
+    if (!status) {
+      *off = __gnat_invalid_tzoff;
+    }
+    else {
+      if (local_time.ull_time > utc_time.ull_time) {
+        *off = (long) ((local_time.ull_time - utc_time.ull_time)
+               / 10000000ULL);
+      }
+      else {
+        *off = - (long) ((utc_time.ull_time - local_time.ull_time)
+               / 10000000ULL);
+      }
+    }
+  }
 
   (*Unlock_Task) ();
 }
@@ -826,21 +749,21 @@ __gnat_localtime_tzoff (const time_t *timer, long *off)
    the Lynx convention when building against the legacy API. */
 
 extern void
-__gnat_localtime_tzoff (const time_t *, long *);
+__gnat_localtime_tzoff (const time_t *, const int *, long *);
 
 void
-__gnat_localtime_tzoff (const time_t *timer, long *off)
+__gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
 {
   *off = 0;
 }
 
 #else
 
-/* VMS does not need __gnat_locatime_tzoff */
+/* VMS does not need __gnat_localtime_tzoff */
 
 #if defined (VMS)
 
-/* Other targets except Lynx, VMS and Windows provide a standard locatime_r */
+/* Other targets except Lynx, VMS and Windows provide a standard localtime_r */
 
 #else
 
@@ -851,10 +774,10 @@ extern void (*Lock_Task) (void);
 extern void (*Unlock_Task) (void);
 
 extern void
-__gnat_localtime_tzoff (const time_t *, long *);
+__gnat_localtime_tzoff (const time_t *, const int *, long *);
 
 void
-__gnat_localtime_tzoff (const time_t *timer, long *off)
+__gnat_localtime_tzoff (const time_t *timer, const int *is_historic, long *off)
 {
   struct tm tp;
 
@@ -868,6 +791,8 @@ __gnat_localtime_tzoff (const time_t *timer, long *off)
 
   (*Unlock_Task) ();
 
+  /* Correct the offset if Daylight Saving Time is in effect */
+
   if (tp.tm_isdst > 0)
     *off = *off + 3600;
 }
@@ -902,9 +827,16 @@ __gnat_localtime_tzoff (const time_t *timer, long *off)
     tz_end = index (tz_start, ':');
     tz_end = '\0';
 
-    /* The Ada layer expects an offset in seconds */
+    /* The Ada layer expects an offset in seconds. Note that we must reverse
+       the sign of the result since west is positive and east is negative on
+       VxWorks targets. */
+
+    *off = -atol (tz_start) * 60;
 
-    *off = atol (tz_start) * 60;
+    /* Correct the offset if Daylight Saving Time is in effect */
+
+    if (tp.tm_isdst > 0)
+      *off = *off + 3600;
   }
 
   (*Unlock_Task) ();
@@ -941,7 +873,7 @@ __gnat_localtime_tzoff (const time_t *timer, long *off)
    the options assigned to the current task (parent), so offering some user
    level control over the options for a task hierarchy. It forces VX_FP_TASK
    because it is almost always required. On processors with the SPE
-   category, VX_SPE_TASK is needed to enable the SPE. */
+   category, VX_SPE_TASK should be used instead to enable the SPE. */
 extern int __gnat_get_task_options (void);
 
 int
@@ -952,10 +884,11 @@ __gnat_get_task_options (void)
   /* Get the options for the task creator */
   taskOptionsGet (taskIdSelf (), &options);
 
-  /* Force VX_FP_TASK because it is almost always required */
-  options |= VX_FP_TASK;
+  /* Force VX_FP_TASK or VX_SPE_TASK as needed */
 #if defined (__SPE__)
   options |= VX_SPE_TASK;
+#else
+  options |= VX_FP_TASK;
 #endif
 
   /* Mask those bits that are not under user control */
@@ -976,8 +909,10 @@ __gnat_is_file_not_found_error (int errno_val) {
       /* In the case of VxWorks, we also have to take into account various
        * filesystem-specific variants of this error.
        */
+#if ! defined (VTHREADS)
       case S_dosFsLib_FILE_NOT_FOUND:
-#if ! defined (__RTP__) && ! defined (VTHREADS)
+#endif
+#if ! defined (__RTP__) && (! defined (VTHREADS) || defined (__VXWORKSMILS__))
       case S_nfsLib_NFSERR_NOENT:
 #endif
 #endif