OSDN Git Service

extra casting required by new pointer type
[pf3gnuchains/gcc-fork.git] / gcc / fixinc / fixincl.c
index 2dc8d21..a1746af 100644 (file)
@@ -1,4 +1,3 @@
-
 /* Install modified versions of certain ANSI-incompatible system header
    files which are fixed to work correctly with ANSI C and placed in a
    directory that GNU C will search.
@@ -24,24 +23,39 @@ Boston, MA 02111-1307, USA.  */
 
 #include "fixlib.h"
 
-#if HAVE_MMAP_FILE
+#if defined( HAVE_MMAP_FILE )
 #include <sys/mman.h>
 #define  BAD_ADDR ((void*)-1)
 #endif
 
 #include <signal.h>
-
+#if ! defined( SIGCHLD ) && defined( SIGCLD )
+#  define SIGCHLD SIGCLD
+#endif
+#ifndef SEPARATE_FIX_PROC
 #include "server.h"
+#endif
 
 /*  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";
 
+/*  This format will be used at the start of every generated file */
+
+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";
+
 /*  Working environment strings.  Essentially, invocation 'options'.  */
-char *pz_dest_dir = NULL;
-char *pz_src_dir = NULL;
-char *pz_machine = NULL;
+
+#define _ENV_(v,m,n,t)   tCC* v = NULL;
+ENV_TABLE
+#undef _ENV_
+
 int find_base_len = 0;
 
 typedef enum {
@@ -56,17 +70,20 @@ typedef enum {
 te_verbose  verbose_level = VERB_PROGRESS;
 int have_tty = 0;
 
-#define VLEVEL(l)  (verbose_level >= l)
+#define VLEVEL(l)  ((unsigned int) verbose_level >= (unsigned int) l)
 #define NOT_SILENT VLEVEL(VERB_FIXES)
 
 pid_t process_chain_head = (pid_t) -1;
 
 char*  pz_curr_file;  /*  name of the current file under test/fix  */
 char*  pz_curr_data;  /*  original contents of that file  */
+char*  pz_temp_file;  /*  for DOS, a place to stash the temporary
+                          fixed data between system(3) calls  */
 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;
@@ -74,24 +91,15 @@ int fixed_ct = 0;
 int altered_ct = 0;
 #endif /* DO_STATS */
 
-#ifdef HAVE_MMAP_FILE
-#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;
 
-void do_version ();
-char *load_file  _P_((const char *));
-void process  _P_((char *, const char *));
-void run_compiles ();
-void initialize _P_((int argc,char** argv));
-void process ();
+static void do_version   PARAMS((void)) ATTRIBUTE_NORETURN;
+char *load_file   PARAMS((const char *));
+void run_compiles PARAMS((void));
+void initialize   PARAMS((int argc,char** argv));
+void process      PARAMS((void));
 
 /*  External Source Code */
 
@@ -101,6 +109,7 @@ void process ();
  *
  *  MAIN ROUTINE
  */
+extern int main PARAMS ((int, char **));
 int
 main (argc, argv)
      int argc;
@@ -174,11 +183,15 @@ Altering  %5d of them\n";
              fixed_ct, altered_ct);
   }
 #endif /* DO_STATS */
-  return EXIT_SUCCESS;
+
+# ifdef SEPARATE_FIX_PROC
+  unlink( pz_temp_file );
+# endif
+  exit (EXIT_SUCCESS);
 }
 
 
-void
+static void
 do_version ()
 {
   static const char zFmt[] = "echo '%s'";
@@ -191,8 +204,12 @@ do_version ()
   */
   run_compiles ();
   sprintf (zBuf, zFmt, program_id);
+#ifndef SEPARATE_FIX_PROC
   puts (zBuf + 5);
   exit (strcmp (run_shell (zBuf), program_id));
+#else
+  exit (system (zBuf));
+#endif
 }
 
 /* * * * * * * * * * * * */
@@ -203,8 +220,18 @@ initialize ( argc, argv )
   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";
