OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / fixinc / fixincl.c
index 23e738a..8deafa8 100644 (file)
@@ -3,7 +3,7 @@
    files which are fixed to work correctly with ANSI C and placed in a
    directory that GNU C will search.
 
-   Copyright (C) 1997-1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA.  */
 
 #include "fixlib.h"
 
-#if HAVE_MMAP
+#if HAVE_MMAP_FILE
 #include <sys/mman.h>
 #define  BAD_ADDR ((void*)-1)
 #endif
@@ -33,75 +33,26 @@ Boston, MA 02111-1307, USA.  */
 
 #include "server.h"
 
-/*  Quality Assurance Marker  :-)
-
-    Any file that contains this string is presumed to have
-    been carefully constructed and will not be fixed  */
-
 /*  The contents of this string are not very important.  It is mostly
     just used as part of the "I am alive and working" test.  */
 
 static const char program_id[] = "fixincl version 1.1";
 
-/*  Test Descriptor
-
-    Each fix may have associated tests that determine
-    whether the fix needs to be applied or not.
-    Each test has a type (from the te_test_type enumeration);
-    associated test text; and, if the test is TT_EGREP or
-    the negated form TT_NEGREP, a pointer to the compiled
-    version of the text string.
-
-    */
-typedef enum
-{
-  TT_TEST, TT_EGREP, TT_NEGREP, TT_FUNCTION
-} te_test_type;
-
-typedef struct test_desc tTestDesc;
-
-struct test_desc
-{
-  te_test_type type;
-  const char *pz_test_text;
-  regex_t *p_test_regex;
-};
-
-typedef struct patch_desc tPatchDesc;
+/*  This format will be used at the start of every generated file */
 
-/*  Fix Descriptor
+static const char z_std_preamble[] =
+"/*  DO NOT EDIT THIS FILE.\n\n\
+    It has been auto-edited by fixincludes from:\n\n\
+\t\"%s/%s\"\n\n\
+    This had to be done to correct non-standard usages in the\n\
+    original, manufacturer supplied header file.  */\n\n";
 
-    Everything you ever wanted to know about how to apply
-    a particular fix (which files, how to qualify them,
-    how to actually make the fix, etc...)
+/*  Working environment strings.  Essentially, invocation 'options'.  */
 
-    NB:  the FD_ defines are BIT FLAGS
+#define _ENV_(v,m,n,t)   tCC* v = NULL;
+ENV_TABLE
+#undef _ENV_
 
-    */
-#define FD_MACH_ONLY      0x0000
-#define FD_MACH_IFNOT     0x0001
-#define FD_SHELL_SCRIPT   0x0002
-#define FD_SUBROUTINE     0x0004
-#define FD_REPLACEMENT    0x0008
-#define FD_SKIP_TEST      0x8000
-
-typedef struct fix_desc tFixDesc;
-struct fix_desc
-{
-  const char*   fix_name;       /* Name of the fix */
-  const char*   file_list;      /* List of files it applies to */
-  const char**  papz_machs;     /* List of machine/os-es it applies to */
-  regex_t*      unused;
-  int           test_ct;
-  int           fd_flags;
-  tTestDesc*    p_test_desc;
-  const char**  patch_args;
-};
-
-/*  Working environment strings.  Essentially, invocation 'options'.  */
-char *pz_dest_dir = NULL;
-char *pz_src_dir = NULL;
-char *pz_machine = NULL;
 int find_base_len = 0;
 
 typedef enum {
@@ -127,6 +78,7 @@ t_bool curr_data_mapped;
 int    data_map_fd;
 size_t data_map_size;
 size_t ttl_data_size = 0;
+
 #ifdef DO_STATS
 int process_ct = 0;
 int apply_ct = 0;
@@ -134,14 +86,6 @@ int fixed_ct = 0;
 int altered_ct = 0;
 #endif /* DO_STATS */
 
-#ifdef HAVE_MMAP
-#define UNLOAD_DATA() do { if (curr_data_mapped) { \
-  munmap ((void*)pz_curr_data, data_map_size); close (data_map_fd); } \
-  else free ((void*)pz_curr_data); } while(0)
-#else
-#define UNLOAD_DATA() free ((void*)pz_curr_data)
-#endif
-
 const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
 tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
 regex_t incl_quote_re;
@@ -150,14 +94,12 @@ void do_version ();
 char *load_file  _P_((const char *));
 void process  _P_((char *, const char *));
 void run_compiles ();
