home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / a-adaint.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  11KB  |  443 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                         GNAT COMPILER COMPONENTS                         */
  4. /*                                                                          */
  5. /*                             A - A D A I N T                              */
  6. /*                                                                          */
  7. /*                            $Revision: 1.52 $                             */
  8. /*                                                                          */
  9. /*                          C Implementation File                           */
  10. /*                                                                          */
  11. /*        Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved        */
  12. /*                                                                          */
  13. /* The GNAT library is free software; you can redistribute it and/or modify */
  14. /* it under terms of the GNU Library General Public License as published by */
  15. /* the Free Software  Foundation; either version 2, or (at your option) any */
  16. /* later version.  The GNAT library is distributed in the hope that it will */
  17. /* be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty */
  18. /* of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU */
  19. /* Library  General  Public  License for  more  details.  You  should  have */
  20. /* received  a copy of the GNU  Library  General Public License  along with */
  21. /* the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free */
  22. /* Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        */
  23. /*                                                                          */
  24. /****************************************************************************/
  25.  
  26. /*  This file contains those routines named by Import pragmas in package    */
  27. /*  GNAT.OS_Lib. Many of the subprograms in OS_Lib import standard library  */
  28. /*  calls directly. This file contains all other routines.                  */
  29.  
  30. #include <sys/types.h>
  31. #include <sys/stat.h>
  32. #include <fcntl.h>
  33. #include <time.h>
  34. #include "config.h"  /* this may define MSDOS */
  35. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  36. #include <process.h>
  37. #include <string.h>
  38. #endif
  39. #include "a-adaint.h"
  40.  
  41. /* Define symbols O_BINARY and O_TEXT as harmless zeroes if they are not
  42.    defined in the current system. On DOS-like systems these flags control
  43.    whether the file is opened/created in text-translation mode (CR/LF in
  44.    external file mapped to LF in internal file), but in Unix-like systems,
  45.    no text translation is required, so these flags have no effect.
  46. */
  47.  
  48.  
  49. #if defined (__EMX__)
  50. #include <os2.h>
  51. #endif
  52.  
  53. #if defined (MSDOS)
  54. #include <dos.h>
  55. #endif
  56.  
  57. #ifndef O_BINARY
  58. #define O_BINARY 0
  59. #endif
  60.  
  61. #ifndef O_TEXT
  62. #define O_TEXT 0
  63. #endif
  64.  
  65. extern char *getenv ();
  66.  
  67. #if __amigaos__
  68. #define fork vfork    /* AmigaOS doesn't have a true fork() */
  69. #endif
  70.  
  71.  
  72. void
  73. to_gm_time (p_time, p_year, p_month, p_day, p_hours, p_mins, p_secs)
  74.      time_t *p_time;
  75.      int *p_year, *p_month, *p_day, *p_hours, *p_mins, *p_secs;
  76. {
  77.   struct tm *res = gmtime (p_time);
  78.  
  79.   *p_year = res->tm_year;
  80.   *p_month = res->tm_mon;
  81.   *p_day = res->tm_mday;
  82.   *p_hours = res->tm_hour;
  83.   *p_mins = res->tm_min;
  84.   *p_secs = res->tm_sec;
  85. }
  86. /* Return the maximum file name length.  */
  87.  
  88. int
  89. Get_Maximum_File_Name_Length ()
  90. {
  91. #ifdef MSDOS
  92.   return 8;
  93. #else
  94.   return -1;
  95. #endif
  96. }
  97.  
  98. /* Return the default switch character.  */
  99.  
  100. char
  101. Get_Switch_Character ()
  102. {
  103.   /* Under MSDOS, the switch character is not normally a hyphen, but this is
  104.      the convention DJGPP uses. Similarly under OS2, the switch character is
  105.      not normally a hypen, but this is the convention EMX uses.
  106.    */
  107.   return '-';
  108. }
  109.  
  110. /* Return nonzero if file names are case sensitive.  */
  111.  
  112. int
  113. Get_File_Names_Case_Sensitive ()
  114. {
  115. #if defined (__EMX__) || defined (MSDOS)
  116.   return 0;
  117. #else
  118.   return 1;
  119. #endif
  120. }
  121.  
  122. char
  123. Get_Default_Identifier_Character_Set ()
  124. {
  125. #if defined (__EMX__) || defined (MSDOS)
  126.   return 'p';
  127. #else
  128.   return '1';
  129. #endif
  130. }
  131.  
  132. #if defined(__EMX__) || defined (MSDOS)
  133. char dirsep_char = '\\';
  134. #else
  135. char dirsep_char = '/';
  136. #endif
  137.  
  138. #if defined(__EMX__) || defined (MSDOS) || defined (WINNT)
  139. char pathsep_char = ';';
  140. #else
  141. char pathsep_char = ':';
  142. #endif
  143.  
  144. /* Return the suffix for object files; the argument, str, is assumed to point
  145.    to an array of at least 4 characters.  */
  146.  
  147. void
  148. Get_Object_Suffix (str)
  149.      char *str;
  150. {
  151.   /* Under MSDOS, the suffix for object files is not normally .o, but this is
  152.      the convention DJGPP uses. Similarly under OS/2, the suffix for object
  153.      files is not normally .o, but this is the convention EMX uses. */
  154.   strcpy (str, "o");
  155. }
  156.  
  157. int
  158. open_read (path, fmode)
  159.      char *path;
  160.      int fmode;
  161. {
  162.   int fd;
  163.  
  164.   if (fmode)
  165.     fd = open (path, O_RDONLY | O_TEXT);
  166.   else
  167.     fd = open (path, O_RDONLY | O_BINARY);
  168.  
  169.   return fd < 0 ? -1 : fd;
  170. }
  171.  
  172.  
  173. #if defined (__EMX__)
  174. #define PERM (S_IREAD | S_IWRITE)
  175. #else
  176. #define PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
  177. #endif
  178.  
  179. int
  180. open_create (path, fmode)
  181.      char *path;
  182.      int  fmode;
  183. {
  184.   int fd;
  185.  
  186.   if (fmode)
  187.     fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, PERM);
  188.   else
  189.     fd = open (path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, PERM);
  190.  
  191.   return fd < 0 ? -1 : fd;
  192. }
  193.  
  194. /*  Open a new file.  Return error (-1) if the file already exists. */
  195.  
  196. int
  197. open_new (path, fmode)
  198.      char *path;
  199.      int fmode;
  200. {
  201.   int fd;
  202.   if (fmode)
  203.     fd =  open (path, O_WRONLY | O_CREAT | O_EXCL | O_TEXT,
  204.                       S_IWRITE | S_IREAD);
  205.   else
  206.     fd =  open (path, O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
  207.                       S_IWRITE | S_IREAD);
  208.  
  209.   return fd < 0 ? -1 : fd;
  210. }
  211.  
  212. /* Return the number of bytes in the specified file. */
  213.  
  214. long
  215. file_length (fd)
  216.      int fd;
  217. {
  218.   int ret;
  219.   struct stat statbuf;
  220.  
  221.   ret = fstat (fd, &statbuf);
  222.   if (ret || !S_ISREG (statbuf.st_mode))
  223.     return 0;
  224.  
  225.   return (statbuf.st_size);
  226. }
  227.  
  228. /* Return a GNAT time stamp given a file name.  */
  229.  
  230. time_t
  231. file_time_name (name)
  232.      char *name;
  233. {
  234.   struct stat statbuf;
  235.   char buf[13];
  236.  
  237. #if defined (__EMX__) || defined (MSDOS)
  238.   int fd = open (name, O_RDONLY | O_BINARY);
  239.   time_t ret = file_time_fd (fd);
  240.   close (fd);
  241.   return ret;
  242.  
  243. #else
  244.  
  245.   int ret = stat (name, &statbuf);
  246.   return statbuf.st_mtime;
  247. #endif
  248. }
  249.  
  250. /* Return a GNAT time stamp given a file descriptor.  */
  251.  
  252. time_t
  253. file_time_fd (fd)
  254.      int fd;
  255. {
  256.   /* The following workaround code is due to the fact that under EMX and DJGPP
  257.      fstat attempts to convert time values to GMT rather than keep the actual
  258.      OS timestamp of the file. By using the OS2/DOS functions directly the GNAT
  259.      timestamp are independent of this behavior, which is desired to facilitate
  260.      the distribution of GNAT compiled libraries. */
  261.  
  262. #if defined (__EMX__) || defined (MSDOS)
  263. #ifdef __EMX__
  264.  
  265.   FILESTATUS fs;
  266.   int ret = DosQueryFileInfo (fd, 1, (unsigned char *) &fs,
  267.                 sizeof (FILESTATUS));
  268.  
  269.   unsigned file_year  = fs.fdateLastWrite.year;
  270.   unsigned file_month = fs.fdateLastWrite.month;
  271.   unsigned file_day   = fs.fdateLastWrite.day;
  272.   unsigned file_hour  = fs.ftimeLastWrite.hours;
  273.   unsigned file_min   = fs.ftimeLastWrite.minutes;
  274.   unsigned file_tsec  = fs.ftimeLastWrite.twosecs;
  275.  
  276. #else
  277.   struct ftime fs;
  278.   int ret = getftime (fd, &fs);
  279.  
  280.   unsigned file_year  = fs.ft_year;
  281.   unsigned file_month = fs.ft_month;
  282.   unsigned file_day   = fs.ft_day;
  283.   unsigned file_hour  = fs.ft_hour;
  284.   unsigned file_min   = fs.ft_min;
  285.   unsigned file_tsec  = fs.ft_tsec;
  286. #endif
  287.  
  288.   /* Calculate the seconds since epoch from the time components. First count
  289.      the whole days passed.  The value for years returned by the DOS and OS2
  290.      functions count years from 1980, so to compensate for the UNIX epoch which
  291.      begins in 1970 start with 10 years worth of days and add days for each
  292.      four year period since then. */
  293.  
  294.   time_t tot_secs;
  295.   int cum_days [12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  296.   int days_passed = 3652 + (file_year / 4) * 1461;
  297.   int years_since_leap = file_year % 4;
  298.   if      (years_since_leap == 1) days_passed += 366;
  299.   else if (years_since_leap == 2) days_passed += 731;
  300.   else if (years_since_leap == 3) days_passed += 1096;
  301.   if (file_year > 20) days_passed -= 1;
  302.   days_passed += cum_days [file_month - 1];
  303.   if (years_since_leap == 0 && file_year != 20
  304.       && file_month > 2) days_passed++;
  305.   days_passed += file_day - 1;
  306.  
  307.   /* OK - have whole days.  Multiply -- then add in other parts. */
  308.   tot_secs  = days_passed               * 86400;
  309.   tot_secs += file_hour   * 3600;
  310.   tot_secs += file_min * 60;
  311.   tot_secs += file_tsec * 2;
  312.  
  313.   return tot_secs;
  314.  
  315. #else
  316.   struct stat statbuf;
  317.   char buf[13];
  318.   int ret = fstat (fd, &statbuf);
  319.   return statbuf.st_mtime;
  320. #endif
  321. }
  322.  
  323. void
  324. get_env_value_ptr (name, len, value)
  325.      char *name;
  326.      int *len;
  327.      char **value;
  328. {
  329.   *value = getenv (name);
  330.   if (!*value)
  331.     *len = 0;
  332.   else
  333.     *len = strlen (*value);
  334.  
  335.   return;
  336. }
  337.  
  338. int
  339. is_regular_file (name)
  340.      char *name;
  341. {
  342.   int ret;
  343.   struct stat statbuf;
  344.  
  345.   ret = stat (name, &statbuf);
  346.   return (!ret && S_ISREG (statbuf.st_mode));
  347. }
  348.  
  349. int
  350. is_directory (name)
  351.      char *name;
  352. {
  353.   int ret;
  354.   struct stat statbuf;
  355.  
  356.   ret = stat (name, &statbuf);
  357.   return (!ret && S_ISDIR (statbuf.st_mode));
  358. }
  359.  
  360. int
  361. portable_spawn (args)
  362.     char *args[];
  363. {
  364.   int status;
  365.   int finished;
  366.   int pid;
  367.  
  368. #if defined (__EMX__) || defined (MSDOS) || defined (WINNT)
  369.   if (spawnvp (P_WAIT, args [0], args) != 0)
  370.     return (4);
  371. #else
  372.   pid = fork ();
  373.   if (pid == -1)
  374.     return (4);
  375.   if (pid == 0) {
  376.     /* The child */
  377.     execv (args [0], args);
  378.     return (4);
  379.   }
  380.  
  381.   /* The parent */
  382.   finished = wait (&status);
  383.   if (finished != pid || status & 0xffff)
  384.     return 4;
  385. #endif
  386.   return 0;
  387. }
  388.  
  389. char *
  390. locate_exec (exec_name, path_val)
  391.      char *exec_name;
  392.      char *path_val;
  393. {
  394.   char buf [1000];
  395.   char *ptr;
  396.  
  397.   /* Handle absolute pathnames (DJGPP and EMX could have either '/' or '\') */
  398.   if ((exec_name [0] == '/' || exec_name [0] == dirsep_char)
  399. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  400.       || isalpha (exec_name [0]) && exec_name [1] == ':'
  401. #endif
  402.      ) {
  403.     strncpy (buf, exec_name, sizeof buf);
  404.     buf[sizeof buf - 1] = '\0';
  405. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  406.     ptr = strstr (buf, ".exe");
  407.     if (ptr == NULL || strlen (ptr) != 4)
  408.        strcat (buf, ".exe");
  409. #endif
  410.     if (is_regular_file (buf))
  411.       return xstrdup (buf);
  412.     else
  413.       return (char *)0;
  414.   }
  415.  
  416.   if (! path_val) return (char *) 0;
  417.  
  418.   for (;;) {
  419.     for (; *path_val == pathsep_char ; path_val++)
  420.       ;
  421.     if (! *path_val) return (char *) 0;
  422.  
  423.     for (ptr = buf; *path_val && *path_val != pathsep_char; )
  424.       *ptr++ = *path_val++;
  425.  
  426.     ptr--;
  427.     if (*ptr != '/' && *ptr != dirsep_char) /* DJGPP could have either */
  428.       *++ptr = dirsep_char;
  429.  
  430.     strcpy (++ptr, exec_name);
  431.  
  432. #if defined(__EMX__) || defined(MSDOS) || defined(WINNT)
  433.     ptr = strstr (buf, ".exe");
  434.     if (ptr == NULL || strlen (ptr) != 4)
  435.        strcat (buf, ".exe");
  436. #endif
  437.     if (is_regular_file (buf))
  438.       return xstrdup (buf);
  439.   }
  440.  
  441.   return (char *) 0;
  442. }
  443.