OSDN Git Service

more rigorous SIGCHLD guarding
[pf3gnuchains/gcc-fork.git] / gcc / fixinc / fixincl.c
index 6a143fd..5f1e363 100644 (file)
@@ -1,9 +1,8 @@
-
 /* 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.
 
-   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -24,97 +23,67 @@ Boston, MA 02111-1307, USA.  */
 
 #include "fixlib.h"
 
-#if HAVE_MMAP
+#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"
-
-/*  Quality Assurance Marker  :-)
-
-    Any file that contains this string is presumed to have
-    been carefully constructed and will not be fixed  */
-
-static const char gnu_lib_mark[] =
-    "This file is part of the GNU C Library";
+#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";
 
-/*  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;
+/*  This format will be used at the start of every generated file */
 
-struct test_desc
-{
-  te_test_type type;
-  const char *pz_test_text;
-  regex_t *p_test_regex;
-};
+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";
 
-typedef struct patch_desc tPatchDesc;
+/*  Working environment strings.  Essentially, invocation 'options'.  */
 
-/*  Fix Descriptor
+#define _ENV_(v,m,n,t)   tCC* v = NULL;
+ENV_TABLE
+#undef _ENV_
 
-    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...)
+int find_base_len = 0;
 
-    NB:  the FD_ defines are BIT FLAGS
+typedef enum {
+  VERB_SILENT = 0,
+  VERB_FIXES,
+  VERB_APPLIES,
+  VERB_PROGRESS,
+  VERB_TESTS,
+  VERB_EVERYTHING
+} te_verbose;
 
-    */
-#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;
-};
+te_verbose  verbose_level = VERB_PROGRESS;
+int have_tty = 0;
 
-/*  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;
+#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;
@@ -122,35 +91,25 @@ 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;
 
-void do_version ();
-char *load_file  _P_((const char *));
-void process  _P_((char *, const char *));
-void run_compiles ();
-void initialize ();
-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 */
 
 #include "fixincl.x"
-#include "fixtests.c"
-#include "fixfixes.c"
 
 /* * * * * * * * * * * * * * * * * * *
  *
  *  MAIN ROUTINE
  */
+extern int main PARAMS ((int, char **));
 int
 main (argc, argv)
      int argc;
@@ -158,28 +117,9 @@ main (argc, argv)
 {
   char *file_name_buf;
 
-  switch (argc)
-    {
-    case 1:
-      break;
+  initialize ( argc, argv );
 
-    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 ();
+  have_tty = isatty (fileno (stderr));
 
   /* Before anything else, ensure we can allocate our file name buffer. */
   file_name_buf = load_file_data (stdin);
@@ -228,37 +168,11 @@ 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
-  {
+  if (VLEVEL( VERB_PROGRESS )) {
     tSCC zFmt[] =
       "\
 Processed %5d files containing %d bytes    \n\
@@ -269,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'";
@@ -281,144 +199,130 @@ 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);
+#ifndef SEPARATE_FIX_PROC
+  puts (zBuf + 5);
   exit (strcmp (run_shell (zBuf), program_id));
+#else
+  exit (system (zBuf));
+#endif
 }
 
 /* * * * * * * * * * * * */
 
 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[] = "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 );
-  }
+    default:
+      fputs ("fixincl ERROR:  too many command line arguments\n", stderr);
+      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
+
+#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.
       */
   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);