-void initialize ();
+void initialize _P_((int argc,char** argv));
 void process ();
 
 /*  External Source Code */
 
 #include "fixincl.x"
-#include "fixtests.c"
-#include "fixfixes.c"
 
 /* * * * * * * * * * * * * * * * * * *
  *
@@ -170,28 +112,7 @@ main (argc, argv)
 {
   char *file_name_buf;
 
-  switch (argc)
-    {
-    case 1:
-      break;
-
-    case 2:
-      if (strcmp (argv[1], "-v") == 0)
-        do_version ();
-      if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
-        {
-          fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
-                   errno, strerror (errno), argv[1] );
-          exit (EXIT_FAILURE);
-        }
-      break;
-
-    default:
-      fputs ("fixincl ERROR:  too many command line arguments\n", stderr);
-      exit (EXIT_FAILURE);
-    }
-
-  initialize ();
+  initialize ( argc, argv );
 
   have_tty = isatty (fileno (stderr));
 
@@ -242,33 +163,7 @@ main (argc, argv)
         continue;
       *pz_end = NUL;
 
-#ifdef NO_BOGOSITY
       process ();
-#else
-      /*  Prevent duplicate output by child process  */
-
-      fflush (stdout);
-      fflush (stderr);
-
-      {
-        void wait_for_pid _P_(( pid_t ));
-        pid_t child = fork ();
-        if (child == NULLPROCESS)
-          {
-            process ();
-            return EXIT_SUCCESS;
-          }
-
-        if (child == NOPROCESS)
-          {
-            fprintf (stderr, "Error %d (%s) forking in main\n",
-                     errno, strerror (errno));
-            exit (EXIT_FAILURE);
-          }
-
-        wait_for_pid( child );
-      }
-#endif
     } /*  for (;;) */
 
 #ifdef DO_STATS
@@ -295,103 +190,97 @@ do_version ()
 
   /* The 'version' option is really used to test that:
      1.  The program loads correctly (no missing libraries)
-     2.  we can correctly run our server shell process
-     3.  that we can compile all the regular expressions.
+     2.  that we can compile all the regular expressions.
+     3.  we can correctly run our server shell process
   */
   run_compiles ();
   sprintf (zBuf, zFmt, program_id);
-  fputs (zBuf + 5, stdout);
+  puts (zBuf + 5);
   exit (strcmp (run_shell (zBuf), program_id));
 }
 
 /* * * * * * * * * * * * */
 
 void
-initialize ()
+initialize ( argc, argv )
+  int argc;
+  char** argv;
 {
   static const char var_not_found[] =
-    "fixincl ERROR:  %s environment variable not defined\n\
-\tTARGET_MACHINE, DESTDIR, SRCDIR and FIND_BASE are required\n";
+    "fixincl ERROR:  %s environment variable not defined\n"
+#ifdef __STDC__
+    "each of these must be defined:\n"
+#define _ENV_(v,m,n,t) "\t" n "  - " t "\n"
+ENV_TABLE
+#undef _ENV_
+#endif
+    ;
 
-  {
-    static const char var[] = "TARGET_MACHINE";
-    pz_machine = getenv (var);
-    if (pz_machine == (char *) NULL)
-      {
-        fprintf (stderr, var_not_found, var);
-        exit (EXIT_FAILURE);
-      }
-  }
+  xmalloc_set_program_name (argv[0]);
 
-  {
-    static const char var[] = "DESTDIR";
-    pz_dest_dir = getenv (var);
-    if (pz_dest_dir == (char *) NULL)
-      {
-        fprintf (stderr, var_not_found, var);
-        exit (EXIT_FAILURE);
-      }
-  }
+  switch (argc)
+    {
+    case 1:
+      break;
 
-  {
-    static const char var[] = "SRCDIR";
-    pz_src_dir = getenv (var);
-    if (pz_src_dir == (char *) NULL)
-      {
-        fprintf (stderr, var_not_found, var);
-        exit (EXIT_FAILURE);
-      }
-  }
+    case 2:
+      if (strcmp (argv[1], "-v") == 0)
+        do_version ();
+      if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
+        {
+          fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
+                   errno, xstrerror (errno), argv[1] );
+          exit (EXIT_FAILURE);
+        }
+      break;
 
-  {
-    static const char var[] = "VERBOSE";
-    char* pz = getenv (var);
-    if (pz != (char *) NULL)
-      {
-        if (isdigit( *pz ))
-          verbose_level = (te_verbose)atoi( pz );
-        else
-          switch (*pz) {
-          case 's':
-          case 'S':
-            verbose_level = VERB_SILENT;     break;
-
-          case 'f':
-          case 'F':
-            verbose_level = VERB_FIXES;      break;
-
-          case 'a':
-          case 'A':
-            verbose_level = VERB_APPLIES;    break;
-
-          case 'p':
-          case 'P':
-            verbose_level = VERB_PROGRESS;   break;
-
-          case 't':
-          case 'T':
-            verbose_level = VERB_TESTS;      break;
-
-          case 'e':
-          case 'E':
-            verbose_level = VERB_EVERYTHING; break;
-          }
-      }
-  }
+    default:
+      fputs ("fixincl ERROR:  too many command line arguments\n", stderr);
+      exit (EXIT_FAILURE);
+    }
 