+#ifndef __STDC__
+    "fixincl ERROR:  %s environment variable not defined\n"
+#else
+    "fixincl ERROR:  %s environment variable not defined\n"
+    "each of these must be defined:\n"
+# define _ENV_(v,m,n,t) "\t" n "  - " t "\n"
+  ENV_TABLE
+# undef _ENV_
+#endif
+    ;
+
+  xmalloc_set_program_name (argv[0]);
 
   switch (argc)
     {
@@ -227,96 +254,73 @@ initialize ( argc, argv )
       exit (EXIT_FAILURE);
     }
 
-  {
-    static const char var[] = "TARGET_MACHINE";
-    pz_machine = getenv (var);
-    if (pz_machine == (char *) NULL)
-      {
-        fprintf (stderr, var_not_found, var);
-        exit (EXIT_FAILURE);
-      }
-  }
+#ifdef SIGCHLD
+  /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
+     receive the signal.  A different setting is inheritable */
+  signal (SIGCHLD, SIG_DFL);
+#endif
 
-  {
-    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);
-      }
-  }
+#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); } }
 
-  {
-    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);
-      }
-  }
+ENV_TABLE
 
-  {
-    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;
-          }
-      }
-  }
+#undef _ENV_
 
-  {
-    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 );
-  }
+  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.
       */
   run_compiles ();
 
+# ifdef SEPARATE_FIX_PROC
+  /* NULL as the first argument to `tempnam' causes it to DTRT
+     wrt the temporary directory where the file will be created.  */
+  pz_temp_file = tempnam( NULL, "fxinc" );
+# endif
+
   signal (SIGQUIT, SIG_IGN);
 #ifdef SIGIOT
   signal (SIGIOT,  SIG_IGN);
 #endif
+#ifdef SIGPIPE
   signal (SIGPIPE, SIG_IGN);
+#endif
   signal (SIGALRM, SIG_IGN);
   signal (SIGTERM, SIG_IGN);
 }
@@ -344,6 +348,10 @@ load_file ( fname )
   if (stbf.st_size == 0)
     return (char*)NULL;
 
+  /*  Make the data map size one larger than the file size for documentation
+      purposes.  Truth is that there will be a following NUL character if
+      the file size is not a multiple of the page size.  If it is a multiple,
+      then this adjustment sometimes fails anyway.  */
   data_map_size = stbf.st_size+1;
   data_map_fd   = open (fname, O_RDONLY);
   ttl_data_size += data_map_size-1;
@@ -358,69 +366,32 @@ load_file ( fname )
 
 #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);
+
+  /*  IF the file size is a multiple of the page size,
+      THEN sometimes you will seg fault trying to access a trailing byte */
+  if ((stbf.st_size & (getpagesize()-1)) == 0)
+    res = (char*)BAD_ADDR;
+  else
+    res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
+                       MAP_PRIVATE, data_map_fd, 0);
   if (res == (char*)BAD_ADDR)
+#endif
     {
+      FILE* fp = fdopen (data_map_fd, "r");
       curr_data_mapped = BOOL_FALSE;
-      res = load_file_data ( fdopen (data_map_fd, "r"));
+      res = load_file_data (fp);
+      fclose (fp);
     }
-#else
-  curr_data_mapped = BOOL_FALSE;
-  res = load_file_data ( fdopen (data_map_fd, "r"));
-#endif
 
   return res;
 }
 