-#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 ))
-          {
-            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:
-          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.
@@ -434,100 +338,58 @@ load_file ( fname )
 
   if (stat (fname, &stbf) != 0)
     {
-      fprintf (stderr, "error %d (%s) stat-ing %s\n",
-               errno, strerror (errno), fname );
+      if (NOT_SILENT)
+        fprintf (stderr, "error %d (%s) stat-ing %s\n",
+                 errno, xstrerror (errno), fname );
       return (char *) NULL;
     }
   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;
 
   if (data_map_fd < 0)
     {
-      fprintf (stderr, "error %d (%s) opening %s for read\n",
-               errno, strerror (errno), fname);
+      if (NOT_SILENT)
+        fprintf (stderr, "error %d (%s) opening %s for read\n",
+                 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);
+
+  /*  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 ()
-{
-  tSCC z_bad_comp[] = "fixincl ERROR:  cannot compile %s regex for %s\n\
-\texpr = `%s'\n\terror %s\n";
-  tFixDesc *p_fixd = fixDescList;
-  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));
-
-  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 re_compile_pattern 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) );
-
-  /*  The patterns we search for are all egrep patterns.
-      In the shell version of this program, we invoke egrep
-      with the supplied pattern.  Here, we will run
-      re_compile_pattern, but it must be using the same rules.  */
-
-  re_set_syntax (RE_SYNTAX_EGREP);
-  pz_err = re_compile_pattern (incl_quote_pat, sizeof (incl_quote_pat)-1,
-                              &incl_quote_re);
-  if (pz_err != (char *) NULL)
-    {
-      fprintf (stderr, z_bad_comp, "quoted include", "run_compiles",
-               incl_quote_pat, pz_err);
-      exit (EXIT_FAILURE);
-    }
-
-  /* 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 */
@@ -537,7 +399,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 */
@@ -589,10 +451,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, ...  */
 
@@ -602,26 +521,10 @@ 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);
-                }
-
               p_test->p_test_regex = p_re++;
-              pz_err = re_compile_pattern (p_test->pz_test_text,
-                                          strlen (p_test->pz_test_text),
-                                          p_test->p_test_regex);
-              if (pz_err != (char *) NULL)
-                {
-                  fprintf (stderr, z_bad_comp, "select test", p_fixd->fix_name,
-                           p_test->pz_test_text, pz_err);
-                  exit (EXIT_FAILURE);
-                }
+              compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
+                          "select test", p_fixd->fix_name);
+            default: break;
             }
           p_test++;
         }
@@ -636,9 +539,25 @@ run_compiles ()
    Input:    the name of the file to create
    Returns:  a file pointer to the new, open file  */
 
-#define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
+#if defined(S_IRUSR) && defined(S_IWUSR) && \
+    defined(S_IRGRP) && defined(S_IROTH)
+
+#   define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
+#else
+#   define S_IRALL 0644
+#endif
+
+#if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
+    defined(S_IROTH) && defined(S_IXOTH)
+
+#   define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+#else
+#   define S_DIRALL 0755
+#endif
+
 
-FILE *
+static FILE *create_file PARAMS ((void));
+static FILE *
 create_file ()
 {
   int fd;
@@ -660,8 +579,7 @@ create_file ()
           *pz_dir = NUL;
           if (stat (fname, &stbf) < 0)
             {
-              mkdir (fname, S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP
-                     | S_IROTH | S_IXOTH);
+              mkdir (fname, S_IFDIR | S_DIRALL);
             }
 
           *pz_dir = '/';
@@ -674,23 +592,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);
     }
-  fprintf (stderr, "Fixed:  %s\n", pz_curr_file);
+  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;
 }
 
@@ -702,8 +620,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;
@@ -716,18 +635,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
 
 /* * * * * * * * * * * * *
 
@@ -739,19 +677,18 @@ 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;
 {
-  regmatch_t match;
-
 #ifdef DEBUG
   if (p_test->p_test_regex == 0)
     fprintf (stderr, "fixincl ERROR RE not compiled:  `%s'\n",
              p_test->pz_test_text);
 #endif
-  if (regexec (p_test->p_test_regex, pz_data, 1, &match, 0) == 0)
+  if (regexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
     return APPLY_FIX;
   return SKIP_FIX;
 }
@@ -763,11 +700,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;
@@ -814,7 +752,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;
@@ -823,7 +762,8 @@ extract_quoted_files (pz_data, pz_fixed_file, p_re_match)
   char *pz_dir_end = strrchr (pz_fixed_file, '/');
   char *pz_incl_quot = pz_data;
 
-  fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
+  if (VLEVEL( VERB_APPLIES ))
+    fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
 
   /*  Set "pz_fixed_file" to point to the containing subdirectory of the source
       If there is none, then it is in our current directory, ".".   */
