summaryrefslogtreecommitdiff
path: root/gcc/ada/sysdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/sysdep.c')
-rw-r--r--gcc/ada/sysdep.c605
1 files changed, 605 insertions, 0 deletions
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
new file mode 100644
index 00000000000..5473ebee42e
--- /dev/null
+++ b/gcc/ada/sysdep.c
@@ -0,0 +1,605 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S Y S D E P *
+ * *
+ * C Implementation File *
+ * *
+ * $Revision: 1.2 $
+ * *
+ * Copyright (C) 1992-2001 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- *
+ * ware Foundation; either version 2, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
+ * for more details. You should have received a copy of the GNU General *
+ * Public License distributed with GNAT; see file COPYING. If not, write *
+ * to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, *
+ * MA 02111-1307, USA. *
+ * *
+ * As a special exception, if you link this file with other files to *
+ * produce an executable, this file does not by itself cause the resulting *
+ * executable to be covered by the GNU General Public License. This except- *
+ * ion does not however invalidate any other reasons why the executable *
+ * file might be covered by the GNU Public License. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). *
+ * *
+ ****************************************************************************/
+
+/* This file contains system dependent symbols that are referenced in the
+ GNAT Run Time Library */
+
+#ifdef __vxworks
+#include "vxWorks.h"
+#endif
+#ifdef IN_RTS
+#define POSIX
+#include "tconfig.h"
+#include "tsystem.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "time.h"
+#else
+#include "config.h"
+#include "system.h"
+#endif
+
+#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
+
+ Notes:
+
+ (1) Opening a file with read mode fails if the file does not exist or
+ cannot be read.
+
+ (2) Opening a file with append mode causes all subsequent writes to the
+ file to be forced to the then current end-of-file, regardless of
+ intervening calls to the fseek function.
+
+ (3) When a file is opened with update mode, both input and output may be
+ performed on the associated stream. However, output may not be directly
+ followed by input without an intervening call to the fflush function or
+ to a file positioning function (fseek, fsetpos, or rewind), and input
+ may not be directly followed by output without an intervening call to a
+ file positioning function, unless the input operation encounters
+ end-of-file.
+
+ The other target dependent declarations here are for the two functions
+ __gnat_set_binary_mode and __gnat_set_text_mode:
+
+ void __gnat_set_binary_mode (int handle);
+ void __gnat_set_text_mode (int handle);
+
+ These functions have no effect in Unix (or similar systems where there is
+ no distinction between binary and text files), but in DOS (and similar
+ systems where text mode does CR/LF translation), these functions allow
+ the mode of the stream with the given handle (fileno can be used to get
+ the handle of a stream) to be changed dynamically. The returned result
+ is 0 if no error occurs and -1 if an error occurs.
+
+ Finally there is a boolean (character) variable
+
+ char __gnat_text_translation_required;
+
+ which is zero (false) in Unix mode, and one (true) in DOS mode, with a
+ true value indicating that text translation is required on text files
+ and that fopen supports the trailing t and b modifiers.
+
+*/
+
+#if defined(WINNT) || defined (MSDOS) || defined (__EMX__)
+const char *mode_read_text = "rt";
+const char *mode_write_text = "wt";
+const char *mode_append_text = "at";
+const char *mode_read_binary = "rb";
+const char *mode_write_binary = "wb";
+const char *mode_append_binary = "ab";
+const char *mode_read_text_plus = "r+t";
+const char *mode_write_text_plus = "w+t";
+const char *mode_append_text_plus = "a+t";
+const char *mode_read_binary_plus = "r+b";
+const char *mode_write_binary_plus = "w+b";
+const char *mode_append_binary_plus = "a+b";
+const char __gnat_text_translation_required = 1;
+
+void
+__gnat_set_binary_mode (handle)
+ int handle;
+{
+ _setmode (handle, O_BINARY);
+}
+
+void
+__gnat_set_text_mode (handle)
+ int handle;
+{
+ _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". */
+
+char *
+__gnat_ttyname (filedes)
+ int filedes;
+{
+ if (isatty (filedes))
+ return "console";
+ else
+ return NULL;
+}
+
+/* This function is needed to fix a bug under Win95/98. Under these plateforms
+ 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. */
+
+static void winflush_init PARAMS ((void));
+
+static void winflush_95 PARAMS ((void));
+
+static void winflush_nt PARAMS ((void));
+
+/* winflusfunction is set first to the winflushinit function which will check
+ the OS version 95/98 or NT/2000 */
+
+static void (*winflush_function) PARAMS ((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 ()
+{
+ 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 ()
+{
+ FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
+}
+
+static void winflush_nt ()
+{
+ /* Does nothing as there is no problem under NT. */
+}
+#endif
+
+#else
+
+const char *mode_read_text = "r";
+const char *mode_write_text = "w";
+const char *mode_append_text = "a";
+const char *mode_read_binary = "r";
+const char *mode_write_binary = "w";
+const char *mode_append_binary = "a";
+const char *mode_read_text_plus = "r+";
+const char *mode_write_text_plus = "w+";
+const char *mode_append_text_plus = "a+";
+const char *mode_read_binary_plus = "r+";
+const char *mode_write_binary_plus = "w+";
+const char *mode_append_binary_plus = "a+";
+const char __gnat_text_translation_required = 0;
+
+/* These functions do nothing in non-DOS systems. */
+
+void
+__gnat_set_binary_mode (stream)
+ FILE *stream ATTRIBUTE_UNUSED;
+{
+}
+
+void
+__gnat_set_text_mode (stream)
+ FILE *stream ATTRIBUTE_UNUSED;
+{
+}
+char *
+__gnat_ttyname (filedes)
+ int filedes;
+{
+#ifndef __vxworks
+ extern char *ttyname PARAMS ((int));
+
+ return ttyname (filedes);
+
+#else
+ return "";
+
+#endif
+}
+#endif
+
+#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+ || (defined (__osf__) && ! defined (__alpha_vxworks)) || defined (WINNT) \
+ || defined (__MACHTEN__)
+#include <termios.h>
+
+#elif defined (VMS)
+extern char *decc$ga_stdscr;
+static int initted = 0;
+#endif
+
+/* Implements the common processing for getc_immediate and
+ getc_immediate_nowait. */
+
+extern void getc_immediate PARAMS ((FILE *, int *, int *));
+extern void getc_immediate_nowait PARAMS ((FILE *, int *, int *, int *));
+extern void getc_immediate_common PARAMS ((FILE *, int *, int *,
+ int *, int));
+
+/* Called by Get_Immediate (Foo); */
+
+void
+getc_immediate (stream, ch, end_of_file)
+ FILE *stream;
+ int *ch;
+ int *end_of_file;
+{
+ int avail;
+
+ getc_immediate_common (stream, ch, end_of_file, &avail, 1);
+}
+
+/* Called by Get_Immediate (Foo, Available); */
+
+void
+getc_immediate_nowait (stream, ch, end_of_file, avail)
+ FILE *stream;
+ int *ch;
+ int *end_of_file;
+ int *avail;
+{
+ getc_immediate_common (stream, ch, end_of_file, avail, 0);
+}
+
+/* Called by getc_immediate () and getc_immediate_nowait () */
+
+void
+getc_immediate_common (stream, ch, end_of_file, avail, waiting)
+ FILE *stream;
+ int *ch;
+ int *end_of_file;
+ int *avail;
+ int waiting;
+{
+#if defined (linux) || defined (sun) || defined (sgi) || defined (__EMX__) \
+ || (defined (__osf__) && ! defined (__alpha_vxworks)) \
+ || defined (__CYGWIN32__) || defined (__MACHTEN__)
+ char c;
+ int nread;
+ int good_one = 0;
+ int eof_ch = 4; /* Ctrl-D */
+ int fd = fileno (stream);
+ struct termios otermios_rec, termios_rec;
+
+ if (isatty (fd))
+ {
+ tcgetattr (fd, &termios_rec);
+ memcpy (&otermios_rec, &termios_rec, sizeof (struct termios));
+ while (! good_one)
+ {
+ /* Set RAW mode */
+ termios_rec.c_lflag = termios_rec.c_lflag & ~ICANON;
+#if defined(sgi) || defined (sun) || defined (__EMX__) || defined (__osf__) \
+ || defined (linux) || defined (__MACHTEN__)
+ eof_ch = termios_rec.c_cc[VEOF];
+
+ /* 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)),
+ 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);
+
+ /* Read() is used here instead of fread(), because fread() doesn't
+ work on Solaris5 and Sunos4 in this situation. Maybe because we
+ are mixing calls that use file descriptors and streams. */
+
+ nread = read (fd, &c, 1);
+ if (nread > 0)
+ {
+ /* On Unix terminals, Ctrl-D (EOT) is an End of File. */
+ if (c == eof_ch)
+ {
+ *avail = 0;
+ *end_of_file = 1;
+ good_one = 1;
+ }
+
+ /* Everything else is ok */
+ else if (c != eof_ch)
+ {
+ *avail = 1;
+ *end_of_file = 0;
+ good_one = 1;
+ }
+ }
+
+ else if (! waiting)
+ {
+ *avail = 0;
+ *end_of_file = 0;
+ good_one = 1;
+ }
+ else
+ {
+ good_one = 0;
+ }
+ }
+
+ tcsetattr (fd, TCSANOW, &otermios_rec);
+ *ch = c;
+ }
+
+ else
+#elif defined (VMS)
+ int fd = fileno (stream);
+
+ if (isatty (fd))
+ {
+ if (initted == 0)
+ {
+ decc$bsd_initscr ();
+ initted = 1;
+ }
+ decc$bsd_cbreak ();
+ *ch = decc$bsd_wgetch (decc$ga_stdscr);
+
+ if (*ch == 4)
+ *end_of_file = 1;
+ else
+ *end_of_file = 0;
+
+ *avail = 1;
+ decc$bsd_nocbreak ();
+ }
+ else
+#elif defined (__MINGW32__)
+ int fd = fileno (stream);
+ int char_waiting;
+ int eot_ch = 4; /* Ctrl-D */
+
+ if (isatty (fd))
+ {
+ if (waiting)
+ {
+ *ch = getch();
+ (*winflush_function)();
+
+ if (*ch == eot_ch)
+ *end_of_file = 1;
+ else
+ *end_of_file = 0;
+
+ *avail = 1;
+ }
+ else /* ! waiting */
+ {
+ char_waiting = kbhit();
+
+ if (char_waiting == 1)
+ {
+ *avail = 1;
+ *ch = getch();
+ (*winflush_function)();
+
+ if (*ch == eot_ch)
+ *end_of_file = 1;
+ else
+ *end_of_file = 0;
+ }
+ else
+ {
+ *avail = 0;
+ *end_of_file = 0;
+ }
+ }
+ }
+ else
+#endif
+ {
+ /* If we're not on a terminal, then we don't need any fancy processing.
+ Also this is the only thing that's left if we're not on one of the
+ supported systems. */
+ *ch = fgetc (stream);
+ if (feof (stream))
+ {
+ *end_of_file = 1;
+ *avail = 0;
+ }
+ else
+ {
+ *end_of_file = 0;
+ *avail = 1;
+ }
+ }
+}
+
+/* The following definitions are provided in NT to support Windows based
+ Ada programs. */
+
+#ifdef WINNT
+#include <windows.h>
+
+/* Provide functions to echo the values passed to WinMain (windows bindings
+ will want to import these). We use the same names as the routines used
+ by AdaMagic for compatibility. */
+
+char *rts_get_hInstance (void) { return (GetModuleHandleA (0)); }
+char *rts_get_hPrevInstance (void) { return (0); }
+char *rts_get_lpCommandLine (void) { return (GetCommandLineA ()); }
+int rts_get_nShowCmd (void) { return (1); }
+
+#endif /* WINNT */
+#ifdef VMS
+
+/* This gets around a problem with using the old threads library on VMS 7.0. */
+
+#include <time.h>
+
+extern long get_gmtoff PARAMS ((void));
+
+long
+get_gmtoff ()
+{
+ time_t t;
+ struct tm *ts;
+
+ t = time ((time_t) 0);
+ ts = localtime (&t);
+ return ts->tm_gmtoff;
+}
+#endif
+
+/* Definition of __gnat_locatime_r used by a-calend.adb */
+
+#if defined (_AIX) || defined (__EMX__)
+#define Lock_Task system__soft_links__lock_task
+extern void (*Lock_Task) (void);
+
+#define Unlock_Task system__soft_links__unlock_task
+extern void (*Unlock_Task) (void);
+
+/* Provide reentrant version of localtime on Aix and OS/2. Note that AiX does
+ provide localtime_r, but in the library libc_r which doesn't get included
+ systematically, so we can't use it. */
+
+exrern void struct tm *__gnat_localtime_r PARAMS ((const time_t *,
+ struct tm *));
+
+struct tm *
+__gnat_localtime_r (timer, tp)
+ const time_t *timer;
+ struct tm *tp;
+{
+ struct tm *tmp;
+
+ (*Lock_Task) ();
+ tmp = localtime (timer);
+ memcpy (tp, tmp, sizeof (struct tm));
+ (*Unlock_Task) ();
+ return tp;
+}
+
+#elif defined (__Lynx__)
+
+/* LynxOS provides a non standard localtime_r */
+
+extern struct tm *__gnat_localtime_r PARAMS ((const time_t *, struct tm *));
+
+struct tm *
+__gnat_localtime_r (timer, tp)
+ const time_t *timer;
+ struct tm *tp;
+{
+ return localtime_r (tp, timer);
+}
+
+#elif defined (VMS) || defined (__MINGW32__)
+
+/* __gnat_localtime_r is not needed on NT and VMS */
+
+#else
+
+/* All other targets provide a standard localtime_r */
+
+extern struct tm *__gnat_localtime_r PARAMS ((const time_t *, struct tm *));
+
+struct tm *
+__gnat_localtime_r (timer, tp)
+ const time_t *timer;
+ struct tm *tp;
+{
+ return (struct tm *) localtime_r (timer, tp);
+}
+#endif