-  {
-    static const char var[] = "FIND_BASE";
-    char *pz = getenv (var);
-    if (pz == (char *) NULL)
-      {
-        fprintf (stderr, var_not_found, var);
-        exit (EXIT_FAILURE);
-      }
-    while ((pz[0] == '.') && (pz[1] == '/'))
-      pz += 2;
-    if ((pz[0] != '.') || (pz[1] != NUL))
-      find_base_len = strlen( pz );
-  }
+#define _ENV_(v,m,n,t)   { tSCC var[] = n;  \
+  v = getenv (var); if (m && (v == NULL)) { \
+  fprintf (stderr, var_not_found, var);     \
+  exit (EXIT_FAILURE); } }
+
+ENV_TABLE
+
+#undef _ENV_
+
+  if (isdigit( *pz_verbose ))
+    verbose_level = (te_verbose)atoi( pz_verbose );
+  else
+    switch (*pz_verbose) {
+    case 's':
+    case 'S':
+      verbose_level = VERB_SILENT;     break;
+
+    case 'f':
+    case 'F':
+      verbose_level = VERB_FIXES;      break;
+
+    case 'a':
+    case 'A':
+      verbose_level = VERB_APPLIES;    break;
+
+    case 'p':
+    case 'P':
+      verbose_level = VERB_PROGRESS;   break;
+
+    case 't':
+    case 'T':
+      verbose_level = VERB_TESTS;      break;
+
+    case 'e':
+    case 'E':
+      verbose_level = VERB_EVERYTHING; break;
+    }
+
+ while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
+   pz_find_base += 2;
+ if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
+   find_base_len = strlen( pz_find_base );
 
   /*  Compile all the regular expressions now.
       That way, it is done only once for the whole run.
@@ -399,80 +288,14 @@ initialize ()
   run_compiles ();
 
   signal (SIGQUIT, SIG_IGN);
+#ifdef SIGIOT
   signal (SIGIOT,  SIG_IGN);
+#endif
   signal (SIGPIPE, SIG_IGN);
   signal (SIGALRM, SIG_IGN);
   signal (SIGTERM, SIG_IGN);
-#ifndef NO_BOGOSITY
-  /*
-     Make sure that if we opened a server process, we close it now.
-     This is the grandparent process.  We don't need the server anymore
-     and our children should make their own.  */
-
-  close_server ();
-  (void)wait ( (int*)NULL );
-#endif
 }
 
