720 lines
20 KiB
C
720 lines
20 KiB
C
/****************************************************************************
|
||
* *
|
||
* GNAT COMPILER COMPONENTS *
|
||
* *
|
||
* S Y S D E P *
|
||
* *
|
||
* C Implementation File *
|
||
* *
|
||
* Copyright (C) 1992-2003 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. *
|
||
* Extensive contributions were provided by Ada Core Technologies Inc. *
|
||
* *
|
||
****************************************************************************/
|
||
|
||
/* This file contains system dependent symbols that are referenced in the
|
||
GNAT Run Time Library */
|
||
|
||
#ifdef __vxworks
|
||
#include "ioLib.h"
|
||
#include "selectLib.h"
|
||
#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>
|
||
#ifdef VMS
|
||
#include <unixio.h>
|
||
#endif
|
||
#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__)
|
||
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";
|
||
const char __gnat_text_translation_required = 1;
|
||
|
||
void
|
||
__gnat_set_binary_mode (int handle)
|
||
{
|
||
_setmode (handle, O_BINARY);
|
||
}
|
||
|
||
void
|
||
__gnat_set_text_mode (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 (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 (void);
|
||
|
||
static void winflush_95 (void);
|
||
|
||
static void winflush_nt (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. */
|
||
}
|
||
#endif
|
||
|
||
#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. */
|
||
|
||
void
|
||
__gnat_set_binary_mode (int handle ATTRIBUTE_UNUSED)
|
||
{
|
||
}
|
||
|
||
void
|
||
__gnat_set_text_mode (int handle ATTRIBUTE_UNUSED)
|
||
{
|
||
}
|
||
char *
|
||
__gnat_ttyname (int filedes)
|
||
{
|
||
#ifndef __vxworks
|
||
extern char *ttyname (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__) || defined (hpux) || defined (_AIX) \
|
||
|| (defined (__svr4__) && defined (i386)) || defined (__Lynx__) \
|
||
|| defined (__CYGWIN__) || defined (__FreeBSD__)
|
||
|
||
#ifdef __MINGW32__
|
||
#if OLD_MINGW
|
||
#include <termios.h>
|
||
#else
|
||
#include <conio.h> /* for getch(), kbhit() */
|
||
#endif
|
||
#else
|
||
#include <termios.h>
|
||
#endif
|
||
|
||
#else
|
||
#if defined (VMS)
|
||
extern char *decc$ga_stdscr;
|
||
static int initted = 0;
|
||
#endif
|
||
#endif
|
||
|
||
/* Implements the common processing for getc_immediate and
|
||
getc_immediate_nowait. */
|
||
|
||
extern void getc_immediate (FILE *, int *, int *);
|
||
extern void getc_immediate_nowait (FILE *, int *, int *, int *);
|
||
extern void getc_immediate_common (FILE *, int *, int *, int *, int);
|
||
|
||
/* Called by Get_Immediate (Foo); */
|
||
|
||
void
|
||
getc_immediate (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 (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 (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__) || defined (hpux) \
|
||
|| defined (_AIX) || (defined (__svr4__) && defined (i386)) \
|
||
|| defined (__Lynx__) || defined (__FreeBSD__)
|
||
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));
|
||
|
||
/* 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__) \
|
||
|| defined (__osf__) || defined (__MACHTEN__) || defined (hpux) \
|
||
|| defined (_AIX) || (defined (__svr4__) && defined (i386)) \
|
||
|| defined (__Lynx__) || defined (__FreeBSD__)
|
||
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);
|
||
|
||
while (! good_one)
|
||
{
|
||
/* 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
|
||
#elif defined (__vxworks)
|
||
/* Bit masks of file descriptors to read from. */
|
||
struct fd_set readFds;
|
||
/* Timeout before select returns if nothing can be read. */
|
||
struct timeval timeOut;
|
||
char c;
|
||
int fd = fileno (stream);
|
||
int nread;
|
||
int option;
|
||
int readable;
|
||
int status;
|
||
int width;
|
||
|
||
if (isatty (fd))
|
||
{
|
||
/* If we do not want to wait, we have to set up fd in RAW mode. This
|
||
should be done outside this function as setting fd in RAW mode under
|
||
vxWorks flushes the buffer of fd. If the RAW mode was set here, the
|
||
buffer would be empty and we would always return that no character
|
||
is available */
|
||
if (! waiting)
|
||
{
|
||
/* Initialization of timeOut for its use with select. */
|
||
timeOut.tv_sec = 0;
|
||
timeOut.tv_usec = 0;
|
||
|
||
/* Initialization of readFds for its use with select;
|
||
FD is the only file descriptor to be monitored */
|
||
FD_ZERO (&readFds);
|
||
FD_SET (fd, &readFds);
|
||
width = 2;
|
||
|
||
/* We do all this processing to emulate a non blocking read. */
|
||
readable = select (width, &readFds, NULL, NULL, &timeOut);
|
||
if (readable == ERROR)
|
||
*avail = -1, *end_of_file = -1;
|
||
/* No character available in input. */
|
||
else if (readable == 0)
|
||
*avail = 0, *end_of_file = 0;
|
||
else
|
||
{
|
||
nread = read (fd, &c, 1);
|
||
if (nread > 0)
|
||
*avail = 1, *end_of_file = 0;
|
||
/* End Of File. */
|
||
else if (nread == 0)
|
||
*avail = 0, *end_of_file = 1;
|
||
/* Error. */
|
||
else
|
||
*avail = -1, *end_of_file = -1;
|
||
}
|
||
}
|
||
|
||
/* We have to wait until we get a character */
|
||
else
|
||
{
|
||
*avail = -1;
|
||
*end_of_file = -1;
|
||
|
||
/* Save the current mode of FD. */
|
||
option = ioctl (fd, FIOGETOPTIONS, 0);
|
||
|
||
/* Set FD in RAW mode. */
|
||
status = ioctl (fd, FIOSETOPTIONS, OPT_RAW);
|
||
if (status != -1)
|
||
{
|
||
nread = read (fd, &c, 1);
|
||
if (nread > 0)
|
||
*avail = 1, *end_of_file = 0;
|
||
/* End of file. */
|
||
else if (nread == 0)
|
||
*avail = 0, *end_of_file = 1;
|
||
/* Else there is an ERROR. */
|
||
}
|
||
|
||
/* Revert FD to its previous mode. */
|
||
status = ioctl (fd, FIOSETOPTIONS, option);
|
||
}
|
||
|
||
*ch = c;
|
||
}
|
||
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; which means that for non supported systems,
|
||
get_immediate may wait for a carriage return on terminals. */
|
||
*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);
|
||
char *rts_get_hPrevInstance (void);
|
||
char *rts_get_lpCommandLine (void);
|
||
int rts_get_nShowCmd (void);
|
||
|
||
char *
|
||
rts_get_hInstance (void)
|
||
{
|
||
return (char *)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 (void);
|
||
|
||
long
|
||
get_gmtoff (void)
|
||
{
|
||
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. */
|
||
|
||
extern struct tm *__gnat_localtime_r (const time_t *, struct tm *);
|
||
|
||
struct tm *
|
||
__gnat_localtime_r (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;
|
||
}
|
||
|
||
#else
|
||
#if defined (__Lynx__) && defined (___THREADS_POSIX4ad4__)
|
||
|
||
/* As of LynxOS 3.1.0a patch level 040, LynuxWorks changes the
|
||
prototype to the C library function localtime_r from the POSIX.4
|
||
Draft 9 to the POSIX 1.c version. Before this change the following
|
||
spec is required. Only use when ___THREADS_POSIX4ad4__ is defined,
|
||
the Lynx convention when building against the legacy API. */
|
||
|
||
extern struct tm *__gnat_localtime_r (const time_t *, struct tm *);
|
||
|
||
struct tm *
|
||
__gnat_localtime_r (const time_t *timer, struct tm *tp)
|
||
{
|
||
localtime_r (tp, timer);
|
||
return NULL;
|
||
}
|
||
|
||
#else
|
||
#if 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 (const time_t *, struct tm *);
|
||
|
||
struct tm *
|
||
__gnat_localtime_r (const time_t *timer, struct tm *tp)
|
||
{
|
||
return (struct tm *) localtime_r (timer, tp);
|
||
}
|
||
#endif
|
||
#endif
|
||
#endif
|