@@ -838,14 +778,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))
         {
@@ -879,8 +813,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;
@@ -918,7 +853,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;
@@ -941,14 +876,157 @@ 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);
 }
+#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 );
+}
+
 /* * * * * * * * * * * * *
 
     This loop should only cycle for 1/2 of one loop.
@@ -956,7 +1034,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;
@@ -973,26 +1053,27 @@ 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;
     }
 
+  /*  Start a fix process, handing off the  previous read fd for its
+      stdin and getting a new fd that reads from the fix process' stdout.
+      We normally will not loop, but we will up to 10 times if we keep
+      getting "EAGAIN" errors.
+
+      */
   for (;;)
     {
       static int failCt = 0;
       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);
 
@@ -1002,7 +1083,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))
@@ -1010,6 +1091,8 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
       sleep (1);
     }
 
+  /*  IF we allocated a shell script command,
+      THEN free it and restore the command format to the fix description */
   if (pz_cmd != (char*)NULL)
     {
       free ((void*)pz_cmd);
@@ -1018,6 +1101,7 @@ start_fixer (read_fd, p_fixd, pz_fix_file)
 
   return read_fd;
 }
+#endif
 
 
 /* * * * * * * * * * * * *
@@ -1026,23 +1110,34 @@ 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;
 {
+  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  */
 
-  if (p_fixd->file_list != (char *) NULL)
+  if (pz_scan != (char *) NULL)
     {
-      const char *pz_fname = pz_curr_file;
-      const char *pz_scan = p_fixd->file_list;
       size_t name_len;
 
       while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
@@ -1075,25 +1170,49 @@ fix_applies (p_fixd)
       switch (p_test->type)
         {
         case TT_TEST:
-          if (test_test (p_test, pz_curr_file) != APPLY_FIX)
+          if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
+#ifdef DEBUG
+            if (VLEVEL( VERB_EVERYTHING ))
+              fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
+#endif
             return BOOL_FALSE;
+          }
           break;
 
         case TT_EGREP:
-          if (egrep_test (pz_curr_data, p_test) != APPLY_FIX)
+          if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
+#ifdef DEBUG
+            if (VLEVEL( VERB_EVERYTHING ))
+              fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
+#endif
             return BOOL_FALSE;
+          }
           break;
 
         case TT_NEGREP:
-          if (egrep_test (pz_curr_data, p_test) == APPLY_FIX)
+          if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
+#ifdef DEBUG
+            if (VLEVEL( VERB_EVERYTHING ))
+              fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
+#endif
             /*  Negated sense  */
             return BOOL_FALSE;
+          }
           break;
 
         case TT_FUNCTION:
           if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
-              != APPLY_FIX)
+              != APPLY_FIX) {
+#ifdef DEBUG
+            if (VLEVEL( VERB_EVERYTHING ))
+              fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
+                       pz_fname, p_fixd->test_ct - test_ct);
+#endif
             return BOOL_FALSE;
+          }
           break;
         }
     }
@@ -1106,7 +1225,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;
 {
@@ -1116,7 +1236,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);
    }
@@ -1132,7 +1252,8 @@ 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;
 {
@@ -1162,7 +1283,7 @@ 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++;
@@ -1205,18 +1326,21 @@ 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)
     {
       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;
     }
 
@@ -1227,13 +1351,10 @@ process ()
 #ifdef DO_STATS
   process_ct++;
 #endif
-  fprintf (stderr, "%6d %-50s   \r", data_map_size, pz_curr_file );
-  if (strstr (pz_curr_data, gnu_lib_mark) != (char *) NULL)
-    {
-      UNLOAD_DATA();
-      return;
-    }
+  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, ...  */
@@ -1242,8 +1363,9 @@ process ()
       if (! fix_applies (p_fixd))
         continue;
 
-      fprintf (stderr, "Applying %-24s to %s\n",
-               p_fixd->fix_name, pz_curr_file);
+      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)
         {
@@ -1264,7 +1386,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);
             }
 
@@ -1293,5 +1415,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();
 }