OSDN Git Service

These files are being moved from the contrib/fixinc directory.
[pf3gnuchains/gcc-fork.git] / gcc / fixinc / fixincl.c
1 /*
2  * $Id: fixincl.c,v 1.2 1998/12/16 21:19:03 law Exp $
3  *
4  * Install modified versions of certain ANSI-incompatible system header
5  * files which are fixed to work correctly with ANSI C and placed in a
6  * directory that GNU C will search.
7  *
8  * See README-fixinc for more information.
9  *
10  *  fixincl is free software.
11  *  
12  *  You may redistribute it and/or modify it under the terms of the
13  *  GNU General Public License, as published by the Free Software
14  *  Foundation; either version 2, or (at your option) any later version.
15  *  
16  *  fixincl is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  *  See the GNU General Public License for more details.
20  *  
21  *  You should have received a copy of the GNU General Public License
22  *  along with fixincl.  See the file "COPYING".  If not,
23  *  write to:  The Free Software Foundation, Inc.,
24  *             59 Temple Place - Suite 330,
25  *             Boston,  MA  02111-1307, USA.
26  */
27
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <string.h>
38 #include <fcntl.h>
39 #include <ctype.h>
40
41 #include "regex.h"
42 #include "server.h"
43
44 #define tSCC static const char
45 #define tCC  const char
46 #define tSC  static char
47
48 typedef int tSuccess;
49
50 #define FAILURE  ((tSuccess)-1)
51 #define SUCCESS  ((tSuccess) 0)
52 #define PROBLEM  ((tSuccess) 1)
53
54 #define SUCCEEDED( p )     ((p) == SUCCESS)
55 #define SUCCESSFUL( p )    SUCCEEDED( p )
56 #define FAILED( p )        ((p) <  SUCCESS)
57 #define HADGLITCH( p )     ((p) >  SUCCESS)
58
59 #define NUL '\0'
60
61 typedef enum
62   {
63     TT_TEST, TT_EGREP, TT_NEGREP
64   }
65 teTestType;
66
67 typedef struct test_desc tTestDesc;
68
69 struct test_desc
70   {
71     teTestType type;
72     const char *pzTest;
73     regex_t *pTestRegex;
74   };
75
76 typedef struct patch_desc tPatchDesc;
77
78 #define FD_MACH_ONLY      0x0000
79 #define FD_MACH_IFNOT     0x0001
80 #define FD_SKIP_TEST      0x8000
81
82 typedef struct fix_desc tFixDesc;
83 struct fix_desc
84   {
85     const char*   pzFixName;     /* Name of the fix */
86     const char*   pzFileList;    /* List of files it applies to */
87     const char**  papzMachs;     /* List of machine/os-es it applies to */
88     regex_t*      pListRegex;
89     int           testCt;
90     int           fdFlags;
91     tTestDesc*    pTestDesc;
92     const char**  papzPatchArgs;
93   };
94
95 char *pzDestDir   = (char *) NULL;
96 char *pzSrcDir    = (char *) NULL;
97 char *pzMachine   = (char *) NULL;
98
99 pid_t chainHead = (pid_t) - 1;
100
101 const char zInclQuote[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
102 regex_t inclQuoteRegex;
103
104 char zFileNameBuf[0x8000];
105
106 char *loadFile (const char *pzFile);
107 void process (char *data, const char *dir, const char *file);
108 void runCompiles (void);
109
110 #include "fixincl.x"
111
112
113 int
114 main (argc, argv)
115      int argc;
116      char **argv;
117 {
118   static const char zGnuLib[] =
119   "This file is part of the GNU C Library";
120   static const char zVarNotFound[] =
121       "fixincl ERROR:  %s environment variable not defined\n";
122
123 #ifndef NO_BOGOSITY_LIMITS
124 # define BOGUS_LIMIT 256
125   size_t loopCt;
126 #endif
127
128   char *apzNames[BOGUS_LIMIT];
129   size_t fileNameCt;
130
131   if (argc != 1)
132     {
133       if (argc != 2)
134         {
135           fputs ("fixincl ERROR:  too many command line arguments\n", stderr);
136           exit (EXIT_FAILURE);
137         }
138
139       if (strcmp (argv[1], "-v") == 0)
140         {
141           fputs ("$Id: fixincl.c,v 1.2 1998/12/16 21:19:03 law Exp $\n", stderr);
142           exit (EXIT_SUCCESS);
143         }
144
145       freopen (argv[1], "r", stdin);
146     }
147
148   {
149     static const char zVar[] = "TARGET_MACHINE";
150     pzMachine = getenv( zVar );
151     if (pzMachine == (char *)NULL)
152       {
153         fprintf( stderr, zVarNotFound, zVar );
154         exit (EXIT_FAILURE);
155       }
156   }
157
158   {
159     static const char zVar[] = "DESTDIR";
160     pzDestDir = getenv( zVar );
161     if (pzDestDir == (char *)NULL)
162       {
163         fprintf( stderr, zVarNotFound, zVar );
164         exit (EXIT_FAILURE);
165       }
166   }
167
168   {
169     static const char zVar[] = "SRCDIR";
170     pzSrcDir = getenv( zVar );
171     if (pzSrcDir == (char *)NULL)
172       {
173         fprintf( stderr, zVarNotFound, zVar );
174         exit (EXIT_FAILURE);
175       }
176   }
177
178   runCompiles ();
179
180   signal ( SIGQUIT, SIG_IGN );
181   signal ( SIGIOT,  SIG_IGN );
182   signal ( SIGPIPE, SIG_IGN );
183   signal ( SIGALRM, SIG_IGN );
184   signal ( SIGTERM, SIG_IGN );
185   signal ( SIGCHLD, SIG_IGN );
186
187 #ifndef NO_BOGOSITY_LIMITS
188   for (;;)
189     {
190       char *pzBuf;
191       pid_t child;
192
193       /*
194        *  Only the parent process can read from stdin without
195        *  confusing the world.  (How does the child tell the
196        *  parent to skip forward?  Pipes and files behave differently.)
197        */
198       for (fileNameCt = 0, pzBuf = zFileNameBuf;
199            (fileNameCt < BOGUS_LIMIT)
200            && (pzBuf
201                < (zFileNameBuf + sizeof (zFileNameBuf) - MAXPATHLEN));
202         )
203         {
204
205           if (fgets (pzBuf, MAXPATHLEN, stdin) == (char *) NULL)
206             break;
207           while (isspace (*pzBuf))
208             pzBuf++;
209           apzNames[fileNameCt++] = pzBuf;
210           pzBuf += strlen (pzBuf);
211           while (isspace (pzBuf[-1]))
212             pzBuf--;
213           *pzBuf++ = '\0';
214         }
215
216       if (fileNameCt == 0)
217         return EXIT_SUCCESS;
218
219       child = fork ();
220       if (child == NULLPROCESS)
221         break;
222
223       if (child == NOPROCESS)
224         {
225           fprintf (stderr, "Error %d (%s) forking in main\n",
226                    errno, strerror (errno));
227           exit (EXIT_FAILURE);
228         }
229
230       waitpid (child, (int *) NULL, 0);
231     }
232 #else
233 #error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"
234 #endif
235
236   /*
237    *  For every file specified in stdandard in
238    *  (except as throttled for bogus reasons)...
239    */
240   for (loopCt = 0; loopCt < fileNameCt; loopCt++)
241     {
242       char *pzData;
243       char *pzFile = apzNames[loopCt];
244
245       if (access (pzFile, R_OK) != 0)
246         {
247           int erno = errno;
248           fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
249                    pzFile, getcwd ((char *) NULL, MAXPATHLEN),
250                    erno, strerror (erno));
251         }
252       else if (pzData = loadFile (pzFile),
253                (pzData != (char *) NULL))
254         {
255
256           if (strstr (pzData, zGnuLib) == (char *) NULL)
257             process (pzData, pzDestDir, pzFile);
258
259           free ((void *) pzData);
260         }
261     }
262
263   return EXIT_SUCCESS;
264 }
265
266
267 char *
268 loadFile (pzFile)
269      const char *pzFile;
270 {
271   char *pzDta;
272   size_t fileSize;
273
274   {
275     struct stat stbf;
276     if (stat (pzFile, &stbf) != 0)
277       {
278         fprintf (stderr, "error %d (%s) stat-ing %s\n",
279                  errno, strerror (errno), pzFile);
280         return (char *) NULL;
281       }
282     fileSize = stbf.st_size;
283   }
284   if (fileSize == 0)
285     return (char *) NULL;
286
287   pzDta = (char *) malloc ((fileSize + 16) & ~0x00F);
288   if (pzDta == (char *) NULL)
289     {
290       fprintf (stderr, "error:  could not malloc %d bytes\n",
291                fileSize);
292       exit (EXIT_FAILURE);
293     }
294
295   {
296     FILE *fp = fopen (pzFile, "r");
297     size_t sizeLeft = fileSize;
298     char *readPtr = pzDta;
299
300     if (fp == (FILE *) NULL)
301       {
302         fprintf (stderr, "error %d (%s) opening %s\n", errno,
303                  strerror (errno), pzFile);
304         free ((void *) pzDta);
305         return (char *) NULL;
306       }
307
308     do
309       {
310         size_t sizeRead = fread ((void *) readPtr, 1, sizeLeft, fp);
311
312         if (sizeRead == 0)
313           {
314             if (feof (fp))
315               break;
316
317             if (ferror (fp))
318               {
319                 fprintf (stderr, "error %d (%s) reading %s\n", errno,
320                          strerror (errno), pzFile);
321                 free ((void *) pzDta);
322                 fclose (fp);
323                 return (char *) NULL;
324               }
325           }
326
327         readPtr += sizeRead;
328         sizeLeft -= sizeRead;
329       }
330     while (sizeLeft != 0);
331
332     *readPtr = '\0';
333     fclose (fp);
334     return pzDta;
335   }
336 }
337
338
339 void
340 runCompiles ()
341 {
342   tSCC zBadComp[] = "fixincl ERROR:  cannot compile %s regex for %s\n"
343     "\texpr = `%s'\n" "\terror %s\n";
344   tFixDesc *pFD = fixDescList;
345   int fixCt = FIX_COUNT;
346   tTestDesc *pTD;
347   int tstCt;
348   int reCt = REGEX_COUNT;
349   const char *pzErr;
350   regex_t *pRegex = (regex_t *) malloc (REGEX_COUNT * sizeof (regex_t));
351
352   if (pRegex == (regex_t *) NULL)
353     {
354       fprintf (stderr, "fixincl ERROR:  cannot allocate %d bytes for regex\n",
355                REGEX_COUNT * sizeof (regex_t));
356       exit (EXIT_FAILURE);
357     }
358
359   re_set_syntax (RE_SYNTAX_EGREP);
360   pzErr = re_compile_pattern (zInclQuote, strlen (zInclQuote),
361                               &inclQuoteRegex);
362   if (pzErr != (char *) NULL)
363     {
364       fprintf (stderr, zBadComp, "quoted include", "runCompiles",
365                zInclQuote, pzErr);
366       exit (EXIT_FAILURE);
367     }
368
369   /*
370    *  FOR every fixup, ...
371    */
372   do
373     {
374       pTD = pFD->pTestDesc;
375       tstCt = pFD->testCt;
376
377       if (pFD->papzMachs != (const char**)NULL) {
378         const char** papzMachs = pFD->papzMachs;
379         char*        pz = zFileNameBuf;
380         char*        pzSep = "";
381         tCC*         pzIfTrue;
382         tCC*         pzIfFalse;
383         tSCC         zSkip[] = "skip";
384         tSCC         zRun[]  = "run";
385
386         sprintf( pz, "case %s in\n", pzMachine );
387         pz += strlen( pz );
388
389         if (pFD->fdFlags & FD_MACH_IFNOT) {
390           pzIfTrue  = zSkip;
391           pzIfFalse = zRun;
392         } else {
393           pzIfTrue  = zRun;
394           pzIfFalse = zSkip;
395         }
396
397         for (;;) {
398           const char* pzMach = *(papzMachs++);
399           if (pzMach == (const char*)NULL)
400             break;
401           sprintf( pz, "%s  %s", pzSep, pzMach );
402           pz += strlen( pz );
403           pzSep = " | \\\n";
404         }
405         sprintf( pz, " )\n    echo %s ;;\n  * )\n    echo %s ;;\nesac",
406                  pzIfTrue, pzIfFalse );
407         pz = runShell( zFileNameBuf );
408         if (*pz == 's') {
409           pFD->fdFlags |= FD_SKIP_TEST;
410           continue;
411         }
412       }
413
414       /*
415        *  FOR every test for the fixup, ...
416        */
417       while (--tstCt >= 0)
418         {
419           switch (pTD->type)
420             {
421             case TT_EGREP:
422             case TT_NEGREP:
423               if (--reCt < 0)
424                 {
425                   fputs ("out of RE's\n", stderr);
426                   exit (EXIT_FAILURE);
427                 }
428
429               pTD->pTestRegex = pRegex++;
430               pzErr = re_compile_pattern (pTD->pzTest,
431                                           strlen (pTD->pzTest),
432                                           pTD->pTestRegex);
433               if (pzErr != (char *) NULL)
434                 {
435                   fprintf (stderr, zBadComp, "select test", pFD->pzFixName,
436                            pTD->pzTest, pzErr);
437                   exit (EXIT_FAILURE);
438                 }
439             }
440           pTD++;
441         }
442     }
443   while (pFD++, --fixCt > 0);
444 }
445
446
447 FILE *
448 createFile (pzFile)
449      const char *pzFile;
450 {
451   int fd;
452   FILE *pf;
453   char fname[MAXPATHLEN];
454
455   sprintf (fname, "%s/%s", pzDestDir, pzFile);
456   unlink (fname);
457
458   fd = open (fname, O_WRONLY | O_CREAT);
459
460   if ((fd < 0) && (errno == ENOENT))
461     {
462       char *pzDir = strchr (fname + 1, '/');
463       struct stat stbf;
464
465       while (pzDir != (char *) NULL)
466         {
467           *pzDir = NUL;
468           if (stat (fname, &stbf) < 0)
469             {
470               mkdir (fname, S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP
471                      | S_IROTH | S_IXOTH);
472             }
473
474           *pzDir = '/';
475           pzDir = strchr (pzDir + 1, '/');
476         }
477       fd = open (fname, O_WRONLY | O_CREAT);
478     }
479   if (fd < 0)
480     {
481       fprintf (stderr, "Error %d (%s) creating %s\n",
482                errno, strerror (errno), fname);
483       exit (EXIT_FAILURE);
484     }
485   fprintf (stderr, "Fixed:  %s\n", pzFile);
486   pf = fdopen (fd, "w");
487
488 #ifdef LATER
489   {
490     static const char zHdr[] =
491     "/*\n"
492     " *  DO NOT EDIT THIS FILE.\n"
493     " *\n"
494     " *  It has been auto-edited by fixincludes from /usr/include/%s\n"
495     " *  This had to be done to correct non-standard usages in the\n"
496     " *  original, manufacturer supplied header file.\n"
497     " */\n\n";
498
499     fprintf (pf, zHdr, pzFile);
500   }
501 #endif
502   return pf;
503 }
504
505 tSuccess
506 testTest (pTest, pzFile)
507      tTestDesc *pTest;
508      char*      pzFile;
509 {
510   char *pzRes;
511   tSuccess res = FAILURE;
512
513   static char zCmdBuf[4096];
514   tSCC zCmdFmt[] = "file=%s\nif ( test %s ) > /dev/null 2>&1\n"
515   "then echo TRUE\n" "else echo FALSE\n" "fi";
516
517   sprintf (zCmdBuf, zCmdFmt, pzFile, pTest->pzTest);
518   pzRes = runShell (zCmdBuf);
519   if (*pzRes == 'T')
520     res = SUCCESS;
521   free ((void *) pzRes);
522   return res;
523 }
524
525
526 tSuccess
527 egrepTest (pzDta, pTest)
528      char *pzDta;
529      tTestDesc *pTest;
530 {
531   regmatch_t match;
532 #ifndef NO_BOGOSITY
533   if (pTest->pTestRegex == 0)
534     fprintf (stderr, "fixincl ERROR RE not compiled:  `%s'\n", pTest->pzTest);
535 #endif
536   if (regexec (pTest->pTestRegex, pzDta, 1, &match, 0) == 0)
537     return SUCCESS;
538   return FAILURE;
539 }
540
541
542
543 void
544 extractQuotedFiles (pzDta, pzFile, pMatch)
545      char *pzDta;
546      const char *pzFile;
547      regmatch_t *pMatch;
548 {
549   char *pzDirEnd = strrchr (pzFile, '/');
550   char *pzInclQuot = pzDta;
551
552   fprintf (stderr, "Quoted includes in %s\n", pzFile);
553
554   /*
555    *  Set "pzFile" to point to the containing subdirectory of the source
556    *  If there is none, then it is in our current direcory, ".".
557    */
558   if (pzDirEnd == (char *) NULL)
559     pzFile = ".";
560   else
561     *pzDirEnd = '\0';
562
563   for (;;)
564     {
565       pzInclQuot += pMatch->rm_so;
566
567       /*
568        *  Skip forward to the included file name
569        */
570       while (isspace (*pzInclQuot))
571         pzInclQuot++;
572       while (isspace (*++pzInclQuot));
573       pzInclQuot += sizeof ("include") - 1;
574       while (*pzInclQuot++ != '"');
575
576       /*
577        *  Print the source directory and the subdirectory of the file
578        *  in question.
579        */
580       printf ("%s  %s/", pzSrcDir, pzFile);
581       pzDirEnd = pzInclQuot;
582
583       /*
584        *  Append to the directory the relative path of the desired file
585        */
586       while (*pzInclQuot != '"')
587         putc (*pzInclQuot++, stdout);
588
589       /*
590        *  Now print the destination directory appended with the relative
591        *  path of the desired file
592        */
593       printf ("  %s/%s/", pzDestDir, pzFile);
594       while (*pzDirEnd != '"')
595         putc (*pzDirEnd++, stdout);
596
597       /*
598        *  End of entry
599        */
600       putc ('\n', stdout);
601
602       /*
603        *  Find the next entry
604        */
605       if (regexec (&inclQuoteRegex, pzInclQuot, 1, pMatch, 0) != 0)
606         break;
607     }
608 }
609
610
611 /*
612  *  Process the potential fixes for a particular include file
613  */
614 void
615 process (pzDta, pzDir, pzFile)
616      char *pzDta;
617      const char *pzDir;
618      const char *pzFile;
619 {
620   static char zEnvFile[1024] =
621     {"file="};
622   tFixDesc *pFD = fixDescList;
623   int todoCt = FIX_COUNT;
624   tFdPair fdp =
625     {-1, -1};
626
627   /*
628    *  IF this is the first time through,
629    *  THEN put the 'file' environment variable into the environment.
630    *       This is used by some of the subject shell scripts and tests.
631    */
632   if (zEnvFile[5] == NUL)
633     putenv (zEnvFile);
634
635   /*
636    *  Ghastly as it is, this actually updates the value of the variable:
637    *
638    *    putenv(3C)             C Library Functions             putenv(3C)
639    *
640    *    DESCRIPTION
641    *         putenv() makes the value of the  environment  variable  name
642    *         equal  to value by altering an existing variable or creating
643    *         a new one.  In either case, the string pointed to by  string
644    *         becomes part of the environment, so altering the string will
645    *         change the environment.  string points to a  string  of  the
646    *         form  ``name=value.''  The space used by string is no longer
647    *         used once a new string-defining name is passed to putenv().
648    */
649   strcpy (zEnvFile + 5, pzFile);
650   chainHead = NOPROCESS;
651
652   /*
653    *  For every fix in our fix list, ...
654    */
655   for (; todoCt > 0; pFD++, todoCt--)
656     {
657       tTestDesc *pTD;
658       int tstCt;
659       tSuccess egrepRes;
660
661       if (pFD->fdFlags & FD_SKIP_TEST)
662         continue;
663
664       /*
665        *  IF there is a file name restriction,
666        *  THEN ensure the current file name matches one in the pattern
667        */
668       if (pFD->pzFileList != (char *) NULL)
669         {
670           const char *pzFil = pzFile;
671           const char *pzScn = pFD->pzFileList;
672           size_t nmLen;
673
674           while ((pzFil[0] == '.') && (pzFil[1] == '/'))
675             pzFil += 2;
676           nmLen = strlen (pzFil);
677
678           for (;;)
679             {
680               pzScn = strstr (pzScn + 1, pzFil);
681               if (pzScn == (char *) NULL)
682                 goto nextFix;
683
684               if ((pzScn[-1] == '|') && (pzScn[nmLen] == '|'))
685                 break;
686             }
687         }
688
689       egrepRes = PROBLEM;
690
691       /*
692        *  IF there are no tests
693        *  THEN we always run the fixup
694        */
695       for (pTD = pFD->pTestDesc, tstCt = pFD->testCt;
696            tstCt-- > 0;
697            pTD++)
698         {
699           switch (pTD->type)
700             {
701             case TT_TEST:
702               /*
703                *  IF *any* of the shell tests fail,
704                *  THEN do not process the fix.
705                */
706               if (!SUCCESSFUL (testTest (pTD, pzFile)))
707                 goto nextFix;
708               break;
709
710             case TT_EGREP:
711               /*
712                *  IF       we have not had a successful egrep test
713                *    *AND*  this test does not pass,
714                *  THEN mark the egrep test as failing.  It starts
715                *       out as a "PROBLEM", meaning that if we do not
716                *       encounter any egrep tests, then we will let it pass.
717                */
718               if ((!SUCCESSFUL (egrepRes))
719                   && (!SUCCESSFUL (egrepTest (pzDta, pTD))))
720
721                 egrepRes = FAILURE;
722
723               break;
724
725             case TT_NEGREP:
726               /*
727                *  IF *any* of the negative egrep tests fail,
728                *  THEN do not process the fix.
729                */
730               if (SUCCESSFUL (egrepTest (pzDta, pTD)))
731                 goto nextFix;
732               break;
733             }
734         }
735
736       /*
737        *  IF there were no egrep tests *OR* at least one passed, ...
738        */
739       if (!FAILED (egrepRes))
740         {
741           fprintf (stderr, "Applying %-32s to %s\n",
742                    pFD->pzFixName, pzFile);
743
744           if (fdp.readFd == -1)
745             {
746               fdp.readFd = open (pzFile, O_RDONLY);
747               if (fdp.readFd < 0)
748                 {
749                   fprintf (stderr, "Error %d (%s) opening %s\n", errno,
750                            strerror (errno), pzFile);
751                   exit (EXIT_FAILURE);
752                 }
753             }
754
755           for (;;)
756             {
757               int newFd = chainOpen (fdp.readFd,
758                                      (tpChar *) pFD->papzPatchArgs,
759                                      (chainHead == -1)
760                                      ? &chainHead : (pid_t *) NULL);
761               if (newFd != -1)
762                 {
763                   fdp.readFd = newFd;
764                   break;
765                 }
766
767               fprintf (stderr, "Error %d (%s) starting filter process "
768                        "for %s\n", errno, strerror (errno),
769                        pFD->pzFixName);
770
771               if (errno != EAGAIN)
772                 exit (EXIT_FAILURE);
773               sleep (1);
774             }
775         }
776
777     nextFix:;
778     }
779
780   /*
781    *  IF after all the tests we did not start any patch programs,
782    *  THEN quit now.
783    */
784   if (fdp.readFd < 0)
785     return;
786
787   {
788     FILE *inFp = fdopen (fdp.readFd, "r");
789     FILE *oFp = (FILE *) NULL;
790     char *pzCmp = pzDta;
791
792     for (;;)
793       {
794         int ch;
795
796         ch = getc (inFp);
797         if (ch == EOF)
798           break;
799
800         if (oFp != (FILE *) NULL)
801           putc (ch, oFp);
802
803         else if (ch != *pzCmp)
804           {
805             oFp = createFile (pzFile);
806             if (pzCmp != pzDta)
807               {
808                 char c = *pzCmp;
809                 *pzCmp = NUL;
810                 fputs (pzDta, oFp);
811                 *pzCmp = c;
812               }
813             putc (ch, oFp);
814
815           }
816         else
817           pzCmp++;
818       }
819
820     if (oFp != (FILE *) NULL)
821       {
822         regmatch_t match;
823
824         fchmod (fileno (oFp), S_IRUSR | S_IRGRP | S_IROTH);
825         fclose (oFp);
826         if (regexec (&inclQuoteRegex, pzDta, 1, &match, 0) == 0)
827           extractQuotedFiles (pzDta, pzFile, &match);
828       }
829
830     fclose (inFp);
831   }
832
833   close (fdp.readFd);
834 }