-
-/* * * * * * * * * * * * *
-
-   run_compiles   run all the regexp compiles for all the fixes once.
- */
-void
-run_compiles ()
-{
-  tFixDesc *p_fixd = fixDescList;
-  int fix_ct = FIX_COUNT;
-  tTestDesc *p_test;
-  int test_ct;
-  const char *pz_err;
-  regex_t *p_re = (regex_t *) malloc (REGEX_COUNT * sizeof (regex_t));
-
-  if (p_re == (regex_t *) NULL)
-    {
-      fprintf (stderr, "fixincl ERROR:  cannot allocate %d bytes for regex\n",
-               REGEX_COUNT * sizeof (regex_t));
-      exit (EXIT_FAILURE);
-    }
-
-  /*  Make sure compile_re does not stumble across invalid data */
-
-  memset ( (void*)p_re, '\0', REGEX_COUNT * sizeof (regex_t) );
-  memset ( (void*)&incl_quote_re, '\0', sizeof (regex_t) );
-
-  compile_re (incl_quote_pat, &incl_quote_re, 1,
-              "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
-    {
-      p_test = p_fixd->p_test_desc;
-      test_ct = p_fixd->test_ct;
-
-      /*  IF the machine type pointer is not NULL (we are not in test mode)
-             AND this test is for or not done on particular machines
-          THEN ...   */
-
-      if (  (pz_machine != NULL)
-         && (p_fixd->papz_machs != (const char**) NULL) )
+static int machine_matches PARAMS ((tFixDesc *));
+static int
+machine_matches( p_fixd )
+  tFixDesc *p_fixd;
         {
+# ifndef SEPARATE_FIX_PROC
           tSCC case_fmt[] = "case %s in\n";     /*  9 bytes, plus string */
           tSCC esac_fmt[] =
                " )\n    echo %s ;;\n* ) echo %s ;;\nesac";/*  4 bytes */
@@ -430,7 +401,7 @@ run_compiles ()
 
           const char **papz_machs = p_fixd->papz_machs;
           char *pz;
-          char *pz_sep = "";
+          const char *pz_sep = "";
           tCC *pz_if_true;
           tCC *pz_if_false;
           char cmd_buf[ MACH_LIST_SIZE_LIMIT ]; /* size lim from fixincl.tpl */
@@ -482,10 +453,67 @@ run_compiles ()
             if (skip)
               {
                 p_fixd->fd_flags |= FD_SKIP_TEST;
-                continue;
-              }
-           }
-        }
+               return BOOL_FALSE;
+             }
+         }
+
+  return BOOL_TRUE;
+# else /* is SEPARATE_FIX_PROC */
+  const char **papz_machs = p_fixd->papz_machs;
+  int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0;
+  for (;;)
+    {
+      const char* pz_mach = *(papz_machs++);
+
+      if (pz_mach == (const char*) NULL)
+        break;
+      if (strstr (pz_mach, "dos") != NULL && !invert)
+       return BOOL_TRUE;
+    }
+
+  p_fixd->fd_flags |= FD_SKIP_TEST;
+  return BOOL_FALSE;
+# endif
+}
+
+/* * * * * * * * * * * * *
+
+   run_compiles   run all the regexp compiles for all the fixes once.
+   */
+void
+run_compiles ()
+{
+  tFixDesc *p_fixd = fixDescList;
+  int fix_ct = FIX_COUNT;
+  regex_t *p_re = (regex_t *) xmalloc (REGEX_COUNT * sizeof (regex_t));
+
+  /*  Make sure compile_re does not stumble across invalid data */
+
+  memset ( (void*)p_re, '\0', REGEX_COUNT * sizeof (regex_t) );
+  memset ( (void*)&incl_quote_re, '\0', sizeof (regex_t) );
+
+  compile_re (incl_quote_pat, &incl_quote_re, 1,
+              "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
+    {
+      tTestDesc *p_test = p_fixd->p_test_desc;
+      int test_ct = p_fixd->test_ct;
+
+      /*  IF the machine type pointer is not NULL (we are not in test mode)
+             AND this test is for or not done on particular machines
+          THEN ...   */
+
+      if (  (pz_machine != NULL)
+         && (p_fixd->papz_machs != (const char**) NULL)
+         && ! machine_matches (p_fixd) )
+        continue;
 
       /* FOR every test for the fixup, ...  */
 
@@ -495,20 +523,10 @@ run_compiles ()
             {
             case TT_EGREP:
             case TT_NEGREP:
-#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);
+            default: break;
             }
           p_test++;
         }
@@ -540,7 +558,8 @@ run_compiles ()
 #endif
 
 
-FILE *
+static FILE *create_file PARAMS ((void));
+static FILE *
 create_file ()
 {
   int fd;
@@ -582,17 +601,16 @@ create_file ()
     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;
 }
 
@@ -604,8 +622,9 @@ create_file ()
           the name of the file that we might want to fix
   Result: APPLY_FIX or SKIP_FIX, depending on the result of the
           shell script we run.  */
-
-int
+#ifndef SEPARATE_FIX_PROC
+static int test_test PARAMS ((tTestDesc *, char *));
+static int
 test_test (p_test, pz_test_file)
      tTestDesc *p_test;
      char*      pz_test_file;
@@ -618,18 +637,37 @@ 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;
 }
-
+#else
+/*
+ *  IF we are in MS-DOS land, then whatever shell-type test is required
+ *  will, by definition, fail
+ */
+#define test_test(t,tf)  SKIP_FIX
+#endif
 
 /* * * * * * * * * * * * *
 
@@ -641,7 +679,8 @@ fi";
   The caller may choose to reverse meaning if the sense of the test
   is inverted.  */
 
-int
+static int egrep_test PARAMS ((char *, tTestDesc *));
+static int
 egrep_test (pz_data, p_test)
      char *pz_data;
      tTestDesc *p_test;
@@ -663,11 +702,12 @@ egrep_test (pz_data, p_test)
   the file name.  If we emit the name, our invoking shell will try
   to copy a non-existing file into the destination directory.  */
 
-int
+static int quoted_file_exists PARAMS ((const char *, const char *, const char *));
+static int
 quoted_file_exists (pz_src_path, pz_file_path, pz_file)
-     char* pz_src_path;
-     char* pz_file_path;
-     char* pz_file;
+     const char *pz_src_path;
+     const char *pz_file_path;
+     const char *pz_file;
 {
   char z[ MAXPATHLEN ];
   char* pz;
@@ -714,7 +754,8 @@ quoted_file_exists (pz_src_path, pz_file_path, pz_file)
            for interpretation by the invoking shell  */
 
 
-void
+static void extract_quoted_files PARAMS ((char *, const char *, regmatch_t *));
+static void
 extract_quoted_files (pz_data, pz_fixed_file, p_re_match)
      char *pz_data;
      const char *pz_fixed_file;
@@ -739,14 +780,8 @@ extract_quoted_files (pz_data, pz_fixed_file, p_re_match)
       pz_incl_quot += p_re_match->rm_so;
 
       /*  Skip forward to the included file name */
-      while (ISSPACE (*pz_incl_quot))
+      while (*pz_incl_quot != '"')
         pz_incl_quot++;
-      /* ISSPACE() may evaluate is argument more than once!  */
-      while (++pz_incl_quot, ISSPACE (*pz_incl_quot))
-        ;
-      pz_incl_quot += sizeof ("include") - 1;
-      while (*pz_incl_quot++ != '"')
-        ;
 
       if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
         {
@@ -780,8 +815,9 @@ extract_quoted_files (pz_data, pz_fixed_file, p_re_match)
 
     Somebody wrote a *_fix subroutine that we must call.
     */
-
-int
+#ifndef SEPARATE_FIX_PROC
+static int internal_fix PARAMS ((int, tFixDesc *));
+static int
 internal_fix (read_fd, p_fixd)
   int read_fd;
   tFixDesc* p_fixd;
@@ -846,7 +882,152 @@ internal_fix (read_fd, p_fixd)
   apply_fix (p_fixd, pz_curr_file);
   exit (0);
 }
+#endif /* !SEPARATE_FIX_PROC */
+
+
+#ifdef SEPARATE_FIX_PROC
+static void
+fix_with_system (p_fixd, pz_fix_file, pz_file_source, pz_temp_file)
+  tFixDesc* p_fixd;
+  tCC* pz_fix_file;
+  tCC* pz_file_source;
+  tCC* pz_temp_file;
+{
+  char*  pz_cmd;
+  char*  pz_scan;
+  size_t argsize;
+
+  if (p_fixd->fd_flags & FD_SUBROUTINE)
+    {
+      tSCC z_applyfix_prog[] = "/fixinc/applyfix";
+
+      argsize = 32
+              + strlen( pz_orig_dir )
+              + sizeof( z_applyfix_prog )
+              + strlen( pz_fix_file )
+              + strlen( pz_file_source )
+              + strlen( pz_temp_file );
+
+      pz_cmd = (char*)xmalloc( argsize );
+
+      strcpy( pz_cmd, pz_orig_dir );
+      pz_scan = pz_cmd + strlen( pz_orig_dir );
+      strcpy( pz_scan, z_applyfix_prog );
+      pz_scan += sizeof( z_applyfix_prog ) - 1;
+      *(pz_scan++) = ' ';
+
+      /*
+       *  Now add the fix number and file names that may be needed
+       */
+      sprintf (pz_scan, "%ld \'%s\' \'%s\' \'%s\'", p_fixd - fixDescList,
+              pz_fix_file, pz_file_source, pz_temp_file);
+    }
+  else /* NOT an "internal" fix: */
+    {
+      size_t parg_size;
+#ifdef __MSDOS__
+      /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
+         dst is a temporary file anyway, so we know there's no other
+         file by that name; and DOS's system(3) doesn't mind to
+         clobber existing file in redirection.  Besides, with DOS 8+3
+         limited file namespace, we can easily lose if dst already has
+         an extension that is 3 or more characters long.
+
+         I do not think the 8+3 issue is relevant because all the files
+         we operate on are named "*.h", making 8+2 adequate.  Anyway,
+         the following bizarre use of 'cat' only works on DOS boxes.
+         It causes the file to be dropped into a temporary file for
+         'cat' to read (pipes do not work on DOS).  */
+      tSCC   z_cmd_fmt[] = " \'%s\' | cat > \'%s\'";
+#else
+      /* Don't use positional formatting arguments because some lame-o
+         implementations cannot cope  :-(.  */
+      tSCC   z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
+#endif
+      tCC**  ppArgs = p_fixd->patch_args;
+
+      argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
+              + strlen( pz_file_source );
+      parg_size = argsize;
+      
+
+      /*
+       *  Compute the size of the command line.  Add lotsa extra space
+       *  because some of the args to sed use lotsa single quotes.
+       *  (This requires three extra bytes per quote.  Here we allow
+       *  for up to 8 single quotes for each argument, including the
+       *  command name "sed" itself.  Nobody will *ever* need more. :)
+       */
+      for (;;)
+        {
+          tCC* p_arg = *(ppArgs++);
+          if (p_arg == NULL)
+            break;
+          argsize += 24 + strlen( p_arg );
+        }
+
+      /* Estimated buffer size we will need.  */
+      pz_scan = pz_cmd = (char*)xmalloc( argsize );
+      /* How much of it do we allot to the program name and its
+         arguments.  */
+      parg_size = argsize - parg_size;
 
+      ppArgs = p_fixd->patch_args;
+
+      /*
+       *  Copy the program name, unquoted
+       */
+      {
+        tCC*   pArg = *(ppArgs++);
+        for (;;)
+          {
+            char ch = *(pArg++);
+            if (ch == NUL)
+              break;
+            *(pz_scan++) = ch;
+          }
+      }
+
+      /*
+       *  Copy the program arguments, quoted
+       */
+      for (;;)
+        {
+          tCC*   pArg = *(ppArgs++);
+         char*  pz_scan_save;
+          if (pArg == NULL)
+            break;
+          *(pz_scan++) = ' ';
+          pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
+                                       parg_size - (pz_scan - pz_cmd) );
+         /*
+          *  Make sure we don't overflow the buffer due to sloppy
+          *  size estimation.
+          */
+         while (pz_scan == (char*)NULL)
+           {
+             size_t already_filled = pz_scan_save - pz_cmd;
+             pz_cmd = (char*)xrealloc( pz_cmd, argsize += 100 );
+             pz_scan_save = pz_scan = pz_cmd + already_filled;
+             parg_size += 100;
+             pz_scan = make_raw_shell_str( pz_scan, pArg,
+                                           parg_size - (pz_scan - pz_cmd) );
+           }
+        }
+
+      /*
+       *  add the file machinations.
+       */
+#ifdef __MSDOS__
+      sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
+#else
+      sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
+               pz_temp_file, pz_temp_file, pz_temp_file);
+#endif
+    }
+  system( pz_cmd );
+  free( (void*)pz_cmd );
+}
 
 /* * * * * * * * * * * * *
 
@@ -855,7 +1036,9 @@ internal_fix (read_fd, p_fixd)
     its stdin and returns the new fd this process will use
     for stdout.  */
 