-#ifndef NO_BOGOSITY
-/* * * * * * * * * * * * *
-
-   wait_for_pid  -  Keep calling `wait(2)' until it returns
-   the process id we are looking for.  Not every system has
-   `waitpid(2)'.  We also ensure that the children exit with success. */
-
-void
-wait_for_pid(child)
-     pid_t child;
-{
-  for (;;) {
-    int status;
-    pid_t dead_kid = wait (&status);
-
-    if (dead_kid == child)
-      {
-        if (! WIFEXITED( status ))
-          {
-            if (WSTOPSIG( status ) == 0)
-              break;
-
-            fprintf (stderr, "child process %d is hung on signal %d\n",
-                     child, WSTOPSIG( status ));
-            exit (EXIT_FAILURE);
-          }
-        if (WEXITSTATUS( status ) != 0)
-          {
-            fprintf (stderr, "child process %d exited with status %d\n",
-                     child, WEXITSTATUS( status ));
-            exit (EXIT_FAILURE);
-          }
-        break; /* normal child completion */
-      }
-
-    /*
-       IF there is an error, THEN see if it is retryable.
-       If it is not retryable, then break out of this loop.  */
-    if (dead_kid == NOPROCESS)
-      {
-        switch (errno) {
-        case EINTR:
-        case EAGAIN:
-          break;
-
-        default:
-          if (NOT_SILENT)
-            fprintf (stderr, "Error %d (%s) waiting for %d to finish\n",
-                     errno, strerror( errno ), child );
-          /* FALLTHROUGH */
-
-        case ECHILD: /* no children to wait for?? */
-          return;
-        }
-      }
-  } done_waiting:;
-}
-#endif /* NO_BOGOSITY */
-
 /* * * * * * * * * * * * *
 
    load_file loads all the contents of a file into malloc-ed memory.
@@ -490,7 +313,7 @@ load_file ( fname )
     {
       if (NOT_SILENT)
         fprintf (stderr, "error %d (%s) stat-ing %s\n",
-                 errno, strerror (errno), fname );
+                 errno, xstrerror (errno), fname );
       return (char *) NULL;
     }
   if (stbf.st_size == 0)
@@ -504,11 +327,11 @@ load_file ( fname )
     {
       if (NOT_SILENT)
         fprintf (stderr, "error %d (%s) opening %s for read\n",
-                 errno, strerror (errno), fname);
+                 errno, xstrerror (errno), fname);
       return (char*)NULL;
     }
 
-#ifdef HAVE_MMAP
+#ifdef HAVE_MMAP_FILE
   curr_data_mapped = BOOL_TRUE;
   res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ, MAP_PRIVATE,
                      data_map_fd, 0);
@@ -537,7 +360,6 @@ run_compiles ()
   int fix_ct = FIX_COUNT;
   tTestDesc *p_test;
   int test_ct;
-  int re_ct = REGEX_COUNT;
   const char *pz_err;
   regex_t *p_re = (regex_t *) malloc (REGEX_COUNT * sizeof (regex_t));
 
@@ -554,7 +376,12 @@ run_compiles ()
   memset ( (void*)&incl_quote_re, '\0', sizeof (regex_t) );
 
   compile_re (incl_quote_pat, &incl_quote_re, 1,
-             "quoted include", "run_compiles");
+              "quoted include", "run_compiles");
+
+  /*  Allow machine name tests to be ignored (testing, mainly) */
+
+  if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
+    pz_machine = (char*)NULL;
 
   /* FOR every fixup, ...  */
   do
@@ -643,20 +470,21 @@ run_compiles ()
             {
             case TT_EGREP:
             case TT_NEGREP:
-              /*  You might consider putting the following under #ifdef.
-                  The number of re's used is computed by autogen.
-                  So, it is static and known at compile time.  */
-
-              if (--re_ct < 0)
-                {
-                  fputs ("out of RE's\n", stderr);
-                  exit (EXIT_FAILURE);
-                }
+#ifdef DEBUG
+              {
+                static int re_ct = REGEX_COUNT;
 
+                if (--re_ct < 0)
+                  {
+                    fputs ("out of RE's\n", stderr);
+                    exit (EXIT_FAILURE);
+                  }
+              }
+#endif
               p_test->p_test_regex = p_re++;
-             compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
-                         "select test", p_fixd->fix_name);
-           }
+              compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
+                          "select test", p_fixd->fix_name);
+            }
           p_test++;
         }
     }
@@ -722,24 +550,23 @@ create_file ()
   if (fd < 0)
     {
       fprintf (stderr, "Error %d (%s) creating %s\n",
-               errno, strerror (errno), fname);
+               errno, xstrerror (errno), fname);
       exit (EXIT_FAILURE);
     }
   if (NOT_SILENT)
     fprintf (stderr, "Fixed:  %s\n", pz_curr_file);
   pf = fdopen (fd, "w");
 
-#ifdef LATER
-  {
-    static const char hdr[] =
-    "/*  DO NOT EDIT THIS FILE.\n\n"
-    "    It has been auto-edited by fixincludes from /usr/include/%s\n"
-    "    This had to be done to correct non-standard usages in the\n"
-    "    original, manufacturer supplied header file.  */\n\n";
+  /*
+   *  IF pz_machine is NULL, then we are in some sort of test mode.
+   *  Do not insert the current directory name.  Use a constant string.
+   */
+  fprintf (pf, z_std_preamble,
+           (pz_machine == NULL)
+           ? "fixinc/tests/inc"
+           : pz_input_dir,
+           pz_curr_file);
 
-    fprintf (pf, hdr, pz_curr_file);
-  }
-#endif
   return pf;
 }
 
