blob: 8bd43dcb748f5e58c32da3e3cbd5c1a1a8d42bbc [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
Paolo Bonziniad643a72004-10-15 07:58:38 +00005 Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
Bruce Korb1f414ac1999-03-03 07:41:52 +00006
Nathanael Nerode6e6a1682003-05-23 20:48:48 +00007This file is part of GCC.
Bruce Korb1f414ac1999-03-03 07:41:52 +00008
Nathanael Nerode6e6a1682003-05-23 20:48:48 +00009GCC is free software; you can redistribute it and/or modify
Bruce Korb1f414ac1999-03-03 07:41:52 +000010it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
Nathanael Nerode6e6a1682003-05-23 20:48:48 +000014GCC is distributed in the hope that it will be useful,
Bruce Korb1f414ac1999-03-03 07:41:52 +000015but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
Nathanael Nerode6e6a1682003-05-23 20:48:48 +000020along with GCC; see the file COPYING. If not, write to
Bruce Korb1f414ac1999-03-03 07:41:52 +000021the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
23
Bruce Korb5abc1f71999-10-12 14:44:18 +000024#include "fixlib.h"
Bruce Korb1f414ac1999-03-03 07:41:52 +000025
Paolo Bonziniad643a72004-10-15 07:58:38 +000026#include <sys/stat.h>
27
Bruce Korb1e570a62000-09-05 22:28:04 +000028#if defined( HAVE_MMAP_FILE )
Philippe De Muyter99d525c1999-11-01 19:14:50 +010029#include <sys/mman.h>
30#define BAD_ADDR ((void*)-1)
31#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +000032
Daniel Berlin283da1d2000-12-02 19:46:32 +000033#ifndef SEPARATE_FIX_PROC
Bruce Korb0083c901998-10-16 07:00:18 +000034#include "server.h"
Bruce Korb62a99402000-08-04 14:16:57 +000035#endif
Bruce Korb0083c901998-10-16 07:00:18 +000036
Bruce Korb5abc1f71999-10-12 14:44:18 +000037/* The contents of this string are not very important. It is mostly
38 just used as part of the "I am alive and working" test. */
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +000039
Bruce Korb5abc1f71999-10-12 14:44:18 +000040static const char program_id[] = "fixincl version 1.1";
Bruce Korb0083c901998-10-16 07:00:18 +000041
Bruce Korbe02ecf32000-07-19 14:10:41 +000042/* This format will be used at the start of every generated file */
43
44static const char z_std_preamble[] =
45"/* DO NOT EDIT THIS FILE.\n\n\
46 It has been auto-edited by fixincludes from:\n\n\
47\t\"%s/%s\"\n\n\
48 This had to be done to correct non-standard usages in the\n\
49 original, manufacturer supplied header file. */\n\n";
50
Bruce Korb7d9ccd91999-03-31 11:51:29 +000051int find_base_len = 0;
Bruce Korb0083c901998-10-16 07:00:18 +000052
Bruce Korbb35926b1999-11-11 14:57:55 +000053typedef enum {
54 VERB_SILENT = 0,
55 VERB_FIXES,
56 VERB_APPLIES,
57 VERB_PROGRESS,
58 VERB_TESTS,
59 VERB_EVERYTHING
60} te_verbose;
61
62te_verbose verbose_level = VERB_PROGRESS;
Zack Weinbergd7eb5a41999-12-17 21:49:30 +000063int have_tty = 0;
Bruce Korbb35926b1999-11-11 14:57:55 +000064
John David Anglindbbbbf32001-03-02 21:41:37 +000065#define VLEVEL(l) ((unsigned int) verbose_level >= (unsigned int) l)
Bruce Korbb35926b1999-11-11 14:57:55 +000066#define NOT_SILENT VLEVEL(VERB_FIXES)
67
Bruce Korb1f414ac1999-03-03 07:41:52 +000068pid_t process_chain_head = (pid_t) -1;
Bruce Korb0083c901998-10-16 07:00:18 +000069
Bruce Korb5abc1f71999-10-12 14:44:18 +000070char* pz_curr_file; /* name of the current file under test/fix */
71char* pz_curr_data; /* original contents of that file */
Bruce Korb62a99402000-08-04 14:16:57 +000072char* pz_temp_file; /* for DOS, a place to stash the temporary
73 fixed data between system(3) calls */
Bruce Korb5abc1f71999-10-12 14:44:18 +000074t_bool curr_data_mapped;
75int data_map_fd;
76size_t data_map_size;
77size_t ttl_data_size = 0;
Bruce Korbe02ecf32000-07-19 14:10:41 +000078
Bruce Korb5abc1f71999-10-12 14:44:18 +000079#ifdef DO_STATS
80int process_ct = 0;
81int apply_ct = 0;
82int fixed_ct = 0;
83int altered_ct = 0;
84#endif /* DO_STATS */
85
Bruce Korb1f414ac1999-03-03 07:41:52 +000086const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
Bruce Korb5abc1f71999-10-12 14:44:18 +000087tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
Bruce Korb1f414ac1999-03-03 07:41:52 +000088regex_t incl_quote_re;
Bruce Korb0083c901998-10-16 07:00:18 +000089
Nathanael Nerodef4dbf932003-08-01 23:07:04 +000090static void do_version (void) ATTRIBUTE_NORETURN;
91char *load_file (const char *);
92void run_compiles (void);
93void initialize (int argc, char** argv);
94void process (void);
Bruce Korb5abc1f71999-10-12 14:44:18 +000095
96/* External Source Code */
Bruce Korb0083c901998-10-16 07:00:18 +000097
98#include "fixincl.x"
99
Bruce Korb1f414ac1999-03-03 07:41:52 +0000100/* * * * * * * * * * * * * * * * * * *
101 *
102 * MAIN ROUTINE
103 */
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000104extern int main (int, char **);
Bruce Korb0083c901998-10-16 07:00:18 +0000105int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000106main (int argc, char** argv)
Bruce Korb0083c901998-10-16 07:00:18 +0000107{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000108 char *file_name_buf;
Bruce Korb0083c901998-10-16 07:00:18 +0000109
Bruce Korb35dfe412000-05-11 13:41:12 +0000110 initialize ( argc, argv );
Bruce Korbd1c6a031999-04-26 10:38:38 +0000111
Zack Weinbergd7eb5a41999-12-17 21:49:30 +0000112 have_tty = isatty (fileno (stderr));
113
Bruce Korb5abc1f71999-10-12 14:44:18 +0000114 /* Before anything else, ensure we can allocate our file name buffer. */
115 file_name_buf = load_file_data (stdin);
116
117 /* Because of the way server shells work, you have to keep stdin, out
118 and err open so that the proper input file does not get closed
119 by accident */
120
121 freopen ("/dev/null", "r", stdin);
122
123 if (file_name_buf == (char *) NULL)
124 {
125 fputs ("No file names listed for fixing\n", stderr);
126 exit (EXIT_FAILURE);
127 }
128
Bruce Korbd1c6a031999-04-26 10:38:38 +0000129 for (;;)
130 {
Bruce Korb5abc1f71999-10-12 14:44:18 +0000131 char* pz_end;
Bruce Korbd1c6a031999-04-26 10:38:38 +0000132
Bruce Korb5abc1f71999-10-12 14:44:18 +0000133 /* skip to start of name, past any "./" prefixes */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000134
Bruce Korb5abc1f71999-10-12 14:44:18 +0000135 while (ISSPACE (*file_name_buf)) file_name_buf++;
136 while ((file_name_buf[0] == '.') && (file_name_buf[1] == '/'))
137 file_name_buf += 2;
Bruce Korbd1c6a031999-04-26 10:38:38 +0000138
Bruce Korb5abc1f71999-10-12 14:44:18 +0000139 /* Check for end of list */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000140
Bruce Korb5abc1f71999-10-12 14:44:18 +0000141 if (*file_name_buf == NUL)
142 break;
143
144 /* Set global file name pointer and find end of name */
145
146 pz_curr_file = file_name_buf;
147 pz_end = strchr( pz_curr_file, '\n' );
148 if (pz_end == (char*)NULL)
149 pz_end = file_name_buf = pz_curr_file + strlen (pz_curr_file);
150 else
151 file_name_buf = pz_end + 1;
152
153 while ((pz_end > pz_curr_file) && ISSPACE( pz_end[-1])) pz_end--;
154
155 /* IF no name is found (blank line) or comment marker, skip line */
156
157 if ((pz_curr_file == pz_end) || (*pz_curr_file == '#'))
158 continue;
159 *pz_end = NUL;
160
Bruce Korb5abc1f71999-10-12 14:44:18 +0000161 process ();
Bruce Korb5abc1f71999-10-12 14:44:18 +0000162 } /* for (;;) */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000163
Bruce Korb5abc1f71999-10-12 14:44:18 +0000164#ifdef DO_STATS
Bruce Korbb35926b1999-11-11 14:57:55 +0000165 if (VLEVEL( VERB_PROGRESS )) {
Bruce Korb5abc1f71999-10-12 14:44:18 +0000166 tSCC zFmt[] =
167 "\
168Processed %5d files containing %d bytes \n\
169Applying %5d fixes to %d files\n\
170Altering %5d of them\n";
Bruce Korbd1c6a031999-04-26 10:38:38 +0000171
Bruce Korb5abc1f71999-10-12 14:44:18 +0000172 fprintf (stderr, zFmt, process_ct, ttl_data_size, apply_ct,
173 fixed_ct, altered_ct);
174 }
175#endif /* DO_STATS */
Bruce Korb62a99402000-08-04 14:16:57 +0000176
Daniel Berlin283da1d2000-12-02 19:46:32 +0000177# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000178 unlink( pz_temp_file );
179# endif
Bruce Korb15fe1a72001-01-05 16:28:58 +0000180 exit (EXIT_SUCCESS);
Bruce Korbd1c6a031999-04-26 10:38:38 +0000181}
182
183
Bruce Korb6864a6c2000-12-02 19:01:16 +0000184static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000185do_version (void)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000186{
187 static const char zFmt[] = "echo '%s'";
188 char zBuf[ 1024 ];
189
190 /* The 'version' option is really used to test that:
191 1. The program loads correctly (no missing libraries)
Bruce Korb35dfe412000-05-11 13:41:12 +0000192 2. that we can compile all the regular expressions.
193 3. we can correctly run our server shell process
Bruce Korb5abc1f71999-10-12 14:44:18 +0000194 */
195 run_compiles ();
196 sprintf (zBuf, zFmt, program_id);
Daniel Berlin283da1d2000-12-02 19:46:32 +0000197#ifndef SEPARATE_FIX_PROC
Bruce Korb6b151aa2000-05-04 14:55:00 +0000198 puts (zBuf + 5);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000199 exit (strcmp (run_shell (zBuf), program_id));
Bruce Korb62a99402000-08-04 14:16:57 +0000200#else
201 exit (system (zBuf));
202#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +0000203}
204
Bruce Korbd1c6a031999-04-26 10:38:38 +0000205/* * * * * * * * * * * * */
206
207void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000208initialize ( int argc, char** argv )
Bruce Korbd1c6a031999-04-26 10:38:38 +0000209{
Bruce Korb878a5792000-07-12 14:45:05 +0000210 xmalloc_set_program_name (argv[0]);
211
Bruce Korb35dfe412000-05-11 13:41:12 +0000212 switch (argc)
213 {
214 case 1:
215 break;
216
217 case 2:
218 if (strcmp (argv[1], "-v") == 0)
219 do_version ();
220 if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
221 {
222 fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
223 errno, xstrerror (errno), argv[1] );
224 exit (EXIT_FAILURE);
225 }
226 break;
227
228 default:
229 fputs ("fixincl ERROR: too many command line arguments\n", stderr);
230 exit (EXIT_FAILURE);
231 }
232
Bruce Korb798bdf72001-03-16 00:58:40 +0000233#ifdef SIGCHLD
234 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
235 receive the signal. A different setting is inheritable */
236 signal (SIGCHLD, SIG_DFL);
237#endif
238
Paolo Bonziniad643a72004-10-15 07:58:38 +0000239 initialize_opts ();
Bruce Korb0083c901998-10-16 07:00:18 +0000240
Bruce Korb6864a6c2000-12-02 19:01:16 +0000241 if (ISDIGIT ( *pz_verbose ))
Bruce Korbe02ecf32000-07-19 14:10:41 +0000242 verbose_level = (te_verbose)atoi( pz_verbose );
243 else
244 switch (*pz_verbose) {
245 case 's':
246 case 'S':
247 verbose_level = VERB_SILENT; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000248
Bruce Korbe02ecf32000-07-19 14:10:41 +0000249 case 'f':
250 case 'F':
251 verbose_level = VERB_FIXES; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000252
Bruce Korbe02ecf32000-07-19 14:10:41 +0000253 case 'a':
254 case 'A':
255 verbose_level = VERB_APPLIES; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000256
DJ Delorie7a9cdb12003-03-22 16:51:04 -0500257 default:
Bruce Korbe02ecf32000-07-19 14:10:41 +0000258 case 'p':
259 case 'P':
260 verbose_level = VERB_PROGRESS; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000261
Bruce Korbe02ecf32000-07-19 14:10:41 +0000262 case 't':
263 case 'T':
264 verbose_level = VERB_TESTS; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000265
Bruce Korbe02ecf32000-07-19 14:10:41 +0000266 case 'e':
267 case 'E':
268 verbose_level = VERB_EVERYTHING; break;
269 }
DJ Delorie7a9cdb12003-03-22 16:51:04 -0500270 if (verbose_level >= VERB_EVERYTHING) {
271 verbose_level = VERB_EVERYTHING;
272 fputs ("fixinc verbosity: EVERYTHING\n", stderr);
273 }
274 while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
275 pz_find_base += 2;
276 if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
277 find_base_len = strlen( pz_find_base );
Bruce Korb7d9ccd91999-03-31 11:51:29 +0000278
Bruce Korb1f414ac1999-03-03 07:41:52 +0000279 /* Compile all the regular expressions now.
280 That way, it is done only once for the whole run.
281 */
282 run_compiles ();
Bruce Korb0083c901998-10-16 07:00:18 +0000283
Daniel Berlin283da1d2000-12-02 19:46:32 +0000284# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000285 /* NULL as the first argument to `tempnam' causes it to DTRT
286 wrt the temporary directory where the file will be created. */
287 pz_temp_file = tempnam( NULL, "fxinc" );
288# endif
289
Bruce Korb1f414ac1999-03-03 07:41:52 +0000290 signal (SIGQUIT, SIG_IGN);
291 signal (SIGIOT, SIG_IGN);
292 signal (SIGPIPE, SIG_IGN);
293 signal (SIGALRM, SIG_IGN);
294 signal (SIGTERM, SIG_IGN);
Bruce Korbd1c6a031999-04-26 10:38:38 +0000295}
Bruce Korb0083c901998-10-16 07:00:18 +0000296
Bruce Korb1f414ac1999-03-03 07:41:52 +0000297/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000298
Bruce Korb1f414ac1999-03-03 07:41:52 +0000299 load_file loads all the contents of a file into malloc-ed memory.
300 Its argument is the name of the file to read in; the returned
301 result is the NUL terminated contents of the file. The file
302 is presumed to be an ASCII text file containing no NULs. */
Bruce Korb0083c901998-10-16 07:00:18 +0000303char *
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000304load_file ( const char* fname )
Bruce Korb0083c901998-10-16 07:00:18 +0000305{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000306 struct stat stbf;
307 char* res;
Bruce Korb0083c901998-10-16 07:00:18 +0000308
Bruce Korb5abc1f71999-10-12 14:44:18 +0000309 if (stat (fname, &stbf) != 0)
Bruce Korb0083c901998-10-16 07:00:18 +0000310 {
Bruce Korbb35926b1999-11-11 14:57:55 +0000311 if (NOT_SILENT)
312 fprintf (stderr, "error %d (%s) stat-ing %s\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000313 errno, xstrerror (errno), fname );
Bruce Korb5abc1f71999-10-12 14:44:18 +0000314 return (char *) NULL;
315 }
316 if (stbf.st_size == 0)
317 return (char*)NULL;
318
Bruce Korba6efbec2000-09-05 18:29:56 +0000319 /* Make the data map size one larger than the file size for documentation
320 purposes. Truth is that there will be a following NUL character if
321 the file size is not a multiple of the page size. If it is a multiple,
322 then this adjustment sometimes fails anyway. */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000323 data_map_size = stbf.st_size+1;
324 data_map_fd = open (fname, O_RDONLY);
325 ttl_data_size += data_map_size-1;
326
327 if (data_map_fd < 0)
328 {
Bruce Korbb35926b1999-11-11 14:57:55 +0000329 if (NOT_SILENT)
330 fprintf (stderr, "error %d (%s) opening %s for read\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000331 errno, xstrerror (errno), fname);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000332 return (char*)NULL;
Bruce Korb0083c901998-10-16 07:00:18 +0000333 }
334
Zack Weinberg56f02b82000-04-17 17:25:57 +0000335#ifdef HAVE_MMAP_FILE
Bruce Korb5abc1f71999-10-12 14:44:18 +0000336 curr_data_mapped = BOOL_TRUE;
Bruce Korba6efbec2000-09-05 18:29:56 +0000337
338 /* IF the file size is a multiple of the page size,
339 THEN sometimes you will seg fault trying to access a trailing byte */
Bruce Korbdc465052000-09-05 22:26:16 +0000340 if ((stbf.st_size & (getpagesize()-1)) == 0)
Bruce Korba6efbec2000-09-05 18:29:56 +0000341 res = (char*)BAD_ADDR;
342 else
343 res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
344 MAP_PRIVATE, data_map_fd, 0);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000345 if (res == (char*)BAD_ADDR)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000346#endif
Bruce Korbca21b4a2001-02-06 22:19:50 +0000347 {
348 FILE* fp = fdopen (data_map_fd, "r");
349 curr_data_mapped = BOOL_FALSE;
350 res = load_file_data (fp);
351 fclose (fp);
352 }
Bruce Korb0083c901998-10-16 07:00:18 +0000353
Bruce Korb5abc1f71999-10-12 14:44:18 +0000354 return res;
Bruce Korb0083c901998-10-16 07:00:18 +0000355}
356
Bruce Korb6864a6c2000-12-02 19:01:16 +0000357static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000358machine_matches( tFixDesc* p_fixd )
Bruce Korb0083c901998-10-16 07:00:18 +0000359 {
Daniel Berlin283da1d2000-12-02 19:46:32 +0000360# ifndef SEPARATE_FIX_PROC
Bruce Korb5abc1f71999-10-12 14:44:18 +0000361 tSCC case_fmt[] = "case %s in\n"; /* 9 bytes, plus string */
Philippe De Muyter99d525c1999-11-01 19:14:50 +0100362 tSCC esac_fmt[] =
363 " )\n echo %s ;;\n* ) echo %s ;;\nesac";/* 4 bytes */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000364 tSCC skip[] = "skip"; /* 4 bytes */
365 tSCC run[] = "run"; /* 3 bytes */
366 /* total bytes to add to machine sum: 49 - see fixincl.tpl */
367
Bruce Korb1f414ac1999-03-03 07:41:52 +0000368 const char **papz_machs = p_fixd->papz_machs;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000369 char *pz;
Bruce Korb6864a6c2000-12-02 19:01:16 +0000370 const char *pz_sep = "";
Bruce Korb1f414ac1999-03-03 07:41:52 +0000371 tCC *pz_if_true;
372 tCC *pz_if_false;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000373 char cmd_buf[ MACH_LIST_SIZE_LIMIT ]; /* size lim from fixincl.tpl */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000374
Bruce Korb5abc1f71999-10-12 14:44:18 +0000375 /* Start the case statement */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000376
Bruce Korb5abc1f71999-10-12 14:44:18 +0000377 sprintf (cmd_buf, case_fmt, pz_machine);
378 pz = cmd_buf + strlen (cmd_buf);
Bruce Korb1f414ac1999-03-03 07:41:52 +0000379
Bruce Korb5abc1f71999-10-12 14:44:18 +0000380 /* Determine if a match means to apply the fix or not apply it */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000381
382 if (p_fixd->fd_flags & FD_MACH_IFNOT)
383 {
384 pz_if_true = skip;
385 pz_if_false = run;
386 }
387 else
388 {
389 pz_if_true = run;
390 pz_if_false = skip;
391 }
392
Bruce Korb5abc1f71999-10-12 14:44:18 +0000393 /* Emit all the machine names. If there are more than one,
394 then we will insert " | \\\n" between the names */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000395
396 for (;;)
397 {
398 const char* pz_mach = *(papz_machs++);
399
400 if (pz_mach == (const char*) NULL)
401 break;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000402 sprintf (pz, "%s%s", pz_sep, pz_mach);
Bruce Korb1f414ac1999-03-03 07:41:52 +0000403 pz += strlen (pz);
404 pz_sep = " | \\\n";
405 }
Bruce Korb5abc1f71999-10-12 14:44:18 +0000406
407 /* Now emit the match and not-match actions and the esac */
408
409 sprintf (pz, esac_fmt, pz_if_true, pz_if_false);
Bruce Korb1f414ac1999-03-03 07:41:52 +0000410
411 /* Run the script.
412 The result will start either with 's' or 'r'. */
413
Rainer Orth7d032a41999-05-07 11:09:31 +0000414 {
415 int skip;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000416 pz = run_shell (cmd_buf);
Rainer Orth7d032a41999-05-07 11:09:31 +0000417 skip = (*pz == 's');
418 free ( (void*)pz );
419 if (skip)
420 {
421 p_fixd->fd_flags |= FD_SKIP_TEST;
Bruce Korb62a99402000-08-04 14:16:57 +0000422 return BOOL_FALSE;
423 }
424 }
425
426 return BOOL_TRUE;
Daniel Berlin283da1d2000-12-02 19:46:32 +0000427# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +0000428 const char **papz_machs = p_fixd->papz_machs;
429 int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0;
430 for (;;)
431 {
432 const char* pz_mach = *(papz_machs++);
433
434 if (pz_mach == (const char*) NULL)
435 break;
436 if (strstr (pz_mach, "dos") != NULL && !invert)
437 return BOOL_TRUE;
438 }
439
440 p_fixd->fd_flags |= FD_SKIP_TEST;
441 return BOOL_FALSE;
442# endif
443}
444
445/* * * * * * * * * * * * *
446
447 run_compiles run all the regexp compiles for all the fixes once.
448 */
449void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000450run_compiles (void)
Bruce Korb62a99402000-08-04 14:16:57 +0000451{
452 tFixDesc *p_fixd = fixDescList;
453 int fix_ct = FIX_COUNT;
Kaveh R. Ghazi29da5c92003-08-11 21:47:39 +0000454 regex_t *p_re = xcalloc (REGEX_COUNT, sizeof (regex_t));
Bruce Korb62a99402000-08-04 14:16:57 +0000455
456 /* Make sure compile_re does not stumble across invalid data */
457
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000458 memset (&incl_quote_re, '\0', sizeof (regex_t));
Bruce Korb62a99402000-08-04 14:16:57 +0000459
460 compile_re (incl_quote_pat, &incl_quote_re, 1,
461 "quoted include", "run_compiles");
462
463 /* Allow machine name tests to be ignored (testing, mainly) */
464
465 if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
466 pz_machine = (char*)NULL;
467
468 /* FOR every fixup, ... */
469 do
470 {
471 tTestDesc *p_test = p_fixd->p_test_desc;
472 int test_ct = p_fixd->test_ct;
473
474 /* IF the machine type pointer is not NULL (we are not in test mode)
475 AND this test is for or not done on particular machines
476 THEN ... */
477
478 if ( (pz_machine != NULL)
479 && (p_fixd->papz_machs != (const char**) NULL)
480 && ! machine_matches (p_fixd) )
481 continue;
Bruce Korb1f414ac1999-03-03 07:41:52 +0000482
483 /* FOR every test for the fixup, ... */
484
485 while (--test_ct >= 0)
486 {
487 switch (p_test->type)
Bruce Korb0083c901998-10-16 07:00:18 +0000488 {
489 case TT_EGREP:
490 case TT_NEGREP:
Bruce Korb1f414ac1999-03-03 07:41:52 +0000491 p_test->p_test_regex = p_re++;
Bruce Korb35dfe412000-05-11 13:41:12 +0000492 compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
493 "select test", p_fixd->fix_name);
Bruce Korb3af556f2000-09-12 14:28:55 +0000494 default: break;
Bruce Korb35dfe412000-05-11 13:41:12 +0000495 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000496 p_test++;
Bruce Korb0083c901998-10-16 07:00:18 +0000497 }
498 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000499 while (p_fixd++, --fix_ct > 0);
Bruce Korb0083c901998-10-16 07:00:18 +0000500}
501
502
Bruce Korb1f414ac1999-03-03 07:41:52 +0000503/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000504
Bruce Korb1f414ac1999-03-03 07:41:52 +0000505 create_file Create the output modified file.
506 Input: the name of the file to create
507 Returns: a file pointer to the new, open file */
508
Bruce Korb063174e1999-11-04 14:50:44 +0000509#if defined(S_IRUSR) && defined(S_IWUSR) && \
510 defined(S_IRGRP) && defined(S_IROTH)
511
512# define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
513#else
514# define S_IRALL 0644
515#endif
516
517#if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
518 defined(S_IROTH) && defined(S_IXOTH)
519
520# define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
521#else
522# define S_DIRALL 0755
523#endif
524
Bruce Korb1f414ac1999-03-03 07:41:52 +0000525
Bruce Korb6864a6c2000-12-02 19:01:16 +0000526static FILE *
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000527create_file (void)
Bruce Korb0083c901998-10-16 07:00:18 +0000528{
529 int fd;
530 FILE *pf;
531 char fname[MAXPATHLEN];
532
Bruce Korb5abc1f71999-10-12 14:44:18 +0000533 sprintf (fname, "%s/%s", pz_dest_dir, pz_curr_file + find_base_len);
Bruce Korb0083c901998-10-16 07:00:18 +0000534
Bruce Korb1f414ac1999-03-03 07:41:52 +0000535 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
Bruce Korb0083c901998-10-16 07:00:18 +0000536
Bruce Korb1f414ac1999-03-03 07:41:52 +0000537 /* We may need to create the directories needed... */
Bruce Korb0083c901998-10-16 07:00:18 +0000538 if ((fd < 0) && (errno == ENOENT))
539 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000540 char *pz_dir = strchr (fname + 1, '/');
Bruce Korb0083c901998-10-16 07:00:18 +0000541 struct stat stbf;
542
Bruce Korb1f414ac1999-03-03 07:41:52 +0000543 while (pz_dir != (char *) NULL)
Bruce Korb0083c901998-10-16 07:00:18 +0000544 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000545 *pz_dir = NUL;
Bruce Korb0083c901998-10-16 07:00:18 +0000546 if (stat (fname, &stbf) < 0)
547 {
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600548#ifdef _WIN32
549 mkdir (fname);
550#else
Bruce Korb063174e1999-11-04 14:50:44 +0000551 mkdir (fname, S_IFDIR | S_DIRALL);
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600552#endif
Bruce Korb0083c901998-10-16 07:00:18 +0000553 }
554
Bruce Korb1f414ac1999-03-03 07:41:52 +0000555 *pz_dir = '/';
556 pz_dir = strchr (pz_dir + 1, '/');
Bruce Korb0083c901998-10-16 07:00:18 +0000557 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000558
559 /* Now, lets try the open again... */
560 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
Bruce Korb0083c901998-10-16 07:00:18 +0000561 }
562 if (fd < 0)
563 {
564 fprintf (stderr, "Error %d (%s) creating %s\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000565 errno, xstrerror (errno), fname);
Bruce Korb0083c901998-10-16 07:00:18 +0000566 exit (EXIT_FAILURE);
567 }
Bruce Korbb35926b1999-11-11 14:57:55 +0000568 if (NOT_SILENT)
569 fprintf (stderr, "Fixed: %s\n", pz_curr_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000570 pf = fdopen (fd, "w");
571
Bruce Korbe02ecf32000-07-19 14:10:41 +0000572 /*
573 * IF pz_machine is NULL, then we are in some sort of test mode.
574 * Do not insert the current directory name. Use a constant string.
575 */
576 fprintf (pf, z_std_preamble,
577 (pz_machine == NULL)
578 ? "fixinc/tests/inc"
579 : pz_input_dir,
580 pz_curr_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000581
Bruce Korb0083c901998-10-16 07:00:18 +0000582 return pf;
583}
584
Bruce Korb1f414ac1999-03-03 07:41:52 +0000585
586/* * * * * * * * * * * * *
587
588 test_test make sure a shell-style test expression passes.
589 Input: a pointer to the descriptor of the test to run and
590 the name of the file that we might want to fix
Bruce Korb5abc1f71999-10-12 14:44:18 +0000591 Result: APPLY_FIX or SKIP_FIX, depending on the result of the
Bruce Korb1f414ac1999-03-03 07:41:52 +0000592 shell script we run. */
Daniel Berlin283da1d2000-12-02 19:46:32 +0000593#ifndef SEPARATE_FIX_PROC
Bruce Korb6864a6c2000-12-02 19:01:16 +0000594static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000595test_test (tTestDesc* p_test, char* pz_test_file)
Bruce Korb0083c901998-10-16 07:00:18 +0000596{
Bruce Korb94db2f71999-05-12 07:32:58 +0000597 tSCC cmd_fmt[] =
598"file=%s\n\
599if ( test %s ) > /dev/null 2>&1\n\
600then echo TRUE\n\
601else echo FALSE\n\
602fi";
603
Bruce Korb1f414ac1999-03-03 07:41:52 +0000604 char *pz_res;
Bruce Korbe9099382000-05-17 14:56:13 +0000605 int res;
Bruce Korb0083c901998-10-16 07:00:18 +0000606
Bruce Korb1f414ac1999-03-03 07:41:52 +0000607 static char cmd_buf[4096];
Bruce Korb0083c901998-10-16 07:00:18 +0000608
Bruce Korb5abc1f71999-10-12 14:44:18 +0000609 sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
Bruce Korb1f414ac1999-03-03 07:41:52 +0000610 pz_res = run_shell (cmd_buf);
Bruce Korbe9099382000-05-17 14:56:13 +0000611
612 switch (*pz_res) {
613 case 'T':
Bruce Korb5abc1f71999-10-12 14:44:18 +0000614 res = APPLY_FIX;
Bruce Korbe9099382000-05-17 14:56:13 +0000615 break;
616
617 case 'F':
618 res = SKIP_FIX;
619 break;
620
621 default:
622 fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
623 pz_res, cmd_buf );
James A. Morrison9cdfc8e2004-01-27 19:10:10 +0000624 res = SKIP_FIX;
Bruce Korbe9099382000-05-17 14:56:13 +0000625 }
626
Bruce Korb1f414ac1999-03-03 07:41:52 +0000627 free ((void *) pz_res);
Bruce Korb0083c901998-10-16 07:00:18 +0000628 return res;
629}
Bruce Korb62a99402000-08-04 14:16:57 +0000630#else
631/*
632 * IF we are in MS-DOS land, then whatever shell-type test is required
633 * will, by definition, fail
634 */
635#define test_test(t,tf) SKIP_FIX
636#endif
Bruce Korb0083c901998-10-16 07:00:18 +0000637
Bruce Korb1f414ac1999-03-03 07:41:52 +0000638/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000639
Bruce Korb1f414ac1999-03-03 07:41:52 +0000640 egrep_test make sure an egrep expression is found in the file text.
641 Input: a pointer to the descriptor of the test to run and
642 the pointer to the contents of the file under suspicion
Bruce Korb5abc1f71999-10-12 14:44:18 +0000643 Result: APPLY_FIX if the pattern is found, SKIP_FIX otherwise
Bruce Korb1f414ac1999-03-03 07:41:52 +0000644
Bruce Korb5abc1f71999-10-12 14:44:18 +0000645 The caller may choose to reverse meaning if the sense of the test
Bruce Korb1f414ac1999-03-03 07:41:52 +0000646 is inverted. */
647
Bruce Korb6864a6c2000-12-02 19:01:16 +0000648static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000649egrep_test (char* pz_data, tTestDesc* p_test)
Bruce Korb0083c901998-10-16 07:00:18 +0000650{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000651#ifdef DEBUG
Bruce Korb1f414ac1999-03-03 07:41:52 +0000652 if (p_test->p_test_regex == 0)
653 fprintf (stderr, "fixincl ERROR RE not compiled: `%s'\n",
654 p_test->pz_test_text);
Bruce Korb0083c901998-10-16 07:00:18 +0000655#endif
Zack Weinbergab747402003-07-08 20:42:19 +0000656 if (xregexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000657 return APPLY_FIX;
658 return SKIP_FIX;
Bruce Korb0083c901998-10-16 07:00:18 +0000659}
660
661
Bruce Korb1f414ac1999-03-03 07:41:52 +0000662/* * * * * * * * * * * * *
Bruce Korb94db2f71999-05-12 07:32:58 +0000663
664 quoted_file_exists Make sure that a file exists before we emit
665 the file name. If we emit the name, our invoking shell will try
666 to copy a non-existing file into the destination directory. */
667
Bruce Korb6864a6c2000-12-02 19:01:16 +0000668static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000669quoted_file_exists (const char* pz_src_path,
670 const char* pz_file_path,
671 const char* pz_file)
Bruce Korb94db2f71999-05-12 07:32:58 +0000672{
673 char z[ MAXPATHLEN ];
674 char* pz;
675 sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
676 pz = z + strlen ( z );
677
678 for (;;) {
679 char ch = *pz_file++;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000680 if (! ISGRAPH( ch ))
Bruce Korb94db2f71999-05-12 07:32:58 +0000681 return 0;
682 if (ch == '"')
683 break;
684 *pz++ = ch;
685 }
686 *pz = '\0';
687 {
688 struct stat s;
689 if (stat (z, &s) != 0)
690 return 0;
691 return S_ISREG( s.st_mode );
692 }
693}
694
695
696/* * * * * * * * * * * * *
Bruce Korb1f414ac1999-03-03 07:41:52 +0000697 *
698 extract_quoted_files
Bruce Korb5abc1f71999-10-12 14:44:18 +0000699
Bruce Korb1f414ac1999-03-03 07:41:52 +0000700 The syntax, `#include "file.h"' specifies that the compiler is to
701 search the local directory of the current file before the include
702 list. Consequently, if we have modified a header and stored it in
703 another directory, any files that are included by that modified
704 file in that fashion must also be copied into this new directory.
705 This routine finds those flavors of #include and for each one found
706 emits a triple of:
Bruce Korb5abc1f71999-10-12 14:44:18 +0000707
Bruce Korb1f414ac1999-03-03 07:41:52 +0000708 1. source directory of the original file
709 2. the relative path file name of the #includ-ed file
710 3. the full destination path for this file
711
712 Input: the text of the file, the file name and a pointer to the
713 match list where the match information was stored.
714 Result: internally nothing. The results are written to stdout
715 for interpretation by the invoking shell */
Bruce Korb0083c901998-10-16 07:00:18 +0000716
Bruce Korb94db2f71999-05-12 07:32:58 +0000717
Bruce Korb6864a6c2000-12-02 19:01:16 +0000718static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000719extract_quoted_files (char* pz_data,
720 const char* pz_fixed_file,
721 regmatch_t* p_re_match)
Bruce Korb0083c901998-10-16 07:00:18 +0000722{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000723 char *pz_dir_end = strrchr (pz_fixed_file, '/');
Bruce Korb1f414ac1999-03-03 07:41:52 +0000724 char *pz_incl_quot = pz_data;
Bruce Korb0083c901998-10-16 07:00:18 +0000725
Bruce Korbb35926b1999-11-11 14:57:55 +0000726 if (VLEVEL( VERB_APPLIES ))
727 fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000728
Bruce Korb5abc1f71999-10-12 14:44:18 +0000729 /* Set "pz_fixed_file" to point to the containing subdirectory of the source
Bruce Korb94db2f71999-05-12 07:32:58 +0000730 If there is none, then it is in our current directory, ".". */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000731
732 if (pz_dir_end == (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000733 pz_fixed_file = ".";
Bruce Korb0083c901998-10-16 07:00:18 +0000734 else
Bruce Korb1f414ac1999-03-03 07:41:52 +0000735 *pz_dir_end = '\0';
Bruce Korb0083c901998-10-16 07:00:18 +0000736
737 for (;;)
738 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000739 pz_incl_quot += p_re_match->rm_so;
Bruce Korb0083c901998-10-16 07:00:18 +0000740
Bruce Korb1f414ac1999-03-03 07:41:52 +0000741 /* Skip forward to the included file name */
Zack Weinbergf6bbde22000-12-08 03:00:26 +0000742 while (*pz_incl_quot != '"')
Bruce Korb1f414ac1999-03-03 07:41:52 +0000743 pz_incl_quot++;
Bruce Korb0083c901998-10-16 07:00:18 +0000744
Bruce Korb5abc1f71999-10-12 14:44:18 +0000745 if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
Bruce Korb94db2f71999-05-12 07:32:58 +0000746 {
747 /* Print the source directory and the subdirectory
748 of the file in question. */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000749 printf ("%s %s/", pz_src_dir, pz_fixed_file);
Bruce Korb94db2f71999-05-12 07:32:58 +0000750 pz_dir_end = pz_incl_quot;
Bruce Korb0083c901998-10-16 07:00:18 +0000751
Bruce Korb94db2f71999-05-12 07:32:58 +0000752 /* Append to the directory the relative path of the desired file */
753 while (*pz_incl_quot != '"')
754 putc (*pz_incl_quot++, stdout);
Bruce Korb0083c901998-10-16 07:00:18 +0000755
Bruce Korb94db2f71999-05-12 07:32:58 +0000756 /* Now print the destination directory appended with the
757 relative path of the desired file */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000758 printf (" %s/%s/", pz_dest_dir, pz_fixed_file);
Bruce Korb94db2f71999-05-12 07:32:58 +0000759 while (*pz_dir_end != '"')
760 putc (*pz_dir_end++, stdout);
Bruce Korb0083c901998-10-16 07:00:18 +0000761
Bruce Korb94db2f71999-05-12 07:32:58 +0000762 /* End of entry */
763 putc ('\n', stdout);
764 }
Bruce Korb0083c901998-10-16 07:00:18 +0000765
Bruce Korb1f414ac1999-03-03 07:41:52 +0000766 /* Find the next entry */
Zack Weinbergab747402003-07-08 20:42:19 +0000767 if (xregexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
Bruce Korb0083c901998-10-16 07:00:18 +0000768 break;
769 }
770}
771
772
Bruce Korb5abc1f71999-10-12 14:44:18 +0000773/* * * * * * * * * * * * *
774
775 Somebody wrote a *_fix subroutine that we must call.
776 */
Daniel Berlin283da1d2000-12-02 19:46:32 +0000777#ifndef SEPARATE_FIX_PROC
Bruce Korb6864a6c2000-12-02 19:01:16 +0000778static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000779internal_fix (int read_fd, tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000780{
781 int fd[2];
782
783 if (pipe( fd ) != 0)
784 {
785 fprintf (stderr, "Error %d on pipe(2) call\n", errno );
786 exit (EXIT_FAILURE);
787 }
788
789 for (;;)
790 {
791 pid_t childid = fork();
792
793 switch (childid)
794 {
795 case -1:
796 break;
797
798 case 0:
799 close (fd[0]);
800 goto do_child_task;
801
802 default:
803 /*
804 * Parent process
805 */
806 close (read_fd);
807 close (fd[1]);
808 return fd[0];
809 }
810
811 /*
812 * Parent in error
813 */
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000814 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
Bruce Korb5abc1f71999-10-12 14:44:18 +0000815 p_fixd->fix_name);
816 {
817 static int failCt = 0;
818 if ((errno != EAGAIN) || (++failCt > 10))
819 exit (EXIT_FAILURE);
820 sleep (1);
821 }
822 } do_child_task:;
823
824 /*
825 * Close our current stdin and stdout
826 */
827 close (STDIN_FILENO);
828 close (STDOUT_FILENO);
829 UNLOAD_DATA();
830
831 /*
832 * Make the fd passed in the stdin, and the write end of
833 * the new pipe become the stdout.
834 */
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600835 dup2 (fd[1], STDOUT_FILENO);
836 dup2 (read_fd, STDIN_FILENO);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000837
Bruce Korb35dfe412000-05-11 13:41:12 +0000838 apply_fix (p_fixd, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000839 exit (0);
840}
Daniel Berlin283da1d2000-12-02 19:46:32 +0000841#endif /* !SEPARATE_FIX_PROC */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000842
Bruce Korbbb786201999-06-02 07:08:54 +0000843
Daniel Berlin283da1d2000-12-02 19:46:32 +0000844#ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000845static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000846fix_with_system (tFixDesc* p_fixd,
847 tCC* pz_fix_file,
848 tCC* pz_file_source,
849 tCC* pz_temp_file)
Bruce Korb62a99402000-08-04 14:16:57 +0000850{
851 char* pz_cmd;
852 char* pz_scan;
853 size_t argsize;
854
855 if (p_fixd->fd_flags & FD_SUBROUTINE)
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000856 {
857 static const char z_applyfix_prog[] =
858 "/../fixincludes/applyfix" EXE_EXT;
Bruce Korb62a99402000-08-04 14:16:57 +0000859
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000860 struct stat buf;
861 argsize = 32
862 + strlen (pz_orig_dir)
863 + sizeof (z_applyfix_prog)
864 + strlen (pz_fix_file)
865 + strlen (pz_file_source)
866 + strlen (pz_temp_file);
Bruce Korb62a99402000-08-04 14:16:57 +0000867
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000868 /* Allocate something sure to be big enough for our purposes */
869 pz_cmd = xmalloc (argsize);
870 strcpy (pz_cmd, pz_orig_dir);
871 pz_scan = pz_cmd + strlen (pz_orig_dir);
Bruce Korb62a99402000-08-04 14:16:57 +0000872
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000873 strcpy (pz_scan, z_applyfix_prog);
Bruce Korb62a99402000-08-04 14:16:57 +0000874
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000875 /* IF we can't find the "applyfix" executable file at the first guess,
876 try one level higher up */
877 if (stat (pz_cmd, &buf) == -1)
878 {
879 strcpy (pz_scan, "/..");
880 strcpy (pz_scan+3, z_applyfix_prog);
881 }
882
883 pz_scan += strlen (pz_scan);
884
885 /*
886 * Now add the fix number and file names that may be needed
887 */
Bruce Korbecb0d202004-11-17 05:06:41 +0000888 sprintf (pz_scan, " %ld '%s' '%s' '%s'", p_fixd - fixDescList,
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000889 pz_fix_file, pz_file_source, pz_temp_file);
890 }
Bruce Korb62a99402000-08-04 14:16:57 +0000891 else /* NOT an "internal" fix: */
892 {
893 size_t parg_size;
Daniel Berlin283da1d2000-12-02 19:46:32 +0000894#ifdef __MSDOS__
Bruce Korb62a99402000-08-04 14:16:57 +0000895 /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
Daniel Berlin283da1d2000-12-02 19:46:32 +0000896 dst is a temporary file anyway, so we know there's no other
897 file by that name; and DOS's system(3) doesn't mind to
Eli Zaretskiidc13bad2000-08-21 19:28:18 +0300898 clobber existing file in redirection. Besides, with DOS 8+3
899 limited file namespace, we can easily lose if dst already has
900 an extension that is 3 or more characters long.
Daniel Berlin283da1d2000-12-02 19:46:32 +0000901
902 I do not think the 8+3 issue is relevant because all the files
903 we operate on are named "*.h", making 8+2 adequate. Anyway,
904 the following bizarre use of 'cat' only works on DOS boxes.
905 It causes the file to be dropped into a temporary file for
Eli Zaretskiidc13bad2000-08-21 19:28:18 +0300906 'cat' to read (pipes do not work on DOS). */
Bruce Korbecb0d202004-11-17 05:06:41 +0000907 tSCC z_cmd_fmt[] = " '%s' | cat > '%s'";
Daniel Berlin283da1d2000-12-02 19:46:32 +0000908#else
909 /* Don't use positional formatting arguments because some lame-o
910 implementations cannot cope :-(. */
911 tSCC z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
912#endif
Bruce Korb62a99402000-08-04 14:16:57 +0000913 tCC** ppArgs = p_fixd->patch_args;
914
915 argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
916 + strlen( pz_file_source );
917 parg_size = argsize;
918
919
920 /*
921 * Compute the size of the command line. Add lotsa extra space
922 * because some of the args to sed use lotsa single quotes.
923 * (This requires three extra bytes per quote. Here we allow
924 * for up to 8 single quotes for each argument, including the
925 * command name "sed" itself. Nobody will *ever* need more. :)
926 */
927 for (;;)
928 {
929 tCC* p_arg = *(ppArgs++);
930 if (p_arg == NULL)
931 break;
932 argsize += 24 + strlen( p_arg );
933 }
934
935 /* Estimated buffer size we will need. */
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000936 pz_scan = pz_cmd = xmalloc (argsize);
Bruce Korb62a99402000-08-04 14:16:57 +0000937 /* How much of it do we allot to the program name and its
938 arguments. */
939 parg_size = argsize - parg_size;
940
941 ppArgs = p_fixd->patch_args;
942
943 /*
944 * Copy the program name, unquoted
945 */
946 {
947 tCC* pArg = *(ppArgs++);
948 for (;;)
949 {
950 char ch = *(pArg++);
951 if (ch == NUL)
952 break;
953 *(pz_scan++) = ch;
954 }
955 }
956
957 /*
958 * Copy the program arguments, quoted
959 */
960 for (;;)
961 {
962 tCC* pArg = *(ppArgs++);
963 char* pz_scan_save;
964 if (pArg == NULL)
965 break;
966 *(pz_scan++) = ' ';
967 pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
968 parg_size - (pz_scan - pz_cmd) );
969 /*
970 * Make sure we don't overflow the buffer due to sloppy
971 * size estimation.
972 */
973 while (pz_scan == (char*)NULL)
974 {
975 size_t already_filled = pz_scan_save - pz_cmd;
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000976 pz_cmd = xrealloc (pz_cmd, argsize += 100);
Bruce Korb62a99402000-08-04 14:16:57 +0000977 pz_scan_save = pz_scan = pz_cmd + already_filled;
978 parg_size += 100;
979 pz_scan = make_raw_shell_str( pz_scan, pArg,
980 parg_size - (pz_scan - pz_cmd) );
981 }
982 }
983
984 /*
985 * add the file machinations.
986 */
Bruce Korb6047d502000-12-07 01:32:11 +0000987#ifdef __MSDOS__
Daniel Berlin283da1d2000-12-02 19:46:32 +0000988 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
989#else
990 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
991 pz_temp_file, pz_temp_file, pz_temp_file);
992#endif
Bruce Korb62a99402000-08-04 14:16:57 +0000993 }
994 system( pz_cmd );
995 free( (void*)pz_cmd );
996}
997
Bruce Korbbb786201999-06-02 07:08:54 +0000998/* * * * * * * * * * * * *
999
1000 This loop should only cycle for 1/2 of one loop.
1001 "chain_open" starts a process that uses "read_fd" as
1002 its stdin and returns the new fd this process will use
1003 for stdout. */
1004
Daniel Berlin283da1d2000-12-02 19:46:32 +00001005#else /* is *NOT* SEPARATE_FIX_PROC */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001006static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001007start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
Bruce Korbbb786201999-06-02 07:08:54 +00001008{
Bruce Korbbb786201999-06-02 07:08:54 +00001009 tCC* pz_cmd_save;
1010 char* pz_cmd;
1011
Bruce Korb5abc1f71999-10-12 14:44:18 +00001012 if ((p_fixd->fd_flags & FD_SUBROUTINE) != 0)
1013 return internal_fix (read_fd, p_fixd);
1014
Bruce Korbbb786201999-06-02 07:08:54 +00001015 if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0)
James A. Morrison9cdfc8e2004-01-27 19:10:10 +00001016 {
1017 pz_cmd = NULL;
1018 pz_cmd_save = NULL;
1019 }
Bruce Korbbb786201999-06-02 07:08:54 +00001020 else
1021 {
1022 tSCC z_cmd_fmt[] = "file='%s'\n%s";
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +00001023 pz_cmd = xmalloc (strlen (p_fixd->patch_args[2])
1024 + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
Bruce Korb5abc1f71999-10-12 14:44:18 +00001025 sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
Bruce Korbbb786201999-06-02 07:08:54 +00001026 pz_cmd_save = p_fixd->patch_args[2];
1027 p_fixd->patch_args[2] = pz_cmd;
1028 }
1029
Bruce Korbb35926b1999-11-11 14:57:55 +00001030 /* Start a fix process, handing off the previous read fd for its
1031 stdin and getting a new fd that reads from the fix process' stdout.
1032 We normally will not loop, but we will up to 10 times if we keep
1033 getting "EAGAIN" errors.
1034
1035 */
Bruce Korbbb786201999-06-02 07:08:54 +00001036 for (;;)
1037 {
1038 static int failCt = 0;
1039 int fd;
1040
1041 fd = chain_open (read_fd,
Bruce Korb2629a112000-12-13 20:07:46 +00001042 (tCC **) p_fixd->patch_args,
Bruce Korbbb786201999-06-02 07:08:54 +00001043 (process_chain_head == -1)
1044 ? &process_chain_head : (pid_t *) NULL);
1045
1046 if (fd != -1)
1047 {
1048 read_fd = fd;
1049 break;
1050 }
1051
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001052 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
Bruce Korbbb786201999-06-02 07:08:54 +00001053 p_fixd->fix_name);
1054
1055 if ((errno != EAGAIN) || (++failCt > 10))
1056 exit (EXIT_FAILURE);
1057 sleep (1);
1058 }
1059
Bruce Korbb35926b1999-11-11 14:57:55 +00001060 /* IF we allocated a shell script command,
1061 THEN free it and restore the command format to the fix description */
Bruce Korbbb786201999-06-02 07:08:54 +00001062 if (pz_cmd != (char*)NULL)
1063 {
1064 free ((void*)pz_cmd);
1065 p_fixd->patch_args[2] = pz_cmd_save;
1066 }
1067
1068 return read_fd;
1069}
Bruce Korb62a99402000-08-04 14:16:57 +00001070#endif
Bruce Korbbb786201999-06-02 07:08:54 +00001071
Bruce Korb5abc1f71999-10-12 14:44:18 +00001072
1073/* * * * * * * * * * * * *
1074
1075 Process the potential fixes for a particular include file.
1076 Input: the original text of the file and the file's name
1077 Result: none. A new file may or may not be created. */
1078
Bruce Korb6864a6c2000-12-02 19:01:16 +00001079static t_bool
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001080fix_applies (tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001081{
Zack Weinbergae5c8392000-01-22 20:55:18 +00001082 const char *pz_fname = pz_curr_file;
1083 const char *pz_scan = p_fixd->file_list;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001084 int test_ct;
1085 tTestDesc *p_test;
1086
Daniel Berlin283da1d2000-12-02 19:46:32 +00001087# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +00001088 /*
1089 * There is only one fix that uses a shell script as of this writing.
1090 * I hope to nuke it anyway, it does not apply to DOS and it would
1091 * be painful to implement. Therefore, no "shell" fixes for DOS.
1092 */
1093 if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
1094 return BOOL_FALSE;
1095# else
Bruce Korb5abc1f71999-10-12 14:44:18 +00001096 if (p_fixd->fd_flags & FD_SKIP_TEST)
1097 return BOOL_FALSE;
Bruce Korb62a99402000-08-04 14:16:57 +00001098# endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001099
1100 /* IF there is a file name restriction,
1101 THEN ensure the current file name matches one in the pattern */
1102
Zack Weinbergae5c8392000-01-22 20:55:18 +00001103 if (pz_scan != (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001104 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001105 size_t name_len;
1106
1107 while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
1108 pz_fname += 2;
1109 name_len = strlen (pz_fname);
1110
1111 for (;;)
1112 {
1113 pz_scan = strstr (pz_scan + 1, pz_fname);
1114 /* IF we can't match the string at all,
1115 THEN bail */
Bruce Korb62a99402000-08-04 14:16:57 +00001116 if (pz_scan == (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001117 return BOOL_FALSE;
1118
1119 /* IF the match is surrounded by the '|' markers,
1120 THEN we found a full match -- time to run the tests */
1121
1122 if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|'))
1123 break;
1124 }
1125 }
1126
1127 /* FOR each test, see if it fails.
1128 IF it does fail, then we go on to the next test */
1129
1130 for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
1131 test_ct-- > 0;
1132 p_test++)
1133 {
1134 switch (p_test->type)
1135 {
1136 case TT_TEST:
Bruce Korbb35926b1999-11-11 14:57:55 +00001137 if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
1138#ifdef DEBUG
1139 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001140 fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
1141 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001142#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001143 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001144 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001145 break;
1146
1147 case TT_EGREP:
Bruce Korbb35926b1999-11-11 14:57:55 +00001148 if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
1149#ifdef DEBUG
1150 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001151 fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
1152 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001153#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001154 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001155 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001156 break;
1157
1158 case TT_NEGREP:
Bruce Korbb35926b1999-11-11 14:57:55 +00001159 if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
1160#ifdef DEBUG
1161 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001162 fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
1163 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001164#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001165 /* Negated sense */
1166 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001167 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001168 break;
1169
1170 case TT_FUNCTION:
1171 if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
Bruce Korbb35926b1999-11-11 14:57:55 +00001172 != APPLY_FIX) {
1173#ifdef DEBUG
1174 if (VLEVEL( VERB_EVERYTHING ))
Bruce Korbe9099382000-05-17 14:56:13 +00001175 fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
1176 pz_fname, p_fixd->test_ct - test_ct);
Bruce Korbb35926b1999-11-11 14:57:55 +00001177#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001178 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001179 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001180 break;
1181 }
1182 }
1183
1184 return BOOL_TRUE;
1185}
1186
1187
1188/* * * * * * * * * * * * *
1189
1190 Write out a replacement file */
1191
Bruce Korb6864a6c2000-12-02 19:01:16 +00001192static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001193write_replacement (tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001194{
1195 const char* pz_text = p_fixd->patch_args[0];
1196
1197 if ((pz_text == (char*)NULL) || (*pz_text == NUL))
1198 return;
1199
1200 {
Bruce Korb6864a6c2000-12-02 19:01:16 +00001201 FILE* out_fp = create_file ();
Bruce Korb5abc1f71999-10-12 14:44:18 +00001202 fputs (pz_text, out_fp);
1203 fclose (out_fp);
1204 }
1205}
1206
1207
1208/* * * * * * * * * * * * *
1209
1210 We have work to do. Read back in the output
1211 of the filtering chain. Compare each byte as we read it with
1212 the contents of the original file. As soon as we find any
1213 difference, we will create the output file, write out all
1214 the matched text and then copy any remaining data from the
1215 output of the filter chain.
1216 */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001217static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001218test_for_changes (int read_fd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001219{
1220 FILE *in_fp = fdopen (read_fd, "r");
1221 FILE *out_fp = (FILE *) NULL;
Bruce Korb90376ae2001-07-21 04:08:29 +00001222 unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001223
1224#ifdef DO_STATS
1225 fixed_ct++;
1226#endif
1227 for (;;)
1228 {
1229 int ch;
1230
1231 ch = getc (in_fp);
1232 if (ch == EOF)
1233 break;
Bruce Korb90376ae2001-07-21 04:08:29 +00001234 ch &= 0xFF; /* all bytes are 8 bits */
Bruce Korb5abc1f71999-10-12 14:44:18 +00001235
1236 /* IF we are emitting the output
1237 THEN emit this character, too.
1238 */
1239 if (out_fp != (FILE *) NULL)
1240 putc (ch, out_fp);
1241
1242 /* ELSE if this character does not match the original,
1243 THEN now is the time to start the output.
1244 */
1245 else if (ch != *pz_cmp)
1246 {
Bruce Korb6864a6c2000-12-02 19:01:16 +00001247 out_fp = create_file ();
Bruce Korb5abc1f71999-10-12 14:44:18 +00001248
1249#ifdef DO_STATS
1250 altered_ct++;
1251#endif
1252 /* IF there are matched data, write the matched part now. */
Bruce Korbc8b0c192001-07-21 04:20:08 +00001253 if ((char*)pz_cmp != pz_curr_data)
1254 fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
1255 1, out_fp);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001256
1257 /* Emit the current unmatching character */
1258 putc (ch, out_fp);
1259 }
1260 else
1261 /* ELSE the character matches. Advance the compare ptr */
1262 pz_cmp++;
1263 }
1264
1265 /* IF we created the output file, ... */
1266 if (out_fp != (FILE *) NULL)
1267 {
1268 regmatch_t match;
1269
1270 /* Close the file and see if we have to worry about
1271 `#include "file.h"' constructs. */
1272 fclose (out_fp);
Zack Weinbergab747402003-07-08 20:42:19 +00001273 if (xregexec (&incl_quote_re, pz_curr_data, 1, &match, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001274 extract_quoted_files (pz_curr_data, pz_curr_file, &match);
1275 }
1276
1277 fclose (in_fp);
1278 close (read_fd); /* probably redundant, but I'm paranoid */
1279}
1280
1281
Bruce Korb1f414ac1999-03-03 07:41:52 +00001282/* * * * * * * * * * * * *
1283
1284 Process the potential fixes for a particular include file.
1285 Input: the original text of the file and the file's name
1286 Result: none. A new file may or may not be created. */
1287
Bruce Korb0083c901998-10-16 07:00:18 +00001288void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001289process (void)
Bruce Korb0083c901998-10-16 07:00:18 +00001290{
Bruce Korb1f414ac1999-03-03 07:41:52 +00001291 tFixDesc *p_fixd = fixDescList;
1292 int todo_ct = FIX_COUNT;
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001293 int read_fd = -1;
Daniel Berlin283da1d2000-12-02 19:46:32 +00001294# ifndef SEPARATE_FIX_PROC
Rainer Orth9f8eec31999-05-17 12:39:19 +00001295 int num_children = 0;
Daniel Berlin283da1d2000-12-02 19:46:32 +00001296# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +00001297 char* pz_file_source = pz_curr_file;
1298# endif
Bruce Korb1f414ac1999-03-03 07:41:52 +00001299
Bruce Korb5abc1f71999-10-12 14:44:18 +00001300 if (access (pz_curr_file, R_OK) != 0)
1301 {
1302 int erno = errno;
1303 fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
1304 pz_curr_file, getcwd ((char *) NULL, MAXPATHLEN),
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001305 erno, xstrerror (erno));
Bruce Korb5abc1f71999-10-12 14:44:18 +00001306 return;
1307 }
1308
1309 pz_curr_data = load_file (pz_curr_file);
1310 if (pz_curr_data == (char *) NULL)
1311 return;
1312
1313#ifdef DO_STATS
1314 process_ct++;
1315#endif
Zack Weinbergd7eb5a41999-12-17 21:49:30 +00001316 if (VLEVEL( VERB_PROGRESS ) && have_tty)
Richard Henderson1c99d802003-01-21 17:02:51 -08001317 fprintf (stderr, "%6lu %-50s \r",
1318 (unsigned long) data_map_size, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001319
Daniel Berlin283da1d2000-12-02 19:46:32 +00001320# ifndef SEPARATE_FIX_PROC
Bruce Korb1f414ac1999-03-03 07:41:52 +00001321 process_chain_head = NOPROCESS;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001322
Bruce Korb1f414ac1999-03-03 07:41:52 +00001323 /* For every fix in our fix list, ... */
1324 for (; todo_ct > 0; p_fixd++, todo_ct--)
Bruce Korb0083c901998-10-16 07:00:18 +00001325 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001326 if (! fix_applies (p_fixd))
Bruce Korb0083c901998-10-16 07:00:18 +00001327 continue;
1328
Bruce Korbb35926b1999-11-11 14:57:55 +00001329 if (VLEVEL( VERB_APPLIES ))
1330 fprintf (stderr, "Applying %-24s to %s\n",
1331 p_fixd->fix_name, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001332
1333 if (p_fixd->fd_flags & FD_REPLACEMENT)
1334 {
1335 write_replacement (p_fixd);
1336 UNLOAD_DATA();
1337 return;
1338 }
Bruce Korb1f414ac1999-03-03 07:41:52 +00001339
1340 /* IF we do not have a read pointer,
1341 THEN this is the first fix for the current file.
1342 Open the source file. That will be used as stdin for
1343 the first fix. Any subsequent fixes will use the
Bruce Korb5abc1f71999-10-12 14:44:18 +00001344 stdout descriptor of the previous fix for its stdin. */
Bruce Korb1f414ac1999-03-03 07:41:52 +00001345
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001346 if (read_fd == -1)
Bruce Korb0083c901998-10-16 07:00:18 +00001347 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001348 read_fd = open (pz_curr_file, O_RDONLY);
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001349 if (read_fd < 0)
Bruce Korb0083c901998-10-16 07:00:18 +00001350 {
Bruce Korb1f414ac1999-03-03 07:41:52 +00001351 fprintf (stderr, "Error %d (%s) opening %s\n", errno,
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001352 xstrerror (errno), pz_curr_file);
Bruce Korb1f414ac1999-03-03 07:41:52 +00001353 exit (EXIT_FAILURE);
Bruce Korb0083c901998-10-16 07:00:18 +00001354 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001355
1356 /* Ensure we do not get duplicate output */
1357
1358 fflush (stdout);
Bruce Korb0083c901998-10-16 07:00:18 +00001359 }
1360
Bruce Korb5abc1f71999-10-12 14:44:18 +00001361 read_fd = start_fixer (read_fd, p_fixd, pz_curr_file);
Bruce Korbbb786201999-06-02 07:08:54 +00001362 num_children++;
Bruce Korb0083c901998-10-16 07:00:18 +00001363 }
1364
Bruce Korb5abc1f71999-10-12 14:44:18 +00001365 /* IF we have a read-back file descriptor,
1366 THEN check for changes and write output if changed. */
Bruce Korb1f414ac1999-03-03 07:41:52 +00001367
Bruce Korb5abc1f71999-10-12 14:44:18 +00001368 if (read_fd >= 0)
1369 {
1370 test_for_changes (read_fd);
1371#ifdef DO_STATS
1372 apply_ct += num_children;
1373#endif
1374 /* Wait for child processes created by chain_open()
1375 to avoid leaving zombies. */
1376 do {
1377 wait ((int *) NULL);
1378 } while (--num_children > 0);
1379 }
Bruce Korb0083c901998-10-16 07:00:18 +00001380
Daniel Berlin283da1d2000-12-02 19:46:32 +00001381# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +00001382
1383 for (; todo_ct > 0; p_fixd++, todo_ct--)
1384 {
1385 if (! fix_applies (p_fixd))
1386 continue;
1387
1388 if (VLEVEL( VERB_APPLIES ))
1389 fprintf (stderr, "Applying %-24s to %s\n",
1390 p_fixd->fix_name, pz_curr_file);
1391
1392 if (p_fixd->fd_flags & FD_REPLACEMENT)
1393 {
1394 write_replacement (p_fixd);
1395 UNLOAD_DATA();
1396 return;
1397 }
1398 fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
1399 pz_file_source = pz_temp_file;
1400 }
1401
Daniel Berlin283da1d2000-12-02 19:46:32 +00001402 read_fd = open (pz_temp_file, O_RDONLY);
1403 if (read_fd < 0)
1404 {
Bruce Korbca21b4a2001-02-06 22:19:50 +00001405 if (errno != ENOENT)
1406 fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
1407 errno, xstrerror (errno), pz_temp_file);
Daniel Berlin283da1d2000-12-02 19:46:32 +00001408 }
1409 else
1410 {
1411 test_for_changes (read_fd);
1412 /* Unlinking a file while it is still open is a Bad Idea on
1413 DOS/Windows. */
1414 close (read_fd);
1415 unlink (pz_temp_file);
1416 }
Bruce Korb62a99402000-08-04 14:16:57 +00001417
1418# endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001419 UNLOAD_DATA();
Bruce Korb0083c901998-10-16 07:00:18 +00001420}