-int
+#else /* is *NOT* SEPARATE_FIX_PROC */
+static int start_fixer PARAMS ((int, tFixDesc *, char *));
+static int
 start_fixer (read_fd, p_fixd, pz_fix_file)
   int read_fd;
   tFixDesc* p_fixd;
@@ -872,14 +1055,9 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
   else
     {
       tSCC z_cmd_fmt[] = "file='%s'\n%s";
-      pz_cmd = (char*)malloc (strlen (p_fixd->patch_args[2])
-                               + sizeof( z_cmd_fmt )
-                               + strlen( pz_fix_file ));
-      if (pz_cmd == (char*)NULL)
-        {
-          fputs ("allocation failure\n", stderr);
-          exit (EXIT_FAILURE);
-        }
+      pz_cmd = (char*) xmalloc (strlen (p_fixd->patch_args[2])
+                               + sizeof( z_cmd_fmt )
+                               + strlen( pz_fix_file ));
       sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
       pz_cmd_save = p_fixd->patch_args[2];
       p_fixd->patch_args[2] = pz_cmd;
@@ -897,7 +1075,7 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
       int fd;
 
       fd = chain_open (read_fd,
-                       (t_pchar *) p_fixd->patch_args,
+                       (tCC **) p_fixd->patch_args,
                        (process_chain_head == -1)
                        ? &process_chain_head : (pid_t *) NULL);
 
@@ -925,6 +1103,7 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
 
   return read_fd;
 }