@@ -765,14 +592,27 @@ else echo FALSE\n\
 fi";
 
   char *pz_res;
-  int res = SKIP_FIX;
+  int res;
 
   static char cmd_buf[4096];
 
   sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
   pz_res = run_shell (cmd_buf);
-  if (*pz_res == 'T')
+
+  switch (*pz_res) {
+  case 'T':
     res = APPLY_FIX;
+    break;
+
+  case 'F':
+    res = SKIP_FIX;
+    break;
+
+  default:
+    fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
+             pz_res, cmd_buf );
+  }
+
   free ((void *) pz_res);
   return res;
 }
@@ -966,7 +806,7 @@ internal_fix (read_fd, p_fixd)
       /*
        *  Parent in error
        */
-      fprintf (stderr, z_fork_err, errno, strerror (errno),
+      fprintf (stderr, z_fork_err, errno, xstrerror (errno),
                p_fixd->fix_name);
       {
         static int failCt = 0;
@@ -989,10 +829,8 @@ internal_fix (read_fd, p_fixd)
    */
   fcntl (fd[1], F_DUPFD, STDOUT_FILENO);
   fcntl (read_fd, F_DUPFD, STDIN_FILENO);
-  fdopen (STDIN_FILENO, "r");
-  fdopen (STDOUT_FILENO, "w");
 
-  apply_fix (p_fixd->patch_args[0], pz_curr_file);
+  apply_fix (p_fixd, pz_curr_file);
   exit (0);
 }
 
@@ -1056,7 +894,7 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
           break;
         }
 
-      fprintf (stderr, z_fork_err, errno, strerror (errno),
+      fprintf (stderr, z_fork_err, errno, xstrerror (errno),
                p_fixd->fix_name);
 
       if ((errno != EAGAIN) || (++failCt > 10))
@@ -1087,7 +925,8 @@ fix_applies (p_fixd)
   tFixDesc *p_fixd;
 {
 #ifdef DEBUG
-  static const char z_failed[] = "not applying %s to %s - test %d failed\n";
+  static const char z_failed[] = "not applying %s %s to %s - \
+test %d failed\n";
 #endif
   const char *pz_fname = pz_curr_file;
   const char *pz_scan = p_fixd->file_list;
@@ -1143,8 +982,8 @@ fix_applies (p_fixd)
           if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
 #ifdef DEBUG
             if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, p_fixd->fix_name, pz_fname,
-                       p_fixd->test_ct - test_ct);
+              fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
 #endif
             return BOOL_FALSE;
           }
@@ -1154,8 +993,8 @@ fix_applies (p_fixd)
           if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
 #ifdef DEBUG
             if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, p_fixd->fix_name, pz_fname,
-                       p_fixd->test_ct - test_ct);
+              fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
 #endif
             return BOOL_FALSE;
           }
@@ -1165,8 +1004,8 @@ fix_applies (p_fixd)
           if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
 #ifdef DEBUG
             if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, p_fixd->fix_name, pz_fname,
-                       p_fixd->test_ct - test_ct);
+              fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
 #endif
             /*  Negated sense  */
             return BOOL_FALSE;
@@ -1178,8 +1017,8 @@ fix_applies (p_fixd)
               != APPLY_FIX) {
 #ifdef DEBUG
             if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, z_failed, p_fixd->fix_name, pz_fname,
-                       p_fixd->test_ct - test_ct);
+              fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
 #endif
             return BOOL_FALSE;
           }
@@ -1305,7 +1144,7 @@ process ()
       int erno = errno;
       fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
                pz_curr_file, getcwd ((char *) NULL, MAXPATHLEN),
-               erno, strerror (erno));
+               erno, xstrerror (erno));
       return;
     }
 
@@ -1350,7 +1189,7 @@ process ()
           if (read_fd < 0)
             {
               fprintf (stderr, "Error %d (%s) opening %s\n", errno,
-                       strerror (errno), pz_curr_file);
+                       xstrerror (errno), pz_curr_file);
               exit (EXIT_FAILURE);
             }