2 /* Install modified versions of certain ANSI-incompatible system header
3 files which are fixed to work correctly with ANSI C and placed in a
4 directory that GNU C will search.
6 Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
8 This file is part of GNU CC.
10 GNU CC is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 GNU CC is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU CC; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
25 #include "auto-host.h"
27 #include <sys/types.h>
28 #include <sys/param.h>
30 #ifdef HAVE_SYS_WAIT_H
46 #include "gnu-regex.h"
49 static const char program_id[] = "fixincl version 1.0";
51 #define MINIMUM_MAXIMUM_LINES 128
53 /* If this particular system's header files define the macro `MAXPATHLEN',
54 we happily take advantage of it; otherwise we use a value which ought
55 to be large enough. */
57 # define MAXPATHLEN 4096
59 #define NAME_TABLE_SIZE (MINIMUM_MAXIMUM_LINES * MAXPATHLEN)
63 #define tSCC static const char
64 #define tCC const char
65 #define tSC static char
67 typedef int t_success;
73 #define SUCCEEDED(p) ((p) == SUCCESS)
74 #define SUCCESSFUL(p) SUCCEEDED (p)
75 #define FAILED(p) ((p) < SUCCESS)
76 #define HADGLITCH(p) ((p) > SUCCESS)
82 Each fix may have associated tests that determine
83 whether the fix needs to be applied or not.
84 Each test has a type (from the te_test_type enumeration);
85 associated test text; and, if the test is TT_EGREP or
86 the negated form TT_NEGREP, a pointer to the compiled
87 version of the text string.
92 TT_TEST, TT_EGREP, TT_NEGREP
95 typedef struct test_desc tTestDesc;
100 const char *pz_test_text;
101 regex_t *p_test_regex;
104 typedef struct patch_desc tPatchDesc;
108 Everything you ever wanted to know about how to apply
109 a particular fix (which files, how to qualify them,
110 how to actually make the fix, etc...)
113 #define FD_MACH_ONLY 0x0000
114 #define FD_MACH_IFNOT 0x0001
115 #define FD_SKIP_TEST 0x8000
117 typedef struct fix_desc tFixDesc;
120 const char* fix_name; /* Name of the fix */
121 const char* file_list; /* List of files it applies to */
122 const char** papz_machs; /* List of machine/os-es it applies to */
126 tTestDesc* p_test_desc;
127 const char** patch_args;
130 /* Working environment strings. Essentially, invocation 'options'. */
131 char *pz_dest_dir = NULL;
132 char *pz_src_dir = NULL;
133 char *pz_machine = NULL;
134 char *pz_find_base = NULL;
135 int find_base_len = 0;
137 pid_t process_chain_head = (pid_t) -1;
139 const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
140 regex_t incl_quote_re;
142 char *load_file _P_((const char *));
143 void process _P_((char *, const char *));
144 void run_compiles ();
145 void wait_for_pid _P_(( pid_t ));
150 /* * * * * * * * * * * * * * * * * * *
159 static const char gnu_lib_mark[] =
160 "This file is part of the GNU C Library";
162 #ifndef NO_BOGOSITY_LIMITS
163 # define BOGUS_LIMIT MINIMUM_MAXIMUM_LINES
167 char *apz_names[BOGUS_LIMIT];
170 /* Before anything else, ensure we can allocate our file name buffer. */
171 file_name_buf = (char *) malloc (NAME_TABLE_SIZE);
172 if (file_name_buf == (char *) NULL)
174 fprintf (stderr, "fixincl cannot allocate 0x%08X bytes\n",
185 if (strcmp (argv[1], "-v") == 0)
187 static const char zFmt[] = "echo '%s'";
189 /* The 'version' option is really used to test that:
190 1. The program loads correctly (no missing libraries)
191 2. we can correctly run our server shell process
192 3. that we can compile all the regular expressions.
195 sprintf (file_name_buf, zFmt, program_id);
196 fputs (file_name_buf + 5, stdout);
197 exit (strcmp (run_shell (file_name_buf), program_id));
199 freopen (argv[1], "r", stdin);
203 fputs ("fixincl ERROR: too many command line arguments\n", stderr);
209 #ifndef NO_BOGOSITY_LIMITS
210 /* Some systems only allow so many calls to fork(2).
211 This is inadequate for this program. Consequently,
212 we must let a grandfather process spawn children
213 that then spawn all the processes that do the real work.
220 char *pz_buf = file_name_buf;
222 /* Only the parent process can read from stdin without confusing
223 the world. (How does the child tell the parent to skip
224 forward? Pipes and files behave differently.) */
226 while ( (file_name_ct < BOGUS_LIMIT)
227 && (pz_buf < (file_name_buf + NAME_TABLE_SIZE - MAXPATHLEN)))
229 if (fgets (pz_buf, MAXPATHLEN, stdin) == (char *) NULL)
231 while (isspace (*pz_buf))
233 if ((*pz_buf == '\0') || (*pz_buf == '#'))
235 apz_names[file_name_ct++] = pz_buf;
236 pz_buf += strlen (pz_buf);
237 while (isspace (pz_buf[-1]))
243 /* IF we did not get any files this time thru
244 THEN we must be done. */
245 if (file_name_ct == 0)
252 pid_t child = fork ();
253 if (child == NULLPROCESS)
256 if (child == NOPROCESS)
258 fprintf (stderr, "Error %d (%s) forking in main\n",
259 errno, strerror (errno));
264 fprintf (stderr, "Waiting for %d to complete %d files\n",
265 child, file_name_ct);
268 wait_for_pid( child, file_name_ct );
272 #error "NON-BOGUS LIMITS NOT SUPPORTED?!?!"
276 Here we are the child of the grandparent process. The parent
277 of all the little fixup processes. We ignore the deaths of
280 signal (SIGCLD, SIG_IGN);
282 /* For every file specified in stdandard in
283 (except as throttled for bogus reasons)...
285 for (loop_ct = 0; loop_ct < file_name_ct; loop_ct++)
288 char *pz_file_name = apz_names[loop_ct];
290 if (access (pz_file_name, R_OK) != 0)
293 fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
294 pz_file_name, getcwd ((char *) NULL, MAXPATHLEN),
295 erno, strerror (erno));
297 else if (pz_data = load_file (pz_file_name), (pz_data != (char *) NULL))
299 if (strstr (pz_data, gnu_lib_mark) == (char *) NULL)
300 process (pz_data, pz_file_name);
301 free ((void *) pz_data);
309 /* * * * * * * * * * * * */
314 static const char var_not_found[] =
315 "fixincl ERROR: %s environment variable not defined\n";
318 static const char var[] = "TARGET_MACHINE";
319 pz_machine = getenv (var);
320 if (pz_machine == (char *) NULL)
322 fprintf (stderr, var_not_found, var);
328 static const char var[] = "DESTDIR";
329 pz_dest_dir = getenv (var);
330 if (pz_dest_dir == (char *) NULL)
332 fprintf (stderr, var_not_found, var);
338 static const char var[] = "SRCDIR";
339 pz_src_dir = getenv (var);
340 if (pz_src_dir == (char *) NULL)
342 fprintf (stderr, var_not_found, var);
348 static const char var[] = "FIND_BASE";
349 pz_find_base = getenv (var);
350 if (pz_find_base == (char *) NULL)
352 fprintf (stderr, var_not_found, var);
355 find_base_len = strlen( pz_find_base );
358 /* Compile all the regular expressions now.
359 That way, it is done only once for the whole run.
363 signal (SIGQUIT, SIG_IGN);
364 signal (SIGIOT, SIG_IGN);
365 signal (SIGPIPE, SIG_IGN);
366 signal (SIGALRM, SIG_IGN);
367 signal (SIGTERM, SIG_IGN);
370 Make sure that if we opened a server process, we close it now.
371 This is the grandparent process. We don't need the server anymore
372 and our children should make their own. */
375 (void)wait ( (int*)NULL );
378 /* * * * * * * * * * * * *
380 wait_for_pid - Keep calling `wait(2)' until it returns
381 the process id we are looking for. Not every system has
382 `waitpid(2)'. We also ensure that the children exit with success. */
385 wait_for_pid( pid_t child, int file_name_ct )
389 pid_t dead_kid = wait (&status);
391 if (dead_kid == child)
393 if (! WIFEXITED( status ))
395 fprintf (stderr, "child process %d is hung on signal %d\n",
396 child, WSTOPSIG( status ));
399 if (WEXITSTATUS( status ) != 0)
401 fprintf (stderr, "child process %d exited with status %d\n",
402 child, WEXITSTATUS( status ));
405 break; /* normal child completion */
409 IF there is an error, THEN see if it is retryable.
410 If it is not retryable, then break out of this loop. */
411 if (dead_kid == NOPROCESS)
419 fprintf (stderr, "Error %d (%s) waiting for %d to finish\n",
420 errno, strerror( errno ), child );
423 case ECHILD: /* no children to wait for?? */
431 /* * * * * * * * * * * * *
433 load_file loads all the contents of a file into malloc-ed memory.
434 Its argument is the name of the file to read in; the returned
435 result is the NUL terminated contents of the file. The file
436 is presumed to be an ASCII text file containing no NULs. */
438 load_file (pz_file_name)
439 const char *pz_file_name;
447 if (stat (pz_file_name, &stbf) != 0)
449 fprintf (stderr, "error %d (%s) stat-ing %s\n",
450 errno, strerror (errno), pz_file_name);
451 return (char *) NULL;
453 file_size = stbf.st_size;
456 return (char *) NULL;
458 pz_data = (char *) malloc ((file_size + 16) & ~0x00F);
459 if (pz_data == (char *) NULL)
461 fprintf (stderr, "error: could not malloc %d bytes\n",
467 FILE *fp = fopen (pz_file_name, "r");
468 size_t size_left = file_size;
469 char *read_ptr = pz_data;
471 if (fp == (FILE *) NULL)
473 fprintf (stderr, "error %d (%s) opening %s\n", errno,
474 strerror (errno), pz_file_name);
475 free ((void *) pz_data);
476 return (char *) NULL;
481 size_t sizeRead = fread ((void *) read_ptr, 1, size_left, fp);
492 fprintf (stderr, "error %d (%s) reading %s\n", err,
493 strerror (err), pz_file_name);
494 free ((void *) pz_data);
496 return (char *) NULL;
500 read_ptr += sizeRead;
501 size_left -= sizeRead;
503 while (size_left != 0);
512 /* * * * * * * * * * * * *
514 run_compiles run all the regexp compiles for all the fixes once.
519 tSCC z_bad_comp[] = "fixincl ERROR: cannot compile %s regex for %s\n\
520 \texpr = `%s'\n\terror %s\n";
521 tFixDesc *p_fixd = fixDescList;
522 int fix_ct = FIX_COUNT;
525 int re_ct = REGEX_COUNT;
527 regex_t *p_re = (regex_t *) malloc (REGEX_COUNT * sizeof (regex_t));
529 if (p_re == (regex_t *) NULL)
531 fprintf (stderr, "fixincl ERROR: cannot allocate %d bytes for regex\n",
532 REGEX_COUNT * sizeof (regex_t));
536 /* Make sure re_compile_pattern does not stumble across invalid
539 memset ( (void*)p_re, '\0', REGEX_COUNT * sizeof (regex_t) );
540 memset ( (void*)&incl_quote_re, '\0', sizeof (regex_t) );
542 /* The patterns we search for are all egrep patterns.
543 In the shell version of this program, we invoke egrep
544 with the supplied pattern. Here, we will run
545 re_compile_pattern, but it must be using the same rules. */
547 re_set_syntax (RE_SYNTAX_EGREP);
548 pz_err = re_compile_pattern (incl_quote_pat, sizeof (incl_quote_pat)-1,
550 if (pz_err != (char *) NULL)
552 fprintf (stderr, z_bad_comp, "quoted include", "run_compiles",
553 incl_quote_pat, pz_err);
557 /* FOR every fixup, ... */
560 p_test = p_fixd->p_test_desc;
561 test_ct = p_fixd->test_ct;
563 /* IF the machine type pointer is not NULL (we are not in test mode)
564 AND this test is for or not done on particular machines
567 if ( (pz_machine != NULL)
568 && (p_fixd->papz_machs != (const char**) NULL) )
570 const char **papz_machs = p_fixd->papz_machs;
571 char *pz = file_name_buf;
575 tSCC skip[] = "skip";
578 /* Construct a shell script that looks like this:
580 case our-cpu-platform-os in
581 tests-cpu-platform-os-pattern )
587 where 'run' and 'skip' may be reversed, depending on
588 the sense of the test. */
590 sprintf (pz, "case %s in\n", pz_machine);
593 if (p_fixd->fd_flags & FD_MACH_IFNOT)
604 /* FOR any additional machine names to test for,
605 insert the " | \\\n" glue and the machine pattern. */
609 const char* pz_mach = *(papz_machs++);
611 if (pz_mach == (const char*) NULL)
613 sprintf (pz, "%s %s", pz_sep, pz_mach);
617 sprintf (pz, " )\n echo %s ;;\n * )\n echo %s ;;\nesac",
618 pz_if_true, pz_if_false);
621 The result will start either with 's' or 'r'. */
625 pz = run_shell (file_name_buf);
630 p_fixd->fd_flags |= FD_SKIP_TEST;
636 /* FOR every test for the fixup, ... */
638 while (--test_ct >= 0)
640 switch (p_test->type)
644 /* You might consider putting the following under #ifdef.
645 The number of re's used is computed by autogen.
646 So, it is static and known at compile time. */
650 fputs ("out of RE's\n", stderr);
654 p_test->p_test_regex = p_re++;
655 pz_err = re_compile_pattern (p_test->pz_test_text,
656 strlen (p_test->pz_test_text),
657 p_test->p_test_regex);
658 if (pz_err != (char *) NULL)
660 fprintf (stderr, z_bad_comp, "select test", p_fixd->fix_name,
661 p_test->pz_test_text, pz_err);
668 while (p_fixd++, --fix_ct > 0);
672 /* * * * * * * * * * * * *
674 create_file Create the output modified file.
675 Input: the name of the file to create
676 Returns: a file pointer to the new, open file */
678 #define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
681 create_file (pz_file_name)
682 const char *pz_file_name;
686 char fname[MAXPATHLEN];
689 if (strncmp( pz_file_name, pz_find_base, find_base_len ) != 0)
691 fprintf (stderr, "Error: input file %s does not match %s/*\n",
692 pz_file_name, pz_find_base );
697 sprintf (fname, "%s/%s", pz_dest_dir, pz_file_name + find_base_len);
699 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
701 /* We may need to create the directories needed... */
702 if ((fd < 0) && (errno == ENOENT))
704 char *pz_dir = strchr (fname + 1, '/');
707 while (pz_dir != (char *) NULL)
710 if (stat (fname, &stbf) < 0)
712 mkdir (fname, S_IFDIR | S_IRWXU | S_IRGRP | S_IXGRP
713 | S_IROTH | S_IXOTH);
717 pz_dir = strchr (pz_dir + 1, '/');
720 /* Now, lets try the open again... */
721 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
725 fprintf (stderr, "Error %d (%s) creating %s\n",
726 errno, strerror (errno), fname);
729 fprintf (stderr, "Fixed: %s\n", pz_file_name);
730 pf = fdopen (fd, "w");
734 static const char hdr[] =
735 "/* DO NOT EDIT THIS FILE.\n\n"
736 " It has been auto-edited by fixincludes from /usr/include/%s\n"
737 " This had to be done to correct non-standard usages in the\n"
738 " original, manufacturer supplied header file. */\n\n";
740 fprintf (pf, hdr, pz_file_name);
747 /* * * * * * * * * * * * *
749 test_test make sure a shell-style test expression passes.
750 Input: a pointer to the descriptor of the test to run and
751 the name of the file that we might want to fix
752 Result: SUCCESS or FAILURE, depending on the result of the
753 shell script we run. */
756 test_test (p_test, pz_file_name)
762 if ( test %s ) > /dev/null 2>&1\n\
768 t_success res = FAILURE;
770 static char cmd_buf[4096];
772 sprintf (cmd_buf, cmd_fmt, pz_file_name, p_test->pz_test_text);
773 pz_res = run_shell (cmd_buf);
776 free ((void *) pz_res);
781 /* * * * * * * * * * * * *
783 egrep_test make sure an egrep expression is found in the file text.
784 Input: a pointer to the descriptor of the test to run and
785 the pointer to the contents of the file under suspicion
786 Result: SUCCESS if the pattern is found, FAILURE otherwise
788 The caller may choose 'FAILURE' as 'SUCCESS' if the sense of the test
792 egrep_test (pz_data, p_test)
799 if (p_test->p_test_regex == 0)
800 fprintf (stderr, "fixincl ERROR RE not compiled: `%s'\n",
801 p_test->pz_test_text);
803 if (regexec (p_test->p_test_regex, pz_data, 1, &match, 0) == 0)
809 /* * * * * * * * * * * * *
811 quoted_file_exists Make sure that a file exists before we emit
812 the file name. If we emit the name, our invoking shell will try
813 to copy a non-existing file into the destination directory. */
816 quoted_file_exists (pz_src_path, pz_file_path, pz_file)
821 char z[ MAXPATHLEN ];
823 sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
824 pz = z + strlen ( z );
827 char ch = *pz_file++;
837 if (stat (z, &s) != 0)
839 return S_ISREG( s.st_mode );
844 /* * * * * * * * * * * * *
848 The syntax, `#include "file.h"' specifies that the compiler is to
849 search the local directory of the current file before the include
850 list. Consequently, if we have modified a header and stored it in
851 another directory, any files that are included by that modified
852 file in that fashion must also be copied into this new directory.
853 This routine finds those flavors of #include and for each one found
856 1. source directory of the original file
857 2. the relative path file name of the #includ-ed file
858 3. the full destination path for this file
860 Input: the text of the file, the file name and a pointer to the
861 match list where the match information was stored.
862 Result: internally nothing. The results are written to stdout
863 for interpretation by the invoking shell */
867 extract_quoted_files (pz_data, pz_file_name, p_re_match)
869 const char *pz_file_name;
870 regmatch_t *p_re_match;
872 char *pz_dir_end = strrchr (pz_file_name, '/');
873 char *pz_incl_quot = pz_data;
875 fprintf (stderr, "Quoted includes in %s\n", pz_file_name);
877 /* Set "pz_file_name" to point to the containing subdirectory of the source
878 If there is none, then it is in our current directory, ".". */
880 if (pz_dir_end == (char *) NULL)
887 pz_incl_quot += p_re_match->rm_so;
889 /* Skip forward to the included file name */
890 while (isspace (*pz_incl_quot))
892 while (isspace (*++pz_incl_quot))
894 pz_incl_quot += sizeof ("include") - 1;
895 while (*pz_incl_quot++ != '"')
898 if (quoted_file_exists (pz_src_dir, pz_file_name, pz_incl_quot))
900 /* Print the source directory and the subdirectory
901 of the file in question. */
902 printf ("%s %s/", pz_src_dir, pz_file_name);
903 pz_dir_end = pz_incl_quot;
905 /* Append to the directory the relative path of the desired file */
906 while (*pz_incl_quot != '"')
907 putc (*pz_incl_quot++, stdout);
909 /* Now print the destination directory appended with the
910 relative path of the desired file */
911 printf (" %s/%s/", pz_dest_dir, pz_file_name);
912 while (*pz_dir_end != '"')
913 putc (*pz_dir_end++, stdout);
919 /* Find the next entry */
920 if (regexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
926 /* * * * * * * * * * * * *
928 Process the potential fixes for a particular include file.
929 Input: the original text of the file and the file's name
930 Result: none. A new file may or may not be created. */
933 process (pz_data, pz_file_name)
935 const char *pz_file_name;
937 static char env_current_file[1024] = { "file=" };
938 tFixDesc *p_fixd = fixDescList;
939 int todo_ct = FIX_COUNT;
940 t_fd_pair fdp = { -1, -1 };
941 int num_children = 0;
943 /* IF this is the first time through,
944 THEN put the 'file' environment variable into the environment.
945 This is used by some of the subject shell scripts and tests. */
947 if (env_current_file[5] == NUL)
948 putenv (env_current_file);
951 Ghastly as it is, this actually updates the value of the variable:
953 putenv(3C) C Library Functions putenv(3C)
956 putenv() makes the value of the environment variable name
957 equal to value by altering an existing variable or creating
958 a new one. In either case, the string pointed to by string
959 becomes part of the environment, so altering the string will
960 change the environment. string points to a string of the
961 form ``name=value.'' The space used by string is no longer
962 used once a new string-defining name is passed to putenv().
964 strcpy (env_current_file + 5, pz_file_name);
965 process_chain_head = NOPROCESS;
966 fprintf (stderr, "%-50s \r", pz_file_name );
967 /* For every fix in our fix list, ... */
968 for (; todo_ct > 0; p_fixd++, todo_ct--)
973 if (p_fixd->fd_flags & FD_SKIP_TEST)
976 /* IF there is a file name restriction,
977 THEN ensure the current file name matches one in the pattern */
979 if (p_fixd->file_list != (char *) NULL)
981 const char *pz_fname = pz_file_name;
982 const char *pz_scan = p_fixd->file_list;
985 while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
987 name_len = strlen (pz_fname);
991 pz_scan = strstr (pz_scan + 1, pz_fname);
992 /* IF we can't match the string at all,
994 if (pz_scan == (char *) NULL)
997 /* IF the match is surrounded by the '|' markers,
998 THEN we found a full match -- time to run the tests */
1000 if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|'))
1005 /* FOR each test, see if it fails.
1006 IF it does fail, then we go on to the next test */
1008 for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
1013 static const char z_test_fail[] =
1014 "%16s test %2d failed for %s\n";
1016 switch (p_test->type)
1019 if (!SUCCESSFUL (test_test (p_test, pz_file_name)))
1022 fprintf (stderr, z_test_fail, p_fixd->fix_name,
1023 p_fixd->test_ct - test_ct, pz_file_name);
1030 if (!SUCCESSFUL (egrep_test (pz_data, p_test)))
1033 fprintf (stderr, z_test_fail, p_fixd->fix_name,
1034 p_fixd->test_ct - test_ct, pz_file_name);
1041 if (SUCCESSFUL (egrep_test (pz_data, p_test)))
1044 fprintf (stderr, z_test_fail, p_fixd->fix_name,
1045 p_fixd->test_ct - test_ct, pz_file_name);
1053 fprintf (stderr, "Applying %-24s to %s\n",
1054 p_fixd->fix_name, pz_file_name);
1056 /* IF we do not have a read pointer,
1057 THEN this is the first fix for the current file.
1058 Open the source file. That will be used as stdin for
1059 the first fix. Any subsequent fixes will use the
1060 stdout descriptor of the previous fix as its stdin. */
1062 if (fdp.read_fd == -1)
1064 fdp.read_fd = open (pz_file_name, O_RDONLY);
1065 if (fdp.read_fd < 0)
1067 fprintf (stderr, "Error %d (%s) opening %s\n", errno,
1068 strerror (errno), pz_file_name);
1069 exit (EXIT_FAILURE);
1073 /* This loop should only cycle for 1/2 of one loop.
1074 "chain_open" starts a process that uses "fdp.read_fd" as
1075 its stdin and returns the new fd this process will use
1080 tSCC z_err[] = "Error %d (%s) starting filter process for %s\n";
1081 static int failCt = 0;
1082 int fd = chain_open (fdp.read_fd,
1083 (t_pchar *) p_fixd->patch_args,
1084 (process_chain_head == -1)
1085 ? &process_chain_head : (pid_t *) NULL);
1094 fprintf (stderr, z_err, errno, strerror (errno),
1097 if ((errno != EAGAIN) || (++failCt > 10))
1098 exit (EXIT_FAILURE);
1106 /* IF after all the tests we did not start any patch programs,
1109 if (fdp.read_fd < 0)
1112 /* OK. We have work to do. Read back in the output
1113 of the filtering chain. Compare each byte as we read it with
1114 the contents of the original file. As soon as we find any
1115 difference, we will create the output file, write out all
1116 the matched text and then copy any remaining data from the
1117 output of the filter chain.
1120 FILE *in_fp = fdopen (fdp.read_fd, "r");
1121 FILE *out_fp = (FILE *) NULL;
1122 char *pz_cmp = pz_data;
1132 /* IF we are emitting the output
1133 THEN emit this character, too.
1135 if (out_fp != (FILE *) NULL)
1138 /* ELSE if this character does not match the original,
1139 THEN now is the time to start the output.
1141 else if (ch != *pz_cmp)
1143 out_fp = create_file (pz_file_name);
1145 /* IF there are matched data, write it all now. */
1146 if (pz_cmp != pz_data)
1151 fputs (pz_data, out_fp);
1155 /* Emit the current unmatching character */
1159 /* ELSE the character matches. Advance the compare ptr */
1163 /* IF we created the output file, ... */
1164 if (out_fp != (FILE *) NULL)
1168 /* Close the file and see if we have to worry about
1169 `#include "file.h"' constructs. */
1171 if (regexec (&incl_quote_re, pz_data, 1, &match, 0) == 0)
1172 extract_quoted_files (pz_data, pz_file_name, &match);
1176 close (fdp.read_fd); /* probably redundant, but I'm paranoid */
1178 /* Wait for child processes created by chain_open()
1179 to avoid creating zombies. */
1180 while (--num_children >= 0)
1181 wait ((int *) NULL);