blob: 1133534202b53fb2fc7f21bd5d9a757811c293f1 [file] [log] [blame]
Bruce Korb1f414ac1999-03-03 07:41:52 +00001/* Install modified versions of certain ANSI-incompatible system header
2 files which are fixed to work correctly with ANSI C and placed in a
Nathanael Nerode6e6a1682003-05-23 20:48:48 +00003 directory that GCC will search.
Bruce Korb1f414ac1999-03-03 07:41:52 +00004
Jakub Jelinek748086b2009-04-09 17:00:19 +02005 Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009
6 Free Software Foundation, Inc.
Bruce Korb1f414ac1999-03-03 07:41:52 +00007
Nathanael Nerode6e6a1682003-05-23 20:48:48 +00008This file is part of GCC.
Bruce Korb1f414ac1999-03-03 07:41:52 +00009
Nathanael Nerode6e6a1682003-05-23 20:48:48 +000010GCC is free software; you can redistribute it and/or modify
Bruce Korb1f414ac1999-03-03 07:41:52 +000011it under the terms of the GNU General Public License as published by
Jakub Jelinek748086b2009-04-09 17:00:19 +020012the Free Software Foundation; either version 3, or (at your option)
Bruce Korb1f414ac1999-03-03 07:41:52 +000013any later version.
14
Nathanael Nerode6e6a1682003-05-23 20:48:48 +000015GCC is distributed in the hope that it will be useful,
Bruce Korb1f414ac1999-03-03 07:41:52 +000016but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Jakub Jelinek748086b2009-04-09 17:00:19 +020018GNU General Public License for more details.
Bruce Korb1f414ac1999-03-03 07:41:52 +000019
20You should have received a copy of the GNU General Public License
Jakub Jelinek748086b2009-04-09 17:00:19 +020021along with GCC; see the file COPYING3. If not see
22<http://www.gnu.org/licenses/>. */
Bruce Korb1f414ac1999-03-03 07:41:52 +000023
Bruce Korb5abc1f71999-10-12 14:44:18 +000024#include "fixlib.h"
Bruce Korb1f414ac1999-03-03 07:41:52 +000025
Bruce Korb401be4b2007-01-06 18:03:50 +000026#include <fnmatch.h>
Paolo Bonziniad643a72004-10-15 07:58:38 +000027#include <sys/stat.h>
Danny Smith8ba8f7e2005-05-22 17:01:02 +000028#ifndef SEPARATE_FIX_PROC
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +000029#include <sys/wait.h>
Danny Smith8ba8f7e2005-05-22 17:01:02 +000030#endif
Paolo Bonziniad643a72004-10-15 07:58:38 +000031
Bruce Korb1e570a62000-09-05 22:28:04 +000032#if defined( HAVE_MMAP_FILE )
Philippe De Muyter99d525c1999-11-01 19:14:50 +010033#include <sys/mman.h>
34#define BAD_ADDR ((void*)-1)
35#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +000036
Daniel Berlin283da1d2000-12-02 19:46:32 +000037#ifndef SEPARATE_FIX_PROC
Bruce Korb0083c901998-10-16 07:00:18 +000038#include "server.h"
Bruce Korb62a99402000-08-04 14:16:57 +000039#endif
Bruce Korb0083c901998-10-16 07:00:18 +000040
Bruce Korb5abc1f71999-10-12 14:44:18 +000041/* The contents of this string are not very important. It is mostly
42 just used as part of the "I am alive and working" test. */
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +000043
Bruce Korb5abc1f71999-10-12 14:44:18 +000044static const char program_id[] = "fixincl version 1.1";
Bruce Korb0083c901998-10-16 07:00:18 +000045
Bruce Korbe02ecf32000-07-19 14:10:41 +000046/* This format will be used at the start of every generated file */
47
48static const char z_std_preamble[] =
49"/* DO NOT EDIT THIS FILE.\n\n\
50 It has been auto-edited by fixincludes from:\n\n\
51\t\"%s/%s\"\n\n\
52 This had to be done to correct non-standard usages in the\n\
53 original, manufacturer supplied header file. */\n\n";
54
Bruce Korb7d9ccd91999-03-31 11:51:29 +000055int find_base_len = 0;
Bruce Korb0083c901998-10-16 07:00:18 +000056
Bruce Korbb35926b1999-11-11 14:57:55 +000057typedef enum {
58 VERB_SILENT = 0,
59 VERB_FIXES,
60 VERB_APPLIES,
61 VERB_PROGRESS,
62 VERB_TESTS,
63 VERB_EVERYTHING
64} te_verbose;
65
66te_verbose verbose_level = VERB_PROGRESS;
Zack Weinbergd7eb5a41999-12-17 21:49:30 +000067int have_tty = 0;
Bruce Korbb35926b1999-11-11 14:57:55 +000068
John David Anglindbbbbf32001-03-02 21:41:37 +000069#define VLEVEL(l) ((unsigned int) verbose_level >= (unsigned int) l)
Bruce Korbb35926b1999-11-11 14:57:55 +000070#define NOT_SILENT VLEVEL(VERB_FIXES)
71
Bruce Korb1f414ac1999-03-03 07:41:52 +000072pid_t process_chain_head = (pid_t) -1;
Bruce Korb0083c901998-10-16 07:00:18 +000073
Bruce Korb5abc1f71999-10-12 14:44:18 +000074char* pz_curr_file; /* name of the current file under test/fix */
75char* pz_curr_data; /* original contents of that file */
Bruce Korb62a99402000-08-04 14:16:57 +000076char* pz_temp_file; /* for DOS, a place to stash the temporary
77 fixed data between system(3) calls */
Bruce Korb5abc1f71999-10-12 14:44:18 +000078t_bool curr_data_mapped;
79int data_map_fd;
80size_t data_map_size;
81size_t ttl_data_size = 0;
Bruce Korbe02ecf32000-07-19 14:10:41 +000082
Bruce Korb5abc1f71999-10-12 14:44:18 +000083#ifdef DO_STATS
84int process_ct = 0;
85int apply_ct = 0;
86int fixed_ct = 0;
87int altered_ct = 0;
88#endif /* DO_STATS */
89
Bruce Korb1f414ac1999-03-03 07:41:52 +000090const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
Bruce Korb5abc1f71999-10-12 14:44:18 +000091tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
Bruce Korb1f414ac1999-03-03 07:41:52 +000092regex_t incl_quote_re;
Bruce Korb0083c901998-10-16 07:00:18 +000093
Nathanael Nerodef4dbf932003-08-01 23:07:04 +000094static void do_version (void) ATTRIBUTE_NORETURN;
95char *load_file (const char *);
96void run_compiles (void);
97void initialize (int argc, char** argv);
98void process (void);
Bruce Korb5abc1f71999-10-12 14:44:18 +000099
100/* External Source Code */
Bruce Korb0083c901998-10-16 07:00:18 +0000101
102#include "fixincl.x"
103
Bruce Korb1f414ac1999-03-03 07:41:52 +0000104/* * * * * * * * * * * * * * * * * * *
105 *
106 * MAIN ROUTINE
107 */
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000108extern int main (int, char **);
Bruce Korb0083c901998-10-16 07:00:18 +0000109int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000110main (int argc, char** argv)
Bruce Korb0083c901998-10-16 07:00:18 +0000111{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000112 char *file_name_buf;
Bruce Korb0083c901998-10-16 07:00:18 +0000113
Bruce Korb35dfe412000-05-11 13:41:12 +0000114 initialize ( argc, argv );
Bruce Korbd1c6a031999-04-26 10:38:38 +0000115
Zack Weinbergd7eb5a41999-12-17 21:49:30 +0000116 have_tty = isatty (fileno (stderr));
117
Bruce Korb5abc1f71999-10-12 14:44:18 +0000118 /* Before anything else, ensure we can allocate our file name buffer. */
119 file_name_buf = load_file_data (stdin);
120
121 /* Because of the way server shells work, you have to keep stdin, out
122 and err open so that the proper input file does not get closed
123 by accident */
124
125 freopen ("/dev/null", "r", stdin);
126
127 if (file_name_buf == (char *) NULL)
128 {
129 fputs ("No file names listed for fixing\n", stderr);
130 exit (EXIT_FAILURE);
131 }
132
Bruce Korbd1c6a031999-04-26 10:38:38 +0000133 for (;;)
134 {
Bruce Korb5abc1f71999-10-12 14:44:18 +0000135 char* pz_end;
Bruce Korbd1c6a031999-04-26 10:38:38 +0000136
Bruce Korb5abc1f71999-10-12 14:44:18 +0000137 /* skip to start of name, past any "./" prefixes */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000138
Bruce Korb5abc1f71999-10-12 14:44:18 +0000139 while (ISSPACE (*file_name_buf)) file_name_buf++;
140 while ((file_name_buf[0] == '.') && (file_name_buf[1] == '/'))
141 file_name_buf += 2;
Bruce Korbd1c6a031999-04-26 10:38:38 +0000142
Bruce Korb5abc1f71999-10-12 14:44:18 +0000143 /* Check for end of list */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000144
Bruce Korb5abc1f71999-10-12 14:44:18 +0000145 if (*file_name_buf == NUL)
146 break;
147
148 /* Set global file name pointer and find end of name */
149
150 pz_curr_file = file_name_buf;
151 pz_end = strchr( pz_curr_file, '\n' );
152 if (pz_end == (char*)NULL)
153 pz_end = file_name_buf = pz_curr_file + strlen (pz_curr_file);
154 else
155 file_name_buf = pz_end + 1;
156
157 while ((pz_end > pz_curr_file) && ISSPACE( pz_end[-1])) pz_end--;
158
159 /* IF no name is found (blank line) or comment marker, skip line */
160
161 if ((pz_curr_file == pz_end) || (*pz_curr_file == '#'))
162 continue;
163 *pz_end = NUL;
164
Bruce Korb5abc1f71999-10-12 14:44:18 +0000165 process ();
Bruce Korb5abc1f71999-10-12 14:44:18 +0000166 } /* for (;;) */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000167
Bruce Korb5abc1f71999-10-12 14:44:18 +0000168#ifdef DO_STATS
Bruce Korbb35926b1999-11-11 14:57:55 +0000169 if (VLEVEL( VERB_PROGRESS )) {
Bruce Korb5abc1f71999-10-12 14:44:18 +0000170 tSCC zFmt[] =
171 "\
172Processed %5d files containing %d bytes \n\
173Applying %5d fixes to %d files\n\
174Altering %5d of them\n";
Bruce Korbd1c6a031999-04-26 10:38:38 +0000175
Bruce Korb5abc1f71999-10-12 14:44:18 +0000176 fprintf (stderr, zFmt, process_ct, ttl_data_size, apply_ct,
177 fixed_ct, altered_ct);
178 }
179#endif /* DO_STATS */
Bruce Korb62a99402000-08-04 14:16:57 +0000180
Daniel Berlin283da1d2000-12-02 19:46:32 +0000181# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000182 unlink( pz_temp_file );
183# endif
Bruce Korb15fe1a72001-01-05 16:28:58 +0000184 exit (EXIT_SUCCESS);
Bruce Korbd1c6a031999-04-26 10:38:38 +0000185}
186
187
Bruce Korb6864a6c2000-12-02 19:01:16 +0000188static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000189do_version (void)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000190{
191 static const char zFmt[] = "echo '%s'";
192 char zBuf[ 1024 ];
193
194 /* The 'version' option is really used to test that:
195 1. The program loads correctly (no missing libraries)
Bruce Korb35dfe412000-05-11 13:41:12 +0000196 2. that we can compile all the regular expressions.
197 3. we can correctly run our server shell process
Bruce Korb5abc1f71999-10-12 14:44:18 +0000198 */
199 run_compiles ();
200 sprintf (zBuf, zFmt, program_id);
Daniel Berlin283da1d2000-12-02 19:46:32 +0000201#ifndef SEPARATE_FIX_PROC
Bruce Korb6b151aa2000-05-04 14:55:00 +0000202 puts (zBuf + 5);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000203 exit (strcmp (run_shell (zBuf), program_id));
Bruce Korb62a99402000-08-04 14:16:57 +0000204#else
205 exit (system (zBuf));
206#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +0000207}
208
Bruce Korbd1c6a031999-04-26 10:38:38 +0000209/* * * * * * * * * * * * */
210
211void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000212initialize ( int argc, char** argv )
Bruce Korbd1c6a031999-04-26 10:38:38 +0000213{
Bruce Korb878a5792000-07-12 14:45:05 +0000214 xmalloc_set_program_name (argv[0]);
215
Bruce Korb35dfe412000-05-11 13:41:12 +0000216 switch (argc)
217 {
218 case 1:
219 break;
220
221 case 2:
222 if (strcmp (argv[1], "-v") == 0)
223 do_version ();
224 if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
225 {
226 fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
227 errno, xstrerror (errno), argv[1] );
228 exit (EXIT_FAILURE);
229 }
230 break;
231
232 default:
233 fputs ("fixincl ERROR: too many command line arguments\n", stderr);
234 exit (EXIT_FAILURE);
235 }
236
Bruce Korb798bdf72001-03-16 00:58:40 +0000237#ifdef SIGCHLD
238 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
239 receive the signal. A different setting is inheritable */
240 signal (SIGCHLD, SIG_DFL);
241#endif
242
Paolo Bonziniad643a72004-10-15 07:58:38 +0000243 initialize_opts ();
Bruce Korb0083c901998-10-16 07:00:18 +0000244
Bruce Korb6864a6c2000-12-02 19:01:16 +0000245 if (ISDIGIT ( *pz_verbose ))
Bruce Korbe02ecf32000-07-19 14:10:41 +0000246 verbose_level = (te_verbose)atoi( pz_verbose );
247 else
248 switch (*pz_verbose) {
249 case 's':
250 case 'S':
251 verbose_level = VERB_SILENT; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000252
Bruce Korbe02ecf32000-07-19 14:10:41 +0000253 case 'f':
254 case 'F':
255 verbose_level = VERB_FIXES; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000256
Bruce Korbe02ecf32000-07-19 14:10:41 +0000257 case 'a':
258 case 'A':
259 verbose_level = VERB_APPLIES; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000260
DJ Delorie7a9cdb12003-03-22 16:51:04 -0500261 default:
Bruce Korbe02ecf32000-07-19 14:10:41 +0000262 case 'p':
263 case 'P':
264 verbose_level = VERB_PROGRESS; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000265
Bruce Korbe02ecf32000-07-19 14:10:41 +0000266 case 't':
267 case 'T':
268 verbose_level = VERB_TESTS; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000269
Bruce Korbe02ecf32000-07-19 14:10:41 +0000270 case 'e':
271 case 'E':
272 verbose_level = VERB_EVERYTHING; break;
273 }
DJ Delorie7a9cdb12003-03-22 16:51:04 -0500274 if (verbose_level >= VERB_EVERYTHING) {
275 verbose_level = VERB_EVERYTHING;
276 fputs ("fixinc verbosity: EVERYTHING\n", stderr);
277 }
278 while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
279 pz_find_base += 2;
280 if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
281 find_base_len = strlen( pz_find_base );
Bruce Korb7d9ccd91999-03-31 11:51:29 +0000282
Bruce Korb1f414ac1999-03-03 07:41:52 +0000283 /* Compile all the regular expressions now.
284 That way, it is done only once for the whole run.
285 */
286 run_compiles ();
Bruce Korb0083c901998-10-16 07:00:18 +0000287
Daniel Berlin283da1d2000-12-02 19:46:32 +0000288# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000289 /* NULL as the first argument to `tempnam' causes it to DTRT
290 wrt the temporary directory where the file will be created. */
291 pz_temp_file = tempnam( NULL, "fxinc" );
292# endif
293
Bruce Korb1f414ac1999-03-03 07:41:52 +0000294 signal (SIGQUIT, SIG_IGN);
295 signal (SIGIOT, SIG_IGN);
296 signal (SIGPIPE, SIG_IGN);
297 signal (SIGALRM, SIG_IGN);
298 signal (SIGTERM, SIG_IGN);
Bruce Korbd1c6a031999-04-26 10:38:38 +0000299}
Bruce Korb0083c901998-10-16 07:00:18 +0000300
Bruce Korb1f414ac1999-03-03 07:41:52 +0000301/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000302
Bruce Korb1f414ac1999-03-03 07:41:52 +0000303 load_file loads all the contents of a file into malloc-ed memory.
304 Its argument is the name of the file to read in; the returned
305 result is the NUL terminated contents of the file. The file
306 is presumed to be an ASCII text file containing no NULs. */
Bruce Korb0083c901998-10-16 07:00:18 +0000307char *
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000308load_file ( const char* fname )
Bruce Korb0083c901998-10-16 07:00:18 +0000309{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000310 struct stat stbf;
311 char* res;
Bruce Korb0083c901998-10-16 07:00:18 +0000312
Bruce Korb5abc1f71999-10-12 14:44:18 +0000313 if (stat (fname, &stbf) != 0)
Bruce Korb0083c901998-10-16 07:00:18 +0000314 {
Bruce Korbb35926b1999-11-11 14:57:55 +0000315 if (NOT_SILENT)
316 fprintf (stderr, "error %d (%s) stat-ing %s\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000317 errno, xstrerror (errno), fname );
Bruce Korb5abc1f71999-10-12 14:44:18 +0000318 return (char *) NULL;
319 }
320 if (stbf.st_size == 0)
321 return (char*)NULL;
322
Bruce Korba6efbec2000-09-05 18:29:56 +0000323 /* Make the data map size one larger than the file size for documentation
324 purposes. Truth is that there will be a following NUL character if
325 the file size is not a multiple of the page size. If it is a multiple,
326 then this adjustment sometimes fails anyway. */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000327 data_map_size = stbf.st_size+1;
328 data_map_fd = open (fname, O_RDONLY);
329 ttl_data_size += data_map_size-1;
330
331 if (data_map_fd < 0)
332 {
Bruce Korbb35926b1999-11-11 14:57:55 +0000333 if (NOT_SILENT)
334 fprintf (stderr, "error %d (%s) opening %s for read\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000335 errno, xstrerror (errno), fname);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000336 return (char*)NULL;
Bruce Korb0083c901998-10-16 07:00:18 +0000337 }
338
Zack Weinberg56f02b82000-04-17 17:25:57 +0000339#ifdef HAVE_MMAP_FILE
Bruce Korb5abc1f71999-10-12 14:44:18 +0000340 curr_data_mapped = BOOL_TRUE;
Bruce Korba6efbec2000-09-05 18:29:56 +0000341
342 /* IF the file size is a multiple of the page size,
343 THEN sometimes you will seg fault trying to access a trailing byte */
Bruce Korbdc465052000-09-05 22:26:16 +0000344 if ((stbf.st_size & (getpagesize()-1)) == 0)
Bruce Korba6efbec2000-09-05 18:29:56 +0000345 res = (char*)BAD_ADDR;
346 else
347 res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
348 MAP_PRIVATE, data_map_fd, 0);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000349 if (res == (char*)BAD_ADDR)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000350#endif
Bruce Korbca21b4a2001-02-06 22:19:50 +0000351 {
352 FILE* fp = fdopen (data_map_fd, "r");
353 curr_data_mapped = BOOL_FALSE;
354 res = load_file_data (fp);
355 fclose (fp);
356 }
Bruce Korb0083c901998-10-16 07:00:18 +0000357
Bruce Korb5abc1f71999-10-12 14:44:18 +0000358 return res;
Bruce Korb0083c901998-10-16 07:00:18 +0000359}
360
Bruce Korb6864a6c2000-12-02 19:01:16 +0000361static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000362machine_matches( tFixDesc* p_fixd )
Bruce Korb401be4b2007-01-06 18:03:50 +0000363{
364 char const ** papz_machs = p_fixd->papz_machs;
365 int have_match = BOOL_FALSE;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000366
Bruce Korb62a99402000-08-04 14:16:57 +0000367 for (;;)
368 {
Bruce Korb401be4b2007-01-06 18:03:50 +0000369 char const * pz_mpat = *(papz_machs++);
370 if (pz_mpat == NULL)
Bruce Korb62a99402000-08-04 14:16:57 +0000371 break;
Bruce Korb401be4b2007-01-06 18:03:50 +0000372 if (fnmatch(pz_mpat, pz_machine, 0) == 0)
373 {
374 have_match = BOOL_TRUE;
375 break;
376 }
Bruce Korb62a99402000-08-04 14:16:57 +0000377 }
378
Bruce Korb2f82a972007-01-06 20:02:22 +0000379 /* Check for sense inversion then set the "skip test" flag, if needed */
Bruce Korb401be4b2007-01-06 18:03:50 +0000380 if (p_fixd->fd_flags & FD_MACH_IFNOT)
Bruce Korb2f82a972007-01-06 20:02:22 +0000381 have_match = ! have_match;
382
383 if (! have_match)
384 p_fixd->fd_flags |= FD_SKIP_TEST;
385
Bruce Korb401be4b2007-01-06 18:03:50 +0000386 return have_match;
Bruce Korb62a99402000-08-04 14:16:57 +0000387}
388
389/* * * * * * * * * * * * *
Bruce Korb401be4b2007-01-06 18:03:50 +0000390 *
391 * run_compiles run all the regexp compiles for all the fixes once.
392 */
Bruce Korb62a99402000-08-04 14:16:57 +0000393void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000394run_compiles (void)
Bruce Korb62a99402000-08-04 14:16:57 +0000395{
396 tFixDesc *p_fixd = fixDescList;
397 int fix_ct = FIX_COUNT;
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000398 regex_t *p_re = XCNEWVEC (regex_t, REGEX_COUNT);
Bruce Korb62a99402000-08-04 14:16:57 +0000399
400 /* Make sure compile_re does not stumble across invalid data */
401
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000402 memset (&incl_quote_re, '\0', sizeof (regex_t));
Bruce Korb62a99402000-08-04 14:16:57 +0000403
404 compile_re (incl_quote_pat, &incl_quote_re, 1,
405 "quoted include", "run_compiles");
406
407 /* Allow machine name tests to be ignored (testing, mainly) */
408
409 if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
410 pz_machine = (char*)NULL;
411
412 /* FOR every fixup, ... */
413 do
414 {
415 tTestDesc *p_test = p_fixd->p_test_desc;
416 int test_ct = p_fixd->test_ct;
417
418 /* IF the machine type pointer is not NULL (we are not in test mode)
419 AND this test is for or not done on particular machines
420 THEN ... */
421
422 if ( (pz_machine != NULL)
423 && (p_fixd->papz_machs != (const char**) NULL)
424 && ! machine_matches (p_fixd) )
425 continue;
Bruce Korb1f414ac1999-03-03 07:41:52 +0000426
427 /* FOR every test for the fixup, ... */
428
429 while (--test_ct >= 0)
430 {
431 switch (p_test->type)
Bruce Korb0083c901998-10-16 07:00:18 +0000432 {
433 case TT_EGREP:
434 case TT_NEGREP:
Bruce Korb1f414ac1999-03-03 07:41:52 +0000435 p_test->p_test_regex = p_re++;
Bruce Korb35dfe412000-05-11 13:41:12 +0000436 compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
437 "select test", p_fixd->fix_name);
Bruce Korb3af556f2000-09-12 14:28:55 +0000438 default: break;
Bruce Korb35dfe412000-05-11 13:41:12 +0000439 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000440 p_test++;
Bruce Korb0083c901998-10-16 07:00:18 +0000441 }
442 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000443 while (p_fixd++, --fix_ct > 0);
Bruce Korb0083c901998-10-16 07:00:18 +0000444}
445
446
Bruce Korb1f414ac1999-03-03 07:41:52 +0000447/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000448
Bruce Korb1f414ac1999-03-03 07:41:52 +0000449 create_file Create the output modified file.
450 Input: the name of the file to create
451 Returns: a file pointer to the new, open file */
452
Bruce Korb063174e1999-11-04 14:50:44 +0000453#if defined(S_IRUSR) && defined(S_IWUSR) && \
454 defined(S_IRGRP) && defined(S_IROTH)
455
456# define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
457#else
458# define S_IRALL 0644
459#endif
460
461#if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
462 defined(S_IROTH) && defined(S_IXOTH)
463
464# define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
465#else
466# define S_DIRALL 0755
467#endif
468
Bruce Korb1f414ac1999-03-03 07:41:52 +0000469
Bruce Korb6864a6c2000-12-02 19:01:16 +0000470static FILE *
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000471create_file (void)
Bruce Korb0083c901998-10-16 07:00:18 +0000472{
473 int fd;
474 FILE *pf;
475 char fname[MAXPATHLEN];
476
Bruce Korb5abc1f71999-10-12 14:44:18 +0000477 sprintf (fname, "%s/%s", pz_dest_dir, pz_curr_file + find_base_len);
Bruce Korb0083c901998-10-16 07:00:18 +0000478
Bruce Korb1f414ac1999-03-03 07:41:52 +0000479 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
Bruce Korb0083c901998-10-16 07:00:18 +0000480
Bruce Korb1f414ac1999-03-03 07:41:52 +0000481 /* We may need to create the directories needed... */
Bruce Korb0083c901998-10-16 07:00:18 +0000482 if ((fd < 0) && (errno == ENOENT))
483 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000484 char *pz_dir = strchr (fname + 1, '/');
Bruce Korb0083c901998-10-16 07:00:18 +0000485 struct stat stbf;
486
Bruce Korb1f414ac1999-03-03 07:41:52 +0000487 while (pz_dir != (char *) NULL)
Bruce Korb0083c901998-10-16 07:00:18 +0000488 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000489 *pz_dir = NUL;
Bruce Korb0083c901998-10-16 07:00:18 +0000490 if (stat (fname, &stbf) < 0)
491 {
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600492#ifdef _WIN32
493 mkdir (fname);
494#else
Bruce Korb063174e1999-11-04 14:50:44 +0000495 mkdir (fname, S_IFDIR | S_DIRALL);
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600496#endif
Bruce Korb0083c901998-10-16 07:00:18 +0000497 }
498
Bruce Korb1f414ac1999-03-03 07:41:52 +0000499 *pz_dir = '/';
500 pz_dir = strchr (pz_dir + 1, '/');
Bruce Korb0083c901998-10-16 07:00:18 +0000501 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000502
503 /* Now, lets try the open again... */
504 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
Bruce Korb0083c901998-10-16 07:00:18 +0000505 }
506 if (fd < 0)
507 {
508 fprintf (stderr, "Error %d (%s) creating %s\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000509 errno, xstrerror (errno), fname);
Bruce Korb0083c901998-10-16 07:00:18 +0000510 exit (EXIT_FAILURE);
511 }
Bruce Korbb35926b1999-11-11 14:57:55 +0000512 if (NOT_SILENT)
513 fprintf (stderr, "Fixed: %s\n", pz_curr_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000514 pf = fdopen (fd, "w");
515
Bruce Korbe02ecf32000-07-19 14:10:41 +0000516 /*
517 * IF pz_machine is NULL, then we are in some sort of test mode.
518 * Do not insert the current directory name. Use a constant string.
519 */
520 fprintf (pf, z_std_preamble,
521 (pz_machine == NULL)
522 ? "fixinc/tests/inc"
523 : pz_input_dir,
524 pz_curr_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000525
Bruce Korb0083c901998-10-16 07:00:18 +0000526 return pf;
527}
528
Bruce Korb1f414ac1999-03-03 07:41:52 +0000529
530/* * * * * * * * * * * * *
531
532 test_test make sure a shell-style test expression passes.
533 Input: a pointer to the descriptor of the test to run and
534 the name of the file that we might want to fix
Bruce Korb5abc1f71999-10-12 14:44:18 +0000535 Result: APPLY_FIX or SKIP_FIX, depending on the result of the
Bruce Korb1f414ac1999-03-03 07:41:52 +0000536 shell script we run. */
Daniel Berlin283da1d2000-12-02 19:46:32 +0000537#ifndef SEPARATE_FIX_PROC
Bruce Korb6864a6c2000-12-02 19:01:16 +0000538static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000539test_test (tTestDesc* p_test, char* pz_test_file)
Bruce Korb0083c901998-10-16 07:00:18 +0000540{
Bruce Korb94db2f71999-05-12 07:32:58 +0000541 tSCC cmd_fmt[] =
542"file=%s\n\
543if ( test %s ) > /dev/null 2>&1\n\
544then echo TRUE\n\
545else echo FALSE\n\
546fi";
547
Bruce Korb1f414ac1999-03-03 07:41:52 +0000548 char *pz_res;
Bruce Korbe9099382000-05-17 14:56:13 +0000549 int res;
Bruce Korb0083c901998-10-16 07:00:18 +0000550
Bruce Korb1f414ac1999-03-03 07:41:52 +0000551 static char cmd_buf[4096];
Bruce Korb0083c901998-10-16 07:00:18 +0000552
Bruce Korb5abc1f71999-10-12 14:44:18 +0000553 sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
Bruce Korb1f414ac1999-03-03 07:41:52 +0000554 pz_res = run_shell (cmd_buf);
Bruce Korbe9099382000-05-17 14:56:13 +0000555
556 switch (*pz_res) {
557 case 'T':
Bruce Korb5abc1f71999-10-12 14:44:18 +0000558 res = APPLY_FIX;
Bruce Korbe9099382000-05-17 14:56:13 +0000559 break;
560
561 case 'F':
562 res = SKIP_FIX;
563 break;
564
565 default:
566 fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
567 pz_res, cmd_buf );
James A. Morrison9cdfc8e2004-01-27 19:10:10 +0000568 res = SKIP_FIX;
Bruce Korbe9099382000-05-17 14:56:13 +0000569 }
570
Bruce Korb1f414ac1999-03-03 07:41:52 +0000571 free ((void *) pz_res);
Bruce Korb0083c901998-10-16 07:00:18 +0000572 return res;
573}
Bruce Korb62a99402000-08-04 14:16:57 +0000574#else
575/*
576 * IF we are in MS-DOS land, then whatever shell-type test is required
577 * will, by definition, fail
578 */
579#define test_test(t,tf) SKIP_FIX
580#endif
Bruce Korb0083c901998-10-16 07:00:18 +0000581
Bruce Korb1f414ac1999-03-03 07:41:52 +0000582/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000583
Bruce Korb1f414ac1999-03-03 07:41:52 +0000584 egrep_test make sure an egrep expression is found in the file text.
585 Input: a pointer to the descriptor of the test to run and
586 the pointer to the contents of the file under suspicion
Bruce Korb5abc1f71999-10-12 14:44:18 +0000587 Result: APPLY_FIX if the pattern is found, SKIP_FIX otherwise
Bruce Korb1f414ac1999-03-03 07:41:52 +0000588
Bruce Korb5abc1f71999-10-12 14:44:18 +0000589 The caller may choose to reverse meaning if the sense of the test
Bruce Korb1f414ac1999-03-03 07:41:52 +0000590 is inverted. */
591
Bruce Korb6864a6c2000-12-02 19:01:16 +0000592static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000593egrep_test (char* pz_data, tTestDesc* p_test)
Bruce Korb0083c901998-10-16 07:00:18 +0000594{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000595#ifdef DEBUG
Bruce Korb1f414ac1999-03-03 07:41:52 +0000596 if (p_test->p_test_regex == 0)
597 fprintf (stderr, "fixincl ERROR RE not compiled: `%s'\n",
598 p_test->pz_test_text);
Bruce Korb0083c901998-10-16 07:00:18 +0000599#endif
Zack Weinbergab747402003-07-08 20:42:19 +0000600 if (xregexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000601 return APPLY_FIX;
602 return SKIP_FIX;
Bruce Korb0083c901998-10-16 07:00:18 +0000603}
604
605
Bruce Korb1f414ac1999-03-03 07:41:52 +0000606/* * * * * * * * * * * * *
Bruce Korb94db2f71999-05-12 07:32:58 +0000607
608 quoted_file_exists Make sure that a file exists before we emit
609 the file name. If we emit the name, our invoking shell will try
610 to copy a non-existing file into the destination directory. */
611
Bruce Korb6864a6c2000-12-02 19:01:16 +0000612static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000613quoted_file_exists (const char* pz_src_path,
614 const char* pz_file_path,
615 const char* pz_file)
Bruce Korb94db2f71999-05-12 07:32:58 +0000616{
617 char z[ MAXPATHLEN ];
618 char* pz;
619 sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
620 pz = z + strlen ( z );
621
622 for (;;) {
623 char ch = *pz_file++;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000624 if (! ISGRAPH( ch ))
Bruce Korb94db2f71999-05-12 07:32:58 +0000625 return 0;
626 if (ch == '"')
627 break;
628 *pz++ = ch;
629 }
630 *pz = '\0';
631 {
632 struct stat s;
633 if (stat (z, &s) != 0)
634 return 0;
635 return S_ISREG( s.st_mode );
636 }
637}
638
639
640/* * * * * * * * * * * * *
Bruce Korb1f414ac1999-03-03 07:41:52 +0000641 *
642 extract_quoted_files
Bruce Korb5abc1f71999-10-12 14:44:18 +0000643
Bruce Korb1f414ac1999-03-03 07:41:52 +0000644 The syntax, `#include "file.h"' specifies that the compiler is to
645 search the local directory of the current file before the include
646 list. Consequently, if we have modified a header and stored it in
647 another directory, any files that are included by that modified
648 file in that fashion must also be copied into this new directory.
649 This routine finds those flavors of #include and for each one found
650 emits a triple of:
Bruce Korb5abc1f71999-10-12 14:44:18 +0000651
Bruce Korb1f414ac1999-03-03 07:41:52 +0000652 1. source directory of the original file
653 2. the relative path file name of the #includ-ed file
654 3. the full destination path for this file
655
656 Input: the text of the file, the file name and a pointer to the
657 match list where the match information was stored.
658 Result: internally nothing. The results are written to stdout
659 for interpretation by the invoking shell */
Bruce Korb0083c901998-10-16 07:00:18 +0000660
Bruce Korb94db2f71999-05-12 07:32:58 +0000661
Bruce Korb6864a6c2000-12-02 19:01:16 +0000662static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000663extract_quoted_files (char* pz_data,
664 const char* pz_fixed_file,
665 regmatch_t* p_re_match)
Bruce Korb0083c901998-10-16 07:00:18 +0000666{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000667 char *pz_dir_end = strrchr (pz_fixed_file, '/');
Bruce Korb1f414ac1999-03-03 07:41:52 +0000668 char *pz_incl_quot = pz_data;
Bruce Korb0083c901998-10-16 07:00:18 +0000669
Bruce Korbb35926b1999-11-11 14:57:55 +0000670 if (VLEVEL( VERB_APPLIES ))
671 fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000672
Bruce Korb5abc1f71999-10-12 14:44:18 +0000673 /* Set "pz_fixed_file" to point to the containing subdirectory of the source
Bruce Korb94db2f71999-05-12 07:32:58 +0000674 If there is none, then it is in our current directory, ".". */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000675
676 if (pz_dir_end == (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000677 pz_fixed_file = ".";
Bruce Korb0083c901998-10-16 07:00:18 +0000678 else
Bruce Korb1f414ac1999-03-03 07:41:52 +0000679 *pz_dir_end = '\0';
Bruce Korb0083c901998-10-16 07:00:18 +0000680
681 for (;;)
682 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000683 pz_incl_quot += p_re_match->rm_so;
Bruce Korb0083c901998-10-16 07:00:18 +0000684
Bruce Korb1f414ac1999-03-03 07:41:52 +0000685 /* Skip forward to the included file name */
Zack Weinbergf6bbde22000-12-08 03:00:26 +0000686 while (*pz_incl_quot != '"')
Bruce Korb1f414ac1999-03-03 07:41:52 +0000687 pz_incl_quot++;
Bruce Korb0083c901998-10-16 07:00:18 +0000688
Bruce Korb5abc1f71999-10-12 14:44:18 +0000689 if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
Bruce Korb94db2f71999-05-12 07:32:58 +0000690 {
691 /* Print the source directory and the subdirectory
692 of the file in question. */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000693 printf ("%s %s/", pz_src_dir, pz_fixed_file);
Bruce Korb94db2f71999-05-12 07:32:58 +0000694 pz_dir_end = pz_incl_quot;
Bruce Korb0083c901998-10-16 07:00:18 +0000695
Bruce Korb94db2f71999-05-12 07:32:58 +0000696 /* Append to the directory the relative path of the desired file */
697 while (*pz_incl_quot != '"')
698 putc (*pz_incl_quot++, stdout);
Bruce Korb0083c901998-10-16 07:00:18 +0000699
Bruce Korb94db2f71999-05-12 07:32:58 +0000700 /* Now print the destination directory appended with the
701 relative path of the desired file */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000702 printf (" %s/%s/", pz_dest_dir, pz_fixed_file);
Bruce Korb94db2f71999-05-12 07:32:58 +0000703 while (*pz_dir_end != '"')
704 putc (*pz_dir_end++, stdout);
Bruce Korb0083c901998-10-16 07:00:18 +0000705
Bruce Korb94db2f71999-05-12 07:32:58 +0000706 /* End of entry */
707 putc ('\n', stdout);
708 }
Bruce Korb0083c901998-10-16 07:00:18 +0000709
Bruce Korb1f414ac1999-03-03 07:41:52 +0000710 /* Find the next entry */
Zack Weinbergab747402003-07-08 20:42:19 +0000711 if (xregexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
Bruce Korb0083c901998-10-16 07:00:18 +0000712 break;
713 }
714}
715
716
Bruce Korb5abc1f71999-10-12 14:44:18 +0000717/* * * * * * * * * * * * *
718
719 Somebody wrote a *_fix subroutine that we must call.
720 */
Daniel Berlin283da1d2000-12-02 19:46:32 +0000721#ifndef SEPARATE_FIX_PROC
Bruce Korb6864a6c2000-12-02 19:01:16 +0000722static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000723internal_fix (int read_fd, tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000724{
725 int fd[2];
726
727 if (pipe( fd ) != 0)
728 {
729 fprintf (stderr, "Error %d on pipe(2) call\n", errno );
730 exit (EXIT_FAILURE);
731 }
732
733 for (;;)
734 {
735 pid_t childid = fork();
736
737 switch (childid)
738 {
739 case -1:
740 break;
741
742 case 0:
743 close (fd[0]);
744 goto do_child_task;
745
746 default:
747 /*
748 * Parent process
749 */
750 close (read_fd);
751 close (fd[1]);
752 return fd[0];
753 }
754
755 /*
756 * Parent in error
757 */
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000758 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
Bruce Korb5abc1f71999-10-12 14:44:18 +0000759 p_fixd->fix_name);
760 {
761 static int failCt = 0;
762 if ((errno != EAGAIN) || (++failCt > 10))
763 exit (EXIT_FAILURE);
764 sleep (1);
765 }
766 } do_child_task:;
767
768 /*
769 * Close our current stdin and stdout
770 */
771 close (STDIN_FILENO);
772 close (STDOUT_FILENO);
773 UNLOAD_DATA();
774
775 /*
776 * Make the fd passed in the stdin, and the write end of
777 * the new pipe become the stdout.
778 */
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600779 dup2 (fd[1], STDOUT_FILENO);
780 dup2 (read_fd, STDIN_FILENO);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000781
Bruce Korb35dfe412000-05-11 13:41:12 +0000782 apply_fix (p_fixd, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000783 exit (0);
784}
Daniel Berlin283da1d2000-12-02 19:46:32 +0000785#endif /* !SEPARATE_FIX_PROC */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000786
Bruce Korbbb786201999-06-02 07:08:54 +0000787
Daniel Berlin283da1d2000-12-02 19:46:32 +0000788#ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000789static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000790fix_with_system (tFixDesc* p_fixd,
791 tCC* pz_fix_file,
792 tCC* pz_file_source,
793 tCC* pz_temp_file)
Bruce Korb62a99402000-08-04 14:16:57 +0000794{
795 char* pz_cmd;
796 char* pz_scan;
797 size_t argsize;
798
799 if (p_fixd->fd_flags & FD_SUBROUTINE)
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000800 {
801 static const char z_applyfix_prog[] =
802 "/../fixincludes/applyfix" EXE_EXT;
Bruce Korb62a99402000-08-04 14:16:57 +0000803
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000804 struct stat buf;
805 argsize = 32
806 + strlen (pz_orig_dir)
807 + sizeof (z_applyfix_prog)
808 + strlen (pz_fix_file)
809 + strlen (pz_file_source)
810 + strlen (pz_temp_file);
Bruce Korb62a99402000-08-04 14:16:57 +0000811
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000812 /* Allocate something sure to be big enough for our purposes */
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000813 pz_cmd = XNEWVEC (char, argsize);
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000814 strcpy (pz_cmd, pz_orig_dir);
815 pz_scan = pz_cmd + strlen (pz_orig_dir);
Bruce Korb62a99402000-08-04 14:16:57 +0000816
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000817 strcpy (pz_scan, z_applyfix_prog);
Bruce Korb62a99402000-08-04 14:16:57 +0000818
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000819 /* IF we can't find the "applyfix" executable file at the first guess,
820 try one level higher up */
821 if (stat (pz_cmd, &buf) == -1)
822 {
823 strcpy (pz_scan, "/..");
824 strcpy (pz_scan+3, z_applyfix_prog);
825 }
826
827 pz_scan += strlen (pz_scan);
828
829 /*
830 * Now add the fix number and file names that may be needed
831 */
Tristan Gingoldc1041242012-04-24 09:24:55 +0000832 sprintf (pz_scan, " %ld '%s' '%s' '%s'", (long) (p_fixd - fixDescList),
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000833 pz_fix_file, pz_file_source, pz_temp_file);
834 }
Bruce Korb62a99402000-08-04 14:16:57 +0000835 else /* NOT an "internal" fix: */
836 {
837 size_t parg_size;
Daniel Berlin283da1d2000-12-02 19:46:32 +0000838#ifdef __MSDOS__
Bruce Korb62a99402000-08-04 14:16:57 +0000839 /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
Daniel Berlin283da1d2000-12-02 19:46:32 +0000840 dst is a temporary file anyway, so we know there's no other
841 file by that name; and DOS's system(3) doesn't mind to
Eli Zaretskiidc13bad2000-08-21 19:28:18 +0300842 clobber existing file in redirection. Besides, with DOS 8+3
843 limited file namespace, we can easily lose if dst already has
844 an extension that is 3 or more characters long.
Daniel Berlin283da1d2000-12-02 19:46:32 +0000845
846 I do not think the 8+3 issue is relevant because all the files
847 we operate on are named "*.h", making 8+2 adequate. Anyway,
848 the following bizarre use of 'cat' only works on DOS boxes.
849 It causes the file to be dropped into a temporary file for
Eli Zaretskiidc13bad2000-08-21 19:28:18 +0300850 'cat' to read (pipes do not work on DOS). */
Bruce Korbecb0d202004-11-17 05:06:41 +0000851 tSCC z_cmd_fmt[] = " '%s' | cat > '%s'";
Daniel Berlin283da1d2000-12-02 19:46:32 +0000852#else
853 /* Don't use positional formatting arguments because some lame-o
854 implementations cannot cope :-(. */
855 tSCC z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
856#endif
Bruce Korb62a99402000-08-04 14:16:57 +0000857 tCC** ppArgs = p_fixd->patch_args;
858
859 argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
860 + strlen( pz_file_source );
861 parg_size = argsize;
862
863
864 /*
865 * Compute the size of the command line. Add lotsa extra space
866 * because some of the args to sed use lotsa single quotes.
867 * (This requires three extra bytes per quote. Here we allow
868 * for up to 8 single quotes for each argument, including the
869 * command name "sed" itself. Nobody will *ever* need more. :)
870 */
871 for (;;)
872 {
873 tCC* p_arg = *(ppArgs++);
874 if (p_arg == NULL)
875 break;
876 argsize += 24 + strlen( p_arg );
877 }
878
879 /* Estimated buffer size we will need. */
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000880 pz_scan = pz_cmd = XNEWVEC (char, argsize);
Bruce Korb62a99402000-08-04 14:16:57 +0000881 /* How much of it do we allot to the program name and its
882 arguments. */
883 parg_size = argsize - parg_size;
884
885 ppArgs = p_fixd->patch_args;
886
887 /*
888 * Copy the program name, unquoted
889 */
890 {
891 tCC* pArg = *(ppArgs++);
892 for (;;)
893 {
894 char ch = *(pArg++);
895 if (ch == NUL)
896 break;
897 *(pz_scan++) = ch;
898 }
899 }
900
901 /*
902 * Copy the program arguments, quoted
903 */
904 for (;;)
905 {
906 tCC* pArg = *(ppArgs++);
907 char* pz_scan_save;
908 if (pArg == NULL)
909 break;
910 *(pz_scan++) = ' ';
911 pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
912 parg_size - (pz_scan - pz_cmd) );
913 /*
914 * Make sure we don't overflow the buffer due to sloppy
915 * size estimation.
916 */
917 while (pz_scan == (char*)NULL)
918 {
919 size_t already_filled = pz_scan_save - pz_cmd;
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000920 pz_cmd = xrealloc (pz_cmd, argsize += 100);
Bruce Korb62a99402000-08-04 14:16:57 +0000921 pz_scan_save = pz_scan = pz_cmd + already_filled;
922 parg_size += 100;
923 pz_scan = make_raw_shell_str( pz_scan, pArg,
924 parg_size - (pz_scan - pz_cmd) );
925 }
926 }
927
928 /*
929 * add the file machinations.
930 */
Bruce Korb6047d502000-12-07 01:32:11 +0000931#ifdef __MSDOS__
Daniel Berlin283da1d2000-12-02 19:46:32 +0000932 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
933#else
934 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
935 pz_temp_file, pz_temp_file, pz_temp_file);
936#endif
Bruce Korb62a99402000-08-04 14:16:57 +0000937 }
938 system( pz_cmd );
939 free( (void*)pz_cmd );
940}
941
Bruce Korbbb786201999-06-02 07:08:54 +0000942/* * * * * * * * * * * * *
943
944 This loop should only cycle for 1/2 of one loop.
945 "chain_open" starts a process that uses "read_fd" as
946 its stdin and returns the new fd this process will use
947 for stdout. */
948
Daniel Berlin283da1d2000-12-02 19:46:32 +0000949#else /* is *NOT* SEPARATE_FIX_PROC */
Bruce Korb6864a6c2000-12-02 19:01:16 +0000950static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000951start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
Bruce Korbbb786201999-06-02 07:08:54 +0000952{
Bruce Korbbb786201999-06-02 07:08:54 +0000953 tCC* pz_cmd_save;
954 char* pz_cmd;
955
Bruce Korb5abc1f71999-10-12 14:44:18 +0000956 if ((p_fixd->fd_flags & FD_SUBROUTINE) != 0)
957 return internal_fix (read_fd, p_fixd);
958
Bruce Korbbb786201999-06-02 07:08:54 +0000959 if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0)
James A. Morrison9cdfc8e2004-01-27 19:10:10 +0000960 {
961 pz_cmd = NULL;
962 pz_cmd_save = NULL;
963 }
Bruce Korbbb786201999-06-02 07:08:54 +0000964 else
965 {
966 tSCC z_cmd_fmt[] = "file='%s'\n%s";
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000967 pz_cmd = XNEWVEC (char, strlen (p_fixd->patch_args[2])
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000968 + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
Bruce Korb5abc1f71999-10-12 14:44:18 +0000969 sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
Bruce Korbbb786201999-06-02 07:08:54 +0000970 pz_cmd_save = p_fixd->patch_args[2];
971 p_fixd->patch_args[2] = pz_cmd;
972 }
973
Bruce Korbb35926b1999-11-11 14:57:55 +0000974 /* Start a fix process, handing off the previous read fd for its
975 stdin and getting a new fd that reads from the fix process' stdout.
976 We normally will not loop, but we will up to 10 times if we keep
977 getting "EAGAIN" errors.
978
979 */
Bruce Korbbb786201999-06-02 07:08:54 +0000980 for (;;)
981 {
982 static int failCt = 0;
983 int fd;
984
985 fd = chain_open (read_fd,
Bruce Korb2629a112000-12-13 20:07:46 +0000986 (tCC **) p_fixd->patch_args,
Bruce Korbbb786201999-06-02 07:08:54 +0000987 (process_chain_head == -1)
988 ? &process_chain_head : (pid_t *) NULL);
989
990 if (fd != -1)
991 {
992 read_fd = fd;
993 break;
994 }
995
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000996 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
Bruce Korbbb786201999-06-02 07:08:54 +0000997 p_fixd->fix_name);
998
999 if ((errno != EAGAIN) || (++failCt > 10))
1000 exit (EXIT_FAILURE);
1001 sleep (1);
1002 }
1003
Bruce Korbb35926b1999-11-11 14:57:55 +00001004 /* IF we allocated a shell script command,
1005 THEN free it and restore the command format to the fix description */
Bruce Korbbb786201999-06-02 07:08:54 +00001006 if (pz_cmd != (char*)NULL)
1007 {
1008 free ((void*)pz_cmd);
1009 p_fixd->patch_args[2] = pz_cmd_save;
1010 }
1011
1012 return read_fd;
1013}
Bruce Korb62a99402000-08-04 14:16:57 +00001014#endif
Bruce Korbbb786201999-06-02 07:08:54 +00001015
Bruce Korb5abc1f71999-10-12 14:44:18 +00001016
1017/* * * * * * * * * * * * *
Bruce Korb401be4b2007-01-06 18:03:50 +00001018 *
1019 * Process the potential fixes for a particular include file.
1020 * Input: the original text of the file and the file's name
1021 * Result: none. A new file may or may not be created.
1022 */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001023static t_bool
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001024fix_applies (tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001025{
Zack Weinbergae5c8392000-01-22 20:55:18 +00001026 const char *pz_fname = pz_curr_file;
1027 const char *pz_scan = p_fixd->file_list;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001028 int test_ct;
1029 tTestDesc *p_test;
1030
Bruce Korb401be4b2007-01-06 18:03:50 +00001031#ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +00001032 /*
1033 * There is only one fix that uses a shell script as of this writing.
1034 * I hope to nuke it anyway, it does not apply to DOS and it would
1035 * be painful to implement. Therefore, no "shell" fixes for DOS.
1036 */
1037 if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
1038 return BOOL_FALSE;
Bruce Korb401be4b2007-01-06 18:03:50 +00001039#else
Bruce Korb5abc1f71999-10-12 14:44:18 +00001040 if (p_fixd->fd_flags & FD_SKIP_TEST)
1041 return BOOL_FALSE;
Bruce Korb401be4b2007-01-06 18:03:50 +00001042#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001043
1044 /* IF there is a file name restriction,
1045 THEN ensure the current file name matches one in the pattern */
1046
Zack Weinbergae5c8392000-01-22 20:55:18 +00001047 if (pz_scan != (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001048 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001049 while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
1050 pz_fname += 2;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001051
1052 for (;;)
1053 {
Bruce Korb401be4b2007-01-06 18:03:50 +00001054 if (fnmatch (pz_scan, pz_fname, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001055 break;
Bruce Korb401be4b2007-01-06 18:03:50 +00001056 pz_scan += strlen (pz_scan) + 1;
1057 if (*pz_scan == NUL)
1058 return BOOL_FALSE;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001059 }
1060 }
1061
1062 /* FOR each test, see if it fails.
1063 IF it does fail, then we go on to the next test */
1064
1065 for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
1066 test_ct-- > 0;
1067 p_test++)
1068 {
1069 switch (p_test->type)
1070 {
1071 case TT_TEST:
Bruce Korbb35926b1999-11-11 14:57:55 +00001072 if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
1073#ifdef DEBUG
1074 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001075 fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
1076 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001077#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001078 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001079 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001080 break;
1081
1082 case TT_EGREP:
Bruce Korbb35926b1999-11-11 14:57:55 +00001083 if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
1084#ifdef DEBUG
1085 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001086 fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
1087 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001088#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001089 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001090 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001091 break;
1092
1093 case TT_NEGREP:
Bruce Korbb35926b1999-11-11 14:57:55 +00001094 if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
1095#ifdef DEBUG
1096 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001097 fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
1098 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001099#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001100 /* Negated sense */
1101 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001102 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001103 break;
1104
1105 case TT_FUNCTION:
1106 if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
Bruce Korbb35926b1999-11-11 14:57:55 +00001107 != APPLY_FIX) {
1108#ifdef DEBUG
1109 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001110 fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
1111 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001112#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001113 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001114 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001115 break;
1116 }
1117 }
1118
1119 return BOOL_TRUE;
1120}
1121
1122
1123/* * * * * * * * * * * * *
1124
1125 Write out a replacement file */
1126
Bruce Korb6864a6c2000-12-02 19:01:16 +00001127static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001128write_replacement (tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001129{
1130 const char* pz_text = p_fixd->patch_args[0];
1131
1132 if ((pz_text == (char*)NULL) || (*pz_text == NUL))
1133 return;
1134
1135 {
Bruce Korb6864a6c2000-12-02 19:01:16 +00001136 FILE* out_fp = create_file ();
Bruce Korb66f788b2005-11-25 05:57:10 +00001137 size_t sz = strlen (pz_text);
1138 fwrite (pz_text, sz, 1, out_fp);
1139 if (pz_text[ sz-1 ] != '\n')
1140 fputc ('\n', out_fp);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001141 fclose (out_fp);
1142 }
1143}
1144
1145
1146/* * * * * * * * * * * * *
1147
1148 We have work to do. Read back in the output
1149 of the filtering chain. Compare each byte as we read it with
1150 the contents of the original file. As soon as we find any
1151 difference, we will create the output file, write out all
1152 the matched text and then copy any remaining data from the
1153 output of the filter chain.
1154 */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001155static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001156test_for_changes (int read_fd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001157{
1158 FILE *in_fp = fdopen (read_fd, "r");
1159 FILE *out_fp = (FILE *) NULL;
Bruce Korb90376ae2001-07-21 04:08:29 +00001160 unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001161
1162#ifdef DO_STATS
1163 fixed_ct++;
1164#endif
1165 for (;;)
1166 {
1167 int ch;
1168
1169 ch = getc (in_fp);
1170 if (ch == EOF)
1171 break;
Bruce Korb90376ae2001-07-21 04:08:29 +00001172 ch &= 0xFF; /* all bytes are 8 bits */
Bruce Korb5abc1f71999-10-12 14:44:18 +00001173
1174 /* IF we are emitting the output
1175 THEN emit this character, too.
1176 */
1177 if (out_fp != (FILE *) NULL)
1178 putc (ch, out_fp);
1179
1180 /* ELSE if this character does not match the original,
1181 THEN now is the time to start the output.
1182 */
1183 else if (ch != *pz_cmp)
1184 {
Bruce Korb6864a6c2000-12-02 19:01:16 +00001185 out_fp = create_file ();
Bruce Korb5abc1f71999-10-12 14:44:18 +00001186
1187#ifdef DO_STATS
1188 altered_ct++;
1189#endif
1190 /* IF there are matched data, write the matched part now. */
Bruce Korbc8b0c192001-07-21 04:20:08 +00001191 if ((char*)pz_cmp != pz_curr_data)
1192 fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
1193 1, out_fp);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001194
1195 /* Emit the current unmatching character */
1196 putc (ch, out_fp);
1197 }
1198 else
1199 /* ELSE the character matches. Advance the compare ptr */
1200 pz_cmp++;
1201 }
1202
1203 /* IF we created the output file, ... */
1204 if (out_fp != (FILE *) NULL)
1205 {
1206 regmatch_t match;
1207
1208 /* Close the file and see if we have to worry about
1209 `#include "file.h"' constructs. */
1210 fclose (out_fp);
Zack Weinbergab747402003-07-08 20:42:19 +00001211 if (xregexec (&incl_quote_re, pz_curr_data, 1, &match, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001212 extract_quoted_files (pz_curr_data, pz_curr_file, &match);
1213 }
1214
1215 fclose (in_fp);
1216 close (read_fd); /* probably redundant, but I'm paranoid */
1217}
1218
1219
Bruce Korb1f414ac1999-03-03 07:41:52 +00001220/* * * * * * * * * * * * *
1221
1222 Process the potential fixes for a particular include file.
1223 Input: the original text of the file and the file's name
1224 Result: none. A new file may or may not be created. */
1225
Bruce Korb0083c901998-10-16 07:00:18 +00001226void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001227process (void)
Bruce Korb0083c901998-10-16 07:00:18 +00001228{
Bruce Korb1f414ac1999-03-03 07:41:52 +00001229 tFixDesc *p_fixd = fixDescList;
1230 int todo_ct = FIX_COUNT;
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001231 int read_fd = -1;
Daniel Berlin283da1d2000-12-02 19:46:32 +00001232# ifndef SEPARATE_FIX_PROC
Rainer Orth9f8eec31999-05-17 12:39:19 +00001233 int num_children = 0;
Daniel Berlin283da1d2000-12-02 19:46:32 +00001234# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +00001235 char* pz_file_source = pz_curr_file;
1236# endif
Bruce Korb1f414ac1999-03-03 07:41:52 +00001237
Bruce Korb5abc1f71999-10-12 14:44:18 +00001238 if (access (pz_curr_file, R_OK) != 0)
1239 {
1240 int erno = errno;
1241 fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
1242 pz_curr_file, getcwd ((char *) NULL, MAXPATHLEN),
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001243 erno, xstrerror (erno));
Bruce Korb5abc1f71999-10-12 14:44:18 +00001244 return;
1245 }
1246
1247 pz_curr_data = load_file (pz_curr_file);
1248 if (pz_curr_data == (char *) NULL)
1249 return;
1250
1251#ifdef DO_STATS
1252 process_ct++;
1253#endif
Zack Weinbergd7eb5a41999-12-17 21:49:30 +00001254 if (VLEVEL( VERB_PROGRESS ) && have_tty)
Richard Henderson1c99d802003-01-21 17:02:51 -08001255 fprintf (stderr, "%6lu %-50s \r",
1256 (unsigned long) data_map_size, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001257
Daniel Berlin283da1d2000-12-02 19:46:32 +00001258# ifndef SEPARATE_FIX_PROC
Bruce Korb1f414ac1999-03-03 07:41:52 +00001259 process_chain_head = NOPROCESS;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001260
Bruce Korb1f414ac1999-03-03 07:41:52 +00001261 /* For every fix in our fix list, ... */
1262 for (; todo_ct > 0; p_fixd++, todo_ct--)
Bruce Korb0083c901998-10-16 07:00:18 +00001263 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001264 if (! fix_applies (p_fixd))
Bruce Korb0083c901998-10-16 07:00:18 +00001265 continue;
1266
Bruce Korbb35926b1999-11-11 14:57:55 +00001267 if (VLEVEL( VERB_APPLIES ))
1268 fprintf (stderr, "Applying %-24s to %s\n",
1269 p_fixd->fix_name, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001270
1271 if (p_fixd->fd_flags & FD_REPLACEMENT)
1272 {
1273 write_replacement (p_fixd);
1274 UNLOAD_DATA();
1275 return;
1276 }
Bruce Korb1f414ac1999-03-03 07:41:52 +00001277
1278 /* IF we do not have a read pointer,
1279 THEN this is the first fix for the current file.
1280 Open the source file. That will be used as stdin for
1281 the first fix. Any subsequent fixes will use the
Bruce Korb5abc1f71999-10-12 14:44:18 +00001282 stdout descriptor of the previous fix for its stdin. */
Bruce Korb1f414ac1999-03-03 07:41:52 +00001283
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001284 if (read_fd == -1)
Bruce Korb0083c901998-10-16 07:00:18 +00001285 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001286 read_fd = open (pz_curr_file, O_RDONLY);
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001287 if (read_fd < 0)
Bruce Korb0083c901998-10-16 07:00:18 +00001288 {
Bruce Korb1f414ac1999-03-03 07:41:52 +00001289 fprintf (stderr, "Error %d (%s) opening %s\n", errno,
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001290 xstrerror (errno), pz_curr_file);
Bruce Korb1f414ac1999-03-03 07:41:52 +00001291 exit (EXIT_FAILURE);
Bruce Korb0083c901998-10-16 07:00:18 +00001292 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001293
1294 /* Ensure we do not get duplicate output */
1295
1296 fflush (stdout);
Bruce Korb0083c901998-10-16 07:00:18 +00001297 }
1298
Bruce Korb5abc1f71999-10-12 14:44:18 +00001299 read_fd = start_fixer (read_fd, p_fixd, pz_curr_file);
Bruce Korbbb786201999-06-02 07:08:54 +00001300 num_children++;
Bruce Korb0083c901998-10-16 07:00:18 +00001301 }
1302
Bruce Korb5abc1f71999-10-12 14:44:18 +00001303 /* IF we have a read-back file descriptor,
1304 THEN check for changes and write output if changed. */
Bruce Korb1f414ac1999-03-03 07:41:52 +00001305
Bruce Korb5abc1f71999-10-12 14:44:18 +00001306 if (read_fd >= 0)
1307 {
1308 test_for_changes (read_fd);
1309#ifdef DO_STATS
1310 apply_ct += num_children;
1311#endif
1312 /* Wait for child processes created by chain_open()
1313 to avoid leaving zombies. */
1314 do {
1315 wait ((int *) NULL);
1316 } while (--num_children > 0);
1317 }
Bruce Korb0083c901998-10-16 07:00:18 +00001318
Daniel Berlin283da1d2000-12-02 19:46:32 +00001319# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +00001320
1321 for (; todo_ct > 0; p_fixd++, todo_ct--)
1322 {
1323 if (! fix_applies (p_fixd))
1324 continue;
1325
1326 if (VLEVEL( VERB_APPLIES ))
1327 fprintf (stderr, "Applying %-24s to %s\n",
1328 p_fixd->fix_name, pz_curr_file);
1329
1330 if (p_fixd->fd_flags & FD_REPLACEMENT)
1331 {
1332 write_replacement (p_fixd);
1333 UNLOAD_DATA();
1334 return;
1335 }
1336 fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
1337 pz_file_source = pz_temp_file;
1338 }
1339
Daniel Berlin283da1d2000-12-02 19:46:32 +00001340 read_fd = open (pz_temp_file, O_RDONLY);
1341 if (read_fd < 0)
1342 {
Bruce Korbca21b4a2001-02-06 22:19:50 +00001343 if (errno != ENOENT)
1344 fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
1345 errno, xstrerror (errno), pz_temp_file);
Daniel Berlin283da1d2000-12-02 19:46:32 +00001346 }
1347 else
1348 {
1349 test_for_changes (read_fd);
1350 /* Unlinking a file while it is still open is a Bad Idea on
1351 DOS/Windows. */
1352 close (read_fd);
1353 unlink (pz_temp_file);
1354 }
Bruce Korb62a99402000-08-04 14:16:57 +00001355
1356# endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001357 UNLOAD_DATA();
Bruce Korb0083c901998-10-16 07:00:18 +00001358}