home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************/
- /* */
- /* GNAT COMPILER COMPONENTS */
- /* */
- /* A - A D A I N T */
- /* */
- /* $Revision: 1.60 $ */
- /* */
- /* C Implementation File */
- /* */
- /* Copyright (C) 1992,1993,1994,1995,1996 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 those routines named by Import pragmas in package */
- /* GNAT.OS_Lib. Many of the subprograms in OS_Lib import standard library */
- /* calls directly. This file contains all other routines. */
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <time.h>
- #include "config.h" /* this may define MSDOS */
- #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
- #include <process.h>
- #include <string.h>
- #endif
- #include "a-adaint.h"
-
- /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
- defined in the current system. On DOS-like systems these flags control
- whether the file is opened/created in text-translation mode (CR/LF in
- external file mapped to LF in internal file), but in Unix-like systems,
- no text translation is required, so these flags have no effect.
- */
-
-
- #if defined (__EMX__)
- #include <os2.h>
- #endif
-
- #if defined (MSDOS)
- #include <dos.h>
- #endif
-
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
-
- #ifndef O_TEXT
- #define O_TEXT 0
- #endif
-
- extern char *getenv ();
-
-
- void
- to_gm_time (p_time, p_year, p_month, p_day, p_hours, p_mins, p_secs)
- time_t *p_time;
- int *p_year, *p_month, *p_day, *p_hours, *p_mins, *p_secs;
- {
- struct tm *res = gmtime (p_time);
-
- *p_year = res->tm_year;
- *p_month = res->tm_mon;
- *p_day = res->tm_mday;
- *p_hours = res->tm_hour;
- *p_mins = res->tm_min;
- *p_secs = res->tm_sec;
- }
- /* Return the maximum file name length. */
-
- int
- Get_Maximum_File_Name_Length ()
- {
- #ifdef MSDOS
- return 8;
- #else
- return -1;
- #endif
- }
-
- /* Return the default switch character. */
-
- char
- Get_Switch_Character ()
- {
- /* Under MSDOS, the switch character is not normally a hyphen, but this is
- the convention DJGPP uses. Similarly under OS2, the switch character is
- not normally a hypen, but this is the convention EMX uses.
- */
- return '-';
- }
-
- /* Return nonzero if file names are case sensitive. */
-
- int
- Get_File_Names_Case_Sensitive ()
- {
- #if defined (__EMX__) || defined (MSDOS)
- return 0;
- #else
- return 1;
- #endif
- }
-
- char
- Get_Default_Identifier_Character_Set ()
- {
- #if defined (__EMX__) || defined (MSDOS)
- return 'p';
- #else
- return '1';
- #endif
- }
-
- #if defined(__EMX__) || defined (MSDOS)
- char dirsep_char = '\\';
- #else
- char dirsep_char = '/';
- #endif
-
- #if defined(__EMX__) || defined (MSDOS) || defined (WINNT)
- char pathsep_char = ';';
- #else
- char pathsep_char = ':';
- #endif
-
- /* Return the suffix for object files; the argument, str, is assumed to point
- to an array of at least 4 characters. */
-
- void
- Get_Object_Suffix (str)
- char *str;
- {
- /* Under MSDOS, the suffix for object files is not normally .o, but this is
- the convention DJGPP uses. Similarly under OS/2, the suffix for object
- files is not normally .o, but this is the convention EMX uses. */
- strcpy (str, "o");
- }
-
- /* Return the suffix for executable files; the argument, str, is assumed to
- point to an array of at least 4 characters. */
-
- void
- Get_Executable_Suffix (str)
- char *str;
- {
- #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
- strcpy (str, ".exe");
- #else
- strcpy (str, "");
- #endif
- }
-
- int
- open_read (path, fmode)
- char *path;
- int fmode;
- {
- int fd;
-
- if (fmode)
- fd = open (path, O_RDONLY | O_TEXT);
- else
- fd = open (path, O_RDONLY | O_BINARY);
-
- return fd < 0 ? -1 : fd;
- }
-
-
- #if defined (__EMX__)
- #define PERM (S_IREAD | S_IWRITE)
- #else
- #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
- #endif
-
- int
- open_rw (path, fmode)
- char *path;
- int fmode;
- {
- int fd;
-
- if (fmode)
- fd = open (path, O_RDWR | O_TEXT, PERM);
- else
- fd = open (path, O_RDWR | O_BINARY, PERM);
-
- return fd < 0 ? -1 : fd;
- }
-
- int
- open_create (path, fmode)
- char *path;
- int fmode;
- {
- int fd;
-
- if (fmode)
- fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
- else
- fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, PERM);
-
- return fd < 0 ? -1 : fd;
- }
-
- /* Open a new file. Return error (-1) if the file already exists. */
-
- int
- open_new (path, fmode)
- char *path;
- int fmode;
- {
- int fd;
- if (fmode)
- fd = open (path, O_WRONLY | O_CREAT | O_EXCL | O_TEXT, PERM);
- else
- fd = open (path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, PERM);
-
- return fd < 0 ? -1 : fd;
- }
-
- /* Return the number of bytes in the specified file. */
-
- long
- file_length (fd)
- int fd;
- {
- int ret;
- struct stat statbuf;
-
- ret = fstat (fd, &statbuf);
- if (ret || !S_ISREG (statbuf.st_mode))
- return 0;
-
- return (statbuf.st_size);
- }
-
- /* Return a GNAT time stamp given a file name. */
-
- time_t
- file_time_name (name)
- char *name;
- {
- struct stat statbuf;
-
- #if defined (__EMX__) || defined (MSDOS)
- int fd = open (name, O_RDONLY | O_BINARY);
- time_t ret = file_time_fd (fd);
- close (fd);
- return ret;
-
- #else
-
- int ret = stat (name, &statbuf);
- return statbuf.st_mtime;
- #endif
- }
-
- /* Return a GNAT time stamp given a file descriptor. */
-
- time_t
- file_time_fd (fd)
- int fd;
- {
- /* The following workaround code is due to the fact that under EMX and DJGPP
- fstat attempts to convert time values to GMT rather than keep the actual
- OS timestamp of the file. By using the OS2/DOS functions directly the GNAT
- timestamp are independent of this behavior, which is desired to facilitate
- the distribution of GNAT compiled libraries. */
-
- #if defined (__EMX__) || defined (MSDOS)
- #ifdef __EMX__
-
- FILESTATUS fs;
- int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
- sizeof (FILESTATUS));
-
- unsigned file_year = fs.fdateLastWrite.year;
- unsigned file_month = fs.fdateLastWrite.month;
- unsigned file_day = fs.fdateLastWrite.day;
- unsigned file_hour = fs.ftimeLastWrite.hours;
- unsigned file_min = fs.ftimeLastWrite.minutes;
- unsigned file_tsec = fs.ftimeLastWrite.twosecs;
-
- #else
- struct ftime fs;
- int ret = getftime (fd, &fs);
-
- unsigned file_year = fs.ft_year;
- unsigned file_month = fs.ft_month;
- unsigned file_day = fs.ft_day;
- unsigned file_hour = fs.ft_hour;
- unsigned file_min = fs.ft_min;
- unsigned file_tsec = fs.ft_tsec;
- #endif
-
- /* Calculate the seconds since epoch from the time components. First count
- the whole days passed. The value for years returned by the DOS and OS2
- functions count years from 1980, so to compensate for the UNIX epoch which
- begins in 1970 start with 10 years worth of days and add days for each
- four year period since then. */
-
- time_t tot_secs;
- int cum_days [12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
- int days_passed = 3652 + (file_year / 4) * 1461;
- int years_since_leap = file_year % 4;
- if (years_since_leap == 1) days_passed += 366;
- else if (years_since_leap == 2) days_passed += 731;
- else if (years_since_leap == 3) days_passed += 1096;
- if (file_year > 20) days_passed -= 1;
- days_passed += cum_days [file_month - 1];
- if (years_since_leap == 0 && file_year != 20
- && file_month > 2) days_passed++;
- days_passed += file_day - 1;
-
- /* OK - have whole days. Multiply -- then add in other parts. */
- tot_secs = days_passed * 86400;
- tot_secs += file_hour * 3600;
- tot_secs += file_min * 60;
- tot_secs += file_tsec * 2;
-
- return tot_secs;
-
- #else
- struct stat statbuf;
- int ret = fstat (fd, &statbuf);
- return statbuf.st_mtime;
- #endif
- }
-
- void
- get_env_value_ptr (name, len, value)
- char *name;
- int *len;
- char **value;
- {
- *value = getenv (name);
- if (!*value)
- *len = 0;
- else
- *len = strlen (*value);
-
- return;
- }
-
- int
- is_regular_file (name)
- char *name;
- {
- int ret;
- struct stat statbuf;
-
- ret = stat (name, &statbuf);
- return (!ret && S_ISREG (statbuf.st_mode));
- }
-
- int
- is_directory (name)
- char *name;
- {
- int ret;
- struct stat statbuf;
-
- ret = stat (name, &statbuf);
- return (!ret && S_ISDIR (statbuf.st_mode));
- }
-
- int
- portable_spawn (args)
- char *args[];
- {
- int status;
- int finished;
- int pid;
-
- #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
- if (spawnvp (P_WAIT, args [0], args) != 0)
- return (4);
- #else
- pid = fork ();
- if (pid == -1)
- return (4);
- if (pid == 0) {
- /* The child */
- execv (args [0], args);
- return (4);
- }
-
- /* The parent */
- finished = wait (&status);
- if (finished != pid || status & 0xffff)
- return 4;
- #endif
- return 0;
- }
-
- int
- portable_no_block_spawn (args)
- char *args[];
- {
- int pid = 0;
-
- #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
- /* ??? For PC machines I (Franco) don't know the system calls to
- implement this routine. So I'll fake it as follows. This routine
- will behave exactly like the blocking portable_spawn and will
- systematically return a pid of 0 unless the spawned task did not
- complete successfully, in which case we return a pid of -1. To
- synchronize with this the portable_wait below systematically
- returns a pid of 0 and reports that the subprocess terminated
- successfully. */
-
- if (spawnvp (P_WAIT, args [0], args) != 0)
- return (-1);
- #else
- pid = fork ();
-
- if (pid == 0) {
- /* The child */
- execv (args [0], args);
- return (-1);
- }
- #endif
-
- return pid;
- }
-
- int
- portable_wait (process_status)
- int *process_status;
- {
- int status = 0;
- int pid = 0;
-
- #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
- /* ??? See corresponding comment in portable_no_block_spawn. */
-
- #else
- pid = wait (&status);
- status = status & 0xffff;
- #endif
-
- *process_status = status;
- return pid;
- }
-
- char *
- locate_exec (exec_name, path_val)
- char *exec_name;
- char *path_val;
- {
- char *ptr, *ptr1;
- int len;
-
- /* Handle absolute pathnames (DJGPP and EMX could have either '/' or '\') */
- for (ptr = exec_name; *ptr && *ptr != '/' && *ptr != dirsep_char; ptr++);
-
- if (*ptr
- #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
- || isalpha (exec_name [0]) && exec_name [1] == ':'
- #endif
- ) {
- /* leave room for possible .exe extension */
- char exec_path[strlen (exec_name) + 5];
-
- strcpy (exec_path, exec_name);
-
- #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
- /* If .exe or .bat extension not specified, make it .exe */
-
- ptr = strstr (exec_path, ".exe");
- ptr1 = strstr (exec_path, ".bat");
- if ((ptr == NULL || strlen (ptr) != 4)
- && (ptr1 == NULL || strlen (ptr1) != 4))
- strcat (exec_path, ".exe");
- #endif
- if (is_regular_file (exec_path))
- return xstrdup(exec_path);
-
- return (char *)0;
- }
-
- if (! path_val) return (char *) 0;
-
- {
- /* The result has to be smaller than path_val + exec_name + .exe */
- char exec_path[strlen (path_val) + strlen (exec_name) + 5];
-
- for (;;) {
- for (; *path_val == pathsep_char ; path_val++)
- ;
- if (! *path_val) return (char *) 0;
-
- for (ptr = exec_path; *path_val && *path_val != pathsep_char; )
- *ptr++ = *path_val++;
-
- ptr--;
- if (*ptr != '/' && *ptr != dirsep_char) /* DJGPP could have either */
- *++ptr = dirsep_char;
-
- strcpy (++ptr, exec_name);
-
- #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
- /* If .exe or .bat extension not specified, make it .exe */
-
- ptr = strstr (exec_path, ".exe");
- ptr1 = strstr (exec_path, ".bat");
- if ((ptr == NULL || strlen (ptr) != 4)
- && (ptr1 == NULL || strlen (ptr1) != 4))
- strcat (exec_path, ".exe");
- #endif
- if (is_regular_file (exec_path))
- return xstrdup(exec_path);
- }
- }
- return (char *) 0;
- }
-