+#endif
 
 
 /* * * * * * * * * * * * *
@@ -933,20 +1112,28 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
    Input:  the original text of the file and the file's name
    Result: none.  A new file may or may not be created.  */
 
-t_bool
+static t_bool fix_applies PARAMS ((tFixDesc *));
+static t_bool
 fix_applies (p_fixd)
   tFixDesc *p_fixd;
 {
-#ifdef DEBUG
-  static const char z_failed[] = "not applying %s to %s - test %d failed\n";
-#endif
   const char *pz_fname = pz_curr_file;
   const char *pz_scan = p_fixd->file_list;
   int test_ct;
   tTestDesc *p_test;
 
+# ifdef SEPARATE_FIX_PROC
+  /*
+   *  There is only one fix that uses a shell script as of this writing.
+   *  I hope to nuke it anyway, it does not apply to DOS and it would
+   *  be painful to implement.  Therefore, no "shell" fixes for DOS.
+   */
+  if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
+    return BOOL_FALSE;
+# else
   if (p_fixd->fd_flags & FD_SKIP_TEST)
     return BOOL_FALSE;
+# endif
 
   /*  IF there is a file name restriction,
       THEN ensure the current file name matches one in the pattern  */
@@ -964,14 +1151,8 @@ fix_applies (p_fixd)
           pz_scan = strstr (pz_scan + 1, pz_fname);
           /*  IF we can't match the string at all,
               THEN bail  */
-          if (pz_scan == (char *) NULL) {
-#ifdef DEBUG
-            if (VLEVEL( VERB_EVERYTHING ))
-              fprintf (stderr, "file %s not in list for %s\n",
-                       pz_fname, p_fixd->fix_name );
-#endif
+          if (pz_scan == (char *) NULL)
             return BOOL_FALSE;
-          }
 
           /*  IF the match is surrounded by the '|' markers,
               THEN we found a full match -- time to run the tests  */
@@ -994,8 +1175,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;
           }
@@ -1005,8 +1186,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;
           }
@@ -1016,8 +1197,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;
@@ -1029,8 +1210,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;
           }
@@ -1046,7 +1227,8 @@ fix_applies (p_fixd)
 
    Write out a replacement file  */
 
-void
+static void write_replacement PARAMS ((tFixDesc *));
+static void
 write_replacement (p_fixd)
   tFixDesc *p_fixd;
 {
@@ -1056,7 +1238,7 @@ write_replacement (p_fixd)
      return;
 
    {
-     FILE* out_fp = create_file (pz_curr_file);
+     FILE* out_fp = create_file ();
      fputs (pz_text, out_fp);
      fclose (out_fp);
    }
@@ -1072,13 +1254,14 @@ write_replacement (p_fixd)
     the matched text and then copy any remaining data from the
     output of the filter chain.
     */
-void
+static void test_for_changes PARAMS ((int));
+static void
 test_for_changes (read_fd)
   int read_fd;
 {
   FILE *in_fp = fdopen (read_fd, "r");
   FILE *out_fp = (FILE *) NULL;
-  char *pz_cmp = pz_curr_data;
+  unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
 
 #ifdef DO_STATS
   fixed_ct++;
@@ -1090,6 +1273,7 @@ test_for_changes (read_fd)
       ch = getc (in_fp);
       if (ch == EOF)
         break;
+      ch &= 0xFF; /* all bytes are 8 bits */
 
       /*  IF we are emitting the output
           THEN emit this character, too.
@@ -1102,14 +1286,15 @@ test_for_changes (read_fd)
       */
       else if (ch != *pz_cmp)
         {
-          out_fp = create_file (pz_curr_file);
+          out_fp = create_file ();
 
 #ifdef DO_STATS
           altered_ct++;
 #endif
           /*  IF there are matched data, write the matched part now. */
-          if (pz_cmp != pz_curr_data)
-            fwrite (pz_curr_data, (size_t)(pz_cmp - pz_curr_data), 1, out_fp);
+          if ((char*)pz_cmp != pz_curr_data)
+            fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
+                                       1, out_fp);
 
           /*  Emit the current unmatching character */
           putc (ch, out_fp);
@@ -1145,11 +1330,14 @@ test_for_changes (read_fd)
 void
 process ()
 {
-  static char env_current_file[1024];
   tFixDesc *p_fixd = fixDescList;
   int todo_ct = FIX_COUNT;
   int read_fd = -1;
+# ifndef SEPARATE_FIX_PROC
   int num_children = 0;
+# else /* is SEPARATE_FIX_PROC */
+  char* pz_file_source = pz_curr_file;
+# endif
 
   if (access (pz_curr_file, R_OK) != 0)
     {
@@ -1170,6 +1358,7 @@ process ()
   if (VLEVEL( VERB_PROGRESS ) && have_tty)
     fprintf (stderr, "%6d %-50s   \r", data_map_size, pz_curr_file );
 
+# ifndef SEPARATE_FIX_PROC
   process_chain_head = NOPROCESS;
 
   /* For every fix in our fix list, ...  */
@@ -1230,5 +1419,43 @@ process ()
       } while (--num_children > 0);
     }
 
+# else /* is SEPARATE_FIX_PROC */
+
+  for (; todo_ct > 0; p_fixd++, todo_ct--)
+    {
+      if (! fix_applies (p_fixd))
+        continue;
+
+      if (VLEVEL( VERB_APPLIES ))
+        fprintf (stderr, "Applying %-24s to %s\n",
+                 p_fixd->fix_name, pz_curr_file);
+
+      if (p_fixd->fd_flags & FD_REPLACEMENT)
+        {
+          write_replacement (p_fixd);
+          UNLOAD_DATA();
+          return;
+        }
+      fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
+      pz_file_source = pz_temp_file;
+    }
+
+  read_fd = open (pz_temp_file, O_RDONLY);
+  if (read_fd < 0)
+    {
+      if (errno != ENOENT)
+        fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
+                 errno, xstrerror (errno), pz_temp_file);
+    }
+  else
+    {
+      test_for_changes (read_fd);
+      /* Unlinking a file while it is still open is a Bad Idea on
+         DOS/Windows.  */
+      close (read_fd);
+      unlink (pz_temp_file);
+    }
+
+# endif
   UNLOAD_DATA();
 }