blob: 6dba2f6e830a9b9827a799984e68bb81e108fba6 [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 Jelinek90d04a42013-01-04 13:49:55 +01005 Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2012
Jakub Jelinek748086b2009-04-09 17:00:19 +02006 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;
Zack Weinbergd7eb5a41999-12-17 21:49:30 +000056int have_tty = 0;
Bruce Korbb35926b1999-11-11 14:57:55 +000057
Bruce Korb1f414ac1999-03-03 07:41:52 +000058pid_t process_chain_head = (pid_t) -1;
Bruce Korb0083c901998-10-16 07:00:18 +000059
Bruce Korb5abc1f71999-10-12 14:44:18 +000060char* pz_curr_file; /* name of the current file under test/fix */
61char* pz_curr_data; /* original contents of that file */
Bruce Korb62a99402000-08-04 14:16:57 +000062char* pz_temp_file; /* for DOS, a place to stash the temporary
63 fixed data between system(3) calls */
Bruce Korb5abc1f71999-10-12 14:44:18 +000064t_bool curr_data_mapped;
65int data_map_fd;
66size_t data_map_size;
67size_t ttl_data_size = 0;
Bruce Korbe02ecf32000-07-19 14:10:41 +000068
Bruce Korb5abc1f71999-10-12 14:44:18 +000069#ifdef DO_STATS
70int process_ct = 0;
71int apply_ct = 0;
72int fixed_ct = 0;
73int altered_ct = 0;
74#endif /* DO_STATS */
75
Bruce Korb1f414ac1999-03-03 07:41:52 +000076const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
77regex_t incl_quote_re;
Bruce Korb0083c901998-10-16 07:00:18 +000078
Tadek Kijkowski716028e42016-09-30 16:36:18 +000079#ifndef SEPARATE_FIX_PROC
80tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
81#endif
82
Nathanael Nerodef4dbf932003-08-01 23:07:04 +000083static void do_version (void) ATTRIBUTE_NORETURN;
84char *load_file (const char *);
85void run_compiles (void);
86void initialize (int argc, char** argv);
87void process (void);
Bruce Korb5abc1f71999-10-12 14:44:18 +000088
89/* External Source Code */
Bruce Korb0083c901998-10-16 07:00:18 +000090
91#include "fixincl.x"
92
Bruce Korb1f414ac1999-03-03 07:41:52 +000093/* * * * * * * * * * * * * * * * * * *
94 *
95 * MAIN ROUTINE
96 */
Nathanael Nerodef4dbf932003-08-01 23:07:04 +000097extern int main (int, char **);
Bruce Korb0083c901998-10-16 07:00:18 +000098int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +000099main (int argc, char** argv)
Bruce Korb0083c901998-10-16 07:00:18 +0000100{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000101 char *file_name_buf;
Bruce Korb0083c901998-10-16 07:00:18 +0000102
Bruce Korb35dfe412000-05-11 13:41:12 +0000103 initialize ( argc, argv );
Bruce Korbd1c6a031999-04-26 10:38:38 +0000104
Zack Weinbergd7eb5a41999-12-17 21:49:30 +0000105 have_tty = isatty (fileno (stderr));
106
Bruce Korb5abc1f71999-10-12 14:44:18 +0000107 /* Before anything else, ensure we can allocate our file name buffer. */
108 file_name_buf = load_file_data (stdin);
109
110 /* Because of the way server shells work, you have to keep stdin, out
111 and err open so that the proper input file does not get closed
112 by accident */
113
114 freopen ("/dev/null", "r", stdin);
115
116 if (file_name_buf == (char *) NULL)
117 {
118 fputs ("No file names listed for fixing\n", stderr);
119 exit (EXIT_FAILURE);
120 }
121
Bruce Korbd1c6a031999-04-26 10:38:38 +0000122 for (;;)
123 {
Bruce Korb5abc1f71999-10-12 14:44:18 +0000124 char* pz_end;
Bruce Korbd1c6a031999-04-26 10:38:38 +0000125
Bruce Korb5abc1f71999-10-12 14:44:18 +0000126 /* skip to start of name, past any "./" prefixes */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000127
Bruce Korb5abc1f71999-10-12 14:44:18 +0000128 while (ISSPACE (*file_name_buf)) file_name_buf++;
129 while ((file_name_buf[0] == '.') && (file_name_buf[1] == '/'))
130 file_name_buf += 2;
Bruce Korbd1c6a031999-04-26 10:38:38 +0000131
Bruce Korb5abc1f71999-10-12 14:44:18 +0000132 /* Check for end of list */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000133
Bruce Korb5abc1f71999-10-12 14:44:18 +0000134 if (*file_name_buf == NUL)
135 break;
136
137 /* Set global file name pointer and find end of name */
138
139 pz_curr_file = file_name_buf;
140 pz_end = strchr( pz_curr_file, '\n' );
141 if (pz_end == (char*)NULL)
142 pz_end = file_name_buf = pz_curr_file + strlen (pz_curr_file);
143 else
144 file_name_buf = pz_end + 1;
145
146 while ((pz_end > pz_curr_file) && ISSPACE( pz_end[-1])) pz_end--;
147
148 /* IF no name is found (blank line) or comment marker, skip line */
149
150 if ((pz_curr_file == pz_end) || (*pz_curr_file == '#'))
151 continue;
152 *pz_end = NUL;
153
Bruce Korb5abc1f71999-10-12 14:44:18 +0000154 process ();
Bruce Korb5abc1f71999-10-12 14:44:18 +0000155 } /* for (;;) */
Bruce Korbd1c6a031999-04-26 10:38:38 +0000156
Bruce Korb5abc1f71999-10-12 14:44:18 +0000157#ifdef DO_STATS
Bruce Korbb35926b1999-11-11 14:57:55 +0000158 if (VLEVEL( VERB_PROGRESS )) {
Bruce Korb5abc1f71999-10-12 14:44:18 +0000159 tSCC zFmt[] =
160 "\
161Processed %5d files containing %d bytes \n\
162Applying %5d fixes to %d files\n\
163Altering %5d of them\n";
Bruce Korbd1c6a031999-04-26 10:38:38 +0000164
Bruce Korb5abc1f71999-10-12 14:44:18 +0000165 fprintf (stderr, zFmt, process_ct, ttl_data_size, apply_ct,
166 fixed_ct, altered_ct);
167 }
168#endif /* DO_STATS */
Bruce Korb62a99402000-08-04 14:16:57 +0000169
Daniel Berlin283da1d2000-12-02 19:46:32 +0000170# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000171 unlink( pz_temp_file );
172# endif
Bruce Korb15fe1a72001-01-05 16:28:58 +0000173 exit (EXIT_SUCCESS);
Bruce Korbd1c6a031999-04-26 10:38:38 +0000174}
175
176
Bruce Korb6864a6c2000-12-02 19:01:16 +0000177static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000178do_version (void)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000179{
180 static const char zFmt[] = "echo '%s'";
181 char zBuf[ 1024 ];
182
183 /* The 'version' option is really used to test that:
184 1. The program loads correctly (no missing libraries)
Bruce Korb35dfe412000-05-11 13:41:12 +0000185 2. that we can compile all the regular expressions.
186 3. we can correctly run our server shell process
Bruce Korb5abc1f71999-10-12 14:44:18 +0000187 */
188 run_compiles ();
189 sprintf (zBuf, zFmt, program_id);
Daniel Berlin283da1d2000-12-02 19:46:32 +0000190#ifndef SEPARATE_FIX_PROC
Bruce Korb6b151aa2000-05-04 14:55:00 +0000191 puts (zBuf + 5);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000192 exit (strcmp (run_shell (zBuf), program_id));
Bruce Korb62a99402000-08-04 14:16:57 +0000193#else
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000194 exit (system_with_shell (zBuf));
Bruce Korb62a99402000-08-04 14:16:57 +0000195#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +0000196}
197
Bruce Korbd1c6a031999-04-26 10:38:38 +0000198/* * * * * * * * * * * * */
199
200void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000201initialize ( int argc, char** argv )
Bruce Korbd1c6a031999-04-26 10:38:38 +0000202{
Bruce Korb878a5792000-07-12 14:45:05 +0000203 xmalloc_set_program_name (argv[0]);
204
Bruce Korb35dfe412000-05-11 13:41:12 +0000205 switch (argc)
206 {
207 case 1:
208 break;
209
210 case 2:
211 if (strcmp (argv[1], "-v") == 0)
212 do_version ();
213 if (freopen (argv[1], "r", stdin) == (FILE*)NULL)
214 {
215 fprintf (stderr, "Error %d (%s) reopening %s as stdin\n",
216 errno, xstrerror (errno), argv[1] );
217 exit (EXIT_FAILURE);
218 }
219 break;
220
221 default:
222 fputs ("fixincl ERROR: too many command line arguments\n", stderr);
223 exit (EXIT_FAILURE);
224 }
225
Bruce Korb798bdf72001-03-16 00:58:40 +0000226#ifdef SIGCHLD
227 /* We *MUST* set SIGCHLD to SIG_DFL so that the wait4() call will
228 receive the signal. A different setting is inheritable */
229 signal (SIGCHLD, SIG_DFL);
230#endif
231
Paolo Bonziniad643a72004-10-15 07:58:38 +0000232 initialize_opts ();
Bruce Korb0083c901998-10-16 07:00:18 +0000233
Bruce Korb6864a6c2000-12-02 19:01:16 +0000234 if (ISDIGIT ( *pz_verbose ))
Bruce Korbe02ecf32000-07-19 14:10:41 +0000235 verbose_level = (te_verbose)atoi( pz_verbose );
236 else
237 switch (*pz_verbose) {
238 case 's':
239 case 'S':
240 verbose_level = VERB_SILENT; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000241
Bruce Korbe02ecf32000-07-19 14:10:41 +0000242 case 'f':
243 case 'F':
244 verbose_level = VERB_FIXES; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000245
Bruce Korbe02ecf32000-07-19 14:10:41 +0000246 case 'a':
247 case 'A':
248 verbose_level = VERB_APPLIES; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000249
DJ Delorie7a9cdb12003-03-22 16:51:04 -0500250 default:
Bruce Korbe02ecf32000-07-19 14:10:41 +0000251 case 'p':
252 case 'P':
253 verbose_level = VERB_PROGRESS; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000254
Bruce Korbe02ecf32000-07-19 14:10:41 +0000255 case 't':
256 case 'T':
257 verbose_level = VERB_TESTS; break;
Bruce Korbb35926b1999-11-11 14:57:55 +0000258
Bruce Korbe02ecf32000-07-19 14:10:41 +0000259 case 'e':
260 case 'E':
261 verbose_level = VERB_EVERYTHING; break;
262 }
DJ Delorie7a9cdb12003-03-22 16:51:04 -0500263 if (verbose_level >= VERB_EVERYTHING) {
264 verbose_level = VERB_EVERYTHING;
265 fputs ("fixinc verbosity: EVERYTHING\n", stderr);
266 }
267 while ((pz_find_base[0] == '.') && (pz_find_base[1] == '/'))
268 pz_find_base += 2;
269 if ((pz_find_base[0] != '.') || (pz_find_base[1] != NUL))
270 find_base_len = strlen( pz_find_base );
Bruce Korb7d9ccd91999-03-31 11:51:29 +0000271
Bruce Korb1f414ac1999-03-03 07:41:52 +0000272 /* Compile all the regular expressions now.
273 That way, it is done only once for the whole run.
274 */
275 run_compiles ();
Bruce Korb0083c901998-10-16 07:00:18 +0000276
Daniel Berlin283da1d2000-12-02 19:46:32 +0000277# ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000278 /* NULL as the first argument to `tempnam' causes it to DTRT
279 wrt the temporary directory where the file will be created. */
280 pz_temp_file = tempnam( NULL, "fxinc" );
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000281
282#if defined(__MINGW32__)
283 fix_path_separators (pz_temp_file);
284#endif
285
Bruce Korb62a99402000-08-04 14:16:57 +0000286# endif
287
Bruce Korb1f414ac1999-03-03 07:41:52 +0000288 signal (SIGQUIT, SIG_IGN);
289 signal (SIGIOT, SIG_IGN);
290 signal (SIGPIPE, SIG_IGN);
291 signal (SIGALRM, SIG_IGN);
292 signal (SIGTERM, SIG_IGN);
Bruce Korbd1c6a031999-04-26 10:38:38 +0000293}
Bruce Korb0083c901998-10-16 07:00:18 +0000294
Bruce Korb1f414ac1999-03-03 07:41:52 +0000295/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000296
Bruce Korb1f414ac1999-03-03 07:41:52 +0000297 load_file loads all the contents of a file into malloc-ed memory.
298 Its argument is the name of the file to read in; the returned
299 result is the NUL terminated contents of the file. The file
300 is presumed to be an ASCII text file containing no NULs. */
Bruce Korb0083c901998-10-16 07:00:18 +0000301char *
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000302load_file ( const char* fname )
Bruce Korb0083c901998-10-16 07:00:18 +0000303{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000304 struct stat stbf;
305 char* res;
Bruce Korb0083c901998-10-16 07:00:18 +0000306
Bruce Korb5abc1f71999-10-12 14:44:18 +0000307 if (stat (fname, &stbf) != 0)
Bruce Korb0083c901998-10-16 07:00:18 +0000308 {
Bruce Korbb35926b1999-11-11 14:57:55 +0000309 if (NOT_SILENT)
310 fprintf (stderr, "error %d (%s) stat-ing %s\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000311 errno, xstrerror (errno), fname );
Bruce Korb5abc1f71999-10-12 14:44:18 +0000312 return (char *) NULL;
313 }
314 if (stbf.st_size == 0)
315 return (char*)NULL;
316
Bruce Korba6efbec2000-09-05 18:29:56 +0000317 /* Make the data map size one larger than the file size for documentation
318 purposes. Truth is that there will be a following NUL character if
319 the file size is not a multiple of the page size. If it is a multiple,
320 then this adjustment sometimes fails anyway. */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000321 data_map_size = stbf.st_size+1;
322 data_map_fd = open (fname, O_RDONLY);
323 ttl_data_size += data_map_size-1;
324
325 if (data_map_fd < 0)
326 {
Bruce Korbb35926b1999-11-11 14:57:55 +0000327 if (NOT_SILENT)
328 fprintf (stderr, "error %d (%s) opening %s for read\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000329 errno, xstrerror (errno), fname);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000330 return (char*)NULL;
Bruce Korb0083c901998-10-16 07:00:18 +0000331 }
332
Zack Weinberg56f02b82000-04-17 17:25:57 +0000333#ifdef HAVE_MMAP_FILE
Bruce Korb5abc1f71999-10-12 14:44:18 +0000334 curr_data_mapped = BOOL_TRUE;
Bruce Korba6efbec2000-09-05 18:29:56 +0000335
336 /* IF the file size is a multiple of the page size,
337 THEN sometimes you will seg fault trying to access a trailing byte */
Bruce Korbdc465052000-09-05 22:26:16 +0000338 if ((stbf.st_size & (getpagesize()-1)) == 0)
Bruce Korba6efbec2000-09-05 18:29:56 +0000339 res = (char*)BAD_ADDR;
340 else
341 res = (char*)mmap ((void*)NULL, data_map_size, PROT_READ,
342 MAP_PRIVATE, data_map_fd, 0);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000343 if (res == (char*)BAD_ADDR)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000344#endif
Bruce Korbca21b4a2001-02-06 22:19:50 +0000345 {
346 FILE* fp = fdopen (data_map_fd, "r");
347 curr_data_mapped = BOOL_FALSE;
348 res = load_file_data (fp);
349 fclose (fp);
350 }
Bruce Korb0083c901998-10-16 07:00:18 +0000351
Bruce Korb5abc1f71999-10-12 14:44:18 +0000352 return res;
Bruce Korb0083c901998-10-16 07:00:18 +0000353}
354
Bruce Korb6864a6c2000-12-02 19:01:16 +0000355static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000356machine_matches( tFixDesc* p_fixd )
Bruce Korb401be4b2007-01-06 18:03:50 +0000357{
358 char const ** papz_machs = p_fixd->papz_machs;
359 int have_match = BOOL_FALSE;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000360
Bruce Korb62a99402000-08-04 14:16:57 +0000361 for (;;)
362 {
Bruce Korb401be4b2007-01-06 18:03:50 +0000363 char const * pz_mpat = *(papz_machs++);
364 if (pz_mpat == NULL)
Bruce Korb62a99402000-08-04 14:16:57 +0000365 break;
Bruce Korb401be4b2007-01-06 18:03:50 +0000366 if (fnmatch(pz_mpat, pz_machine, 0) == 0)
367 {
368 have_match = BOOL_TRUE;
369 break;
370 }
Bruce Korb62a99402000-08-04 14:16:57 +0000371 }
372
Bruce Korb2f82a972007-01-06 20:02:22 +0000373 /* Check for sense inversion then set the "skip test" flag, if needed */
Bruce Korb401be4b2007-01-06 18:03:50 +0000374 if (p_fixd->fd_flags & FD_MACH_IFNOT)
Bruce Korb2f82a972007-01-06 20:02:22 +0000375 have_match = ! have_match;
376
377 if (! have_match)
378 p_fixd->fd_flags |= FD_SKIP_TEST;
379
Bruce Korb401be4b2007-01-06 18:03:50 +0000380 return have_match;
Bruce Korb62a99402000-08-04 14:16:57 +0000381}
382
383/* * * * * * * * * * * * *
Bruce Korb401be4b2007-01-06 18:03:50 +0000384 *
385 * run_compiles run all the regexp compiles for all the fixes once.
386 */
Bruce Korb62a99402000-08-04 14:16:57 +0000387void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000388run_compiles (void)
Bruce Korb62a99402000-08-04 14:16:57 +0000389{
390 tFixDesc *p_fixd = fixDescList;
391 int fix_ct = FIX_COUNT;
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000392 regex_t *p_re = XCNEWVEC (regex_t, REGEX_COUNT);
Bruce Korb62a99402000-08-04 14:16:57 +0000393
394 /* Make sure compile_re does not stumble across invalid data */
395
Kaveh R. Ghazic68b0a82003-07-19 16:09:51 +0000396 memset (&incl_quote_re, '\0', sizeof (regex_t));
Bruce Korb62a99402000-08-04 14:16:57 +0000397
398 compile_re (incl_quote_pat, &incl_quote_re, 1,
399 "quoted include", "run_compiles");
400
401 /* Allow machine name tests to be ignored (testing, mainly) */
402
403 if (pz_machine && ((*pz_machine == '\0') || (*pz_machine == '*')))
404 pz_machine = (char*)NULL;
405
406 /* FOR every fixup, ... */
407 do
408 {
Bruce Korb7e416542012-10-29 16:44:34 +0000409 tTestDesc *p_test;
410 int test_ct;
411
412 if (fixinc_mode && (p_fixd->fd_flags & FD_REPLACEMENT))
413 {
414 p_fixd->fd_flags |= FD_SKIP_TEST;
415 continue;
416 }
417
418 p_test = p_fixd->p_test_desc;
419 test_ct = p_fixd->test_ct;
Bruce Korb62a99402000-08-04 14:16:57 +0000420
421 /* IF the machine type pointer is not NULL (we are not in test mode)
422 AND this test is for or not done on particular machines
423 THEN ... */
424
425 if ( (pz_machine != NULL)
426 && (p_fixd->papz_machs != (const char**) NULL)
427 && ! machine_matches (p_fixd) )
428 continue;
Bruce Korb1f414ac1999-03-03 07:41:52 +0000429
430 /* FOR every test for the fixup, ... */
431
432 while (--test_ct >= 0)
433 {
434 switch (p_test->type)
Bruce Korb0083c901998-10-16 07:00:18 +0000435 {
436 case TT_EGREP:
437 case TT_NEGREP:
Bruce Korb1f414ac1999-03-03 07:41:52 +0000438 p_test->p_test_regex = p_re++;
Bruce Korb35dfe412000-05-11 13:41:12 +0000439 compile_re (p_test->pz_test_text, p_test->p_test_regex, 0,
440 "select test", p_fixd->fix_name);
Bruce Korb3af556f2000-09-12 14:28:55 +0000441 default: break;
Bruce Korb35dfe412000-05-11 13:41:12 +0000442 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000443 p_test++;
Bruce Korb0083c901998-10-16 07:00:18 +0000444 }
445 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000446 while (p_fixd++, --fix_ct > 0);
Bruce Korb0083c901998-10-16 07:00:18 +0000447}
448
449
Bruce Korb1f414ac1999-03-03 07:41:52 +0000450/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000451
Bruce Korb1f414ac1999-03-03 07:41:52 +0000452 create_file Create the output modified file.
453 Input: the name of the file to create
454 Returns: a file pointer to the new, open file */
455
Bruce Korb063174e1999-11-04 14:50:44 +0000456#if defined(S_IRUSR) && defined(S_IWUSR) && \
457 defined(S_IRGRP) && defined(S_IROTH)
458
459# define S_IRALL (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
460#else
461# define S_IRALL 0644
462#endif
463
464#if defined(S_IRWXU) && defined(S_IRGRP) && defined(S_IXGRP) && \
465 defined(S_IROTH) && defined(S_IXOTH)
466
467# define S_DIRALL (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
468#else
469# define S_DIRALL 0755
470#endif
471
Bruce Korb1f414ac1999-03-03 07:41:52 +0000472
Bruce Korb6864a6c2000-12-02 19:01:16 +0000473static FILE *
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000474create_file (void)
Bruce Korb0083c901998-10-16 07:00:18 +0000475{
476 int fd;
477 FILE *pf;
478 char fname[MAXPATHLEN];
479
Bruce Korb5abc1f71999-10-12 14:44:18 +0000480 sprintf (fname, "%s/%s", pz_dest_dir, pz_curr_file + find_base_len);
Bruce Korb0083c901998-10-16 07:00:18 +0000481
Bruce Korb1f414ac1999-03-03 07:41:52 +0000482 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
Bruce Korb0083c901998-10-16 07:00:18 +0000483
Bruce Korb1f414ac1999-03-03 07:41:52 +0000484 /* We may need to create the directories needed... */
Bruce Korb0083c901998-10-16 07:00:18 +0000485 if ((fd < 0) && (errno == ENOENT))
486 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000487 char *pz_dir = strchr (fname + 1, '/');
Bruce Korb0083c901998-10-16 07:00:18 +0000488 struct stat stbf;
489
Bruce Korb1f414ac1999-03-03 07:41:52 +0000490 while (pz_dir != (char *) NULL)
Bruce Korb0083c901998-10-16 07:00:18 +0000491 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000492 *pz_dir = NUL;
Bruce Korb0083c901998-10-16 07:00:18 +0000493 if (stat (fname, &stbf) < 0)
494 {
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600495#ifdef _WIN32
496 mkdir (fname);
497#else
Bruce Korb063174e1999-11-04 14:50:44 +0000498 mkdir (fname, S_IFDIR | S_DIRALL);
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600499#endif
Bruce Korb0083c901998-10-16 07:00:18 +0000500 }
501
Bruce Korb1f414ac1999-03-03 07:41:52 +0000502 *pz_dir = '/';
503 pz_dir = strchr (pz_dir + 1, '/');
Bruce Korb0083c901998-10-16 07:00:18 +0000504 }
Bruce Korb1f414ac1999-03-03 07:41:52 +0000505
506 /* Now, lets try the open again... */
507 fd = open (fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRALL);
Bruce Korb0083c901998-10-16 07:00:18 +0000508 }
509 if (fd < 0)
510 {
511 fprintf (stderr, "Error %d (%s) creating %s\n",
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000512 errno, xstrerror (errno), fname);
Bruce Korb0083c901998-10-16 07:00:18 +0000513 exit (EXIT_FAILURE);
514 }
Bruce Korbb35926b1999-11-11 14:57:55 +0000515 if (NOT_SILENT)
516 fprintf (stderr, "Fixed: %s\n", pz_curr_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000517 pf = fdopen (fd, "w");
518
Bruce Korbe02ecf32000-07-19 14:10:41 +0000519 /*
520 * IF pz_machine is NULL, then we are in some sort of test mode.
521 * Do not insert the current directory name. Use a constant string.
522 */
523 fprintf (pf, z_std_preamble,
524 (pz_machine == NULL)
525 ? "fixinc/tests/inc"
526 : pz_input_dir,
527 pz_curr_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000528
Bruce Korb0083c901998-10-16 07:00:18 +0000529 return pf;
530}
531
Bruce Korb1f414ac1999-03-03 07:41:52 +0000532
533/* * * * * * * * * * * * *
534
535 test_test make sure a shell-style test expression passes.
536 Input: a pointer to the descriptor of the test to run and
537 the name of the file that we might want to fix
Bruce Korb5abc1f71999-10-12 14:44:18 +0000538 Result: APPLY_FIX or SKIP_FIX, depending on the result of the
Bruce Korb1f414ac1999-03-03 07:41:52 +0000539 shell script we run. */
Daniel Berlin283da1d2000-12-02 19:46:32 +0000540#ifndef SEPARATE_FIX_PROC
Bruce Korb6864a6c2000-12-02 19:01:16 +0000541static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000542test_test (tTestDesc* p_test, char* pz_test_file)
Bruce Korb0083c901998-10-16 07:00:18 +0000543{
Bruce Korb94db2f71999-05-12 07:32:58 +0000544 tSCC cmd_fmt[] =
545"file=%s\n\
546if ( test %s ) > /dev/null 2>&1\n\
547then echo TRUE\n\
548else echo FALSE\n\
549fi";
550
Bruce Korb1f414ac1999-03-03 07:41:52 +0000551 char *pz_res;
Bruce Korbe9099382000-05-17 14:56:13 +0000552 int res;
Bruce Korb0083c901998-10-16 07:00:18 +0000553
Bruce Korb1f414ac1999-03-03 07:41:52 +0000554 static char cmd_buf[4096];
Bruce Korb0083c901998-10-16 07:00:18 +0000555
Bruce Korb5abc1f71999-10-12 14:44:18 +0000556 sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
Bruce Korb1f414ac1999-03-03 07:41:52 +0000557 pz_res = run_shell (cmd_buf);
Bruce Korbe9099382000-05-17 14:56:13 +0000558
559 switch (*pz_res) {
560 case 'T':
Bruce Korb5abc1f71999-10-12 14:44:18 +0000561 res = APPLY_FIX;
Bruce Korbe9099382000-05-17 14:56:13 +0000562 break;
563
564 case 'F':
565 res = SKIP_FIX;
566 break;
567
568 default:
569 fprintf (stderr, "Script yielded bogus result of `%s':\n%s\n\n",
570 pz_res, cmd_buf );
James A. Morrison9cdfc8e2004-01-27 19:10:10 +0000571 res = SKIP_FIX;
Bruce Korbe9099382000-05-17 14:56:13 +0000572 }
573
Bruce Korb1f414ac1999-03-03 07:41:52 +0000574 free ((void *) pz_res);
Bruce Korb0083c901998-10-16 07:00:18 +0000575 return res;
576}
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000577#elif defined(__MINGW32__) || defined(__DJGPP__)
578static int
579test_test (tTestDesc* p_test, char* pz_test_file)
580{
581 tSCC cmd_fmt[] =
582#if defined(__DJGPP__)
583 "file=%s; test %s >/dev/null 2>/dev/null";
584#else
585 "file=%s; test %s > /dev/null 2>&1";
586#endif
587 int res;
588
589 char *cmd_buf = XNEWVEC (char, strlen(cmd_fmt) + strlen(pz_test_file) + strlen(p_test->pz_test_text));
590
591 sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
592 res = system_with_shell (cmd_buf);
593
594 free (cmd_buf);
595 return res ? SKIP_FIX : APPLY_FIX;
596}
Bruce Korb62a99402000-08-04 14:16:57 +0000597#else
598/*
599 * IF we are in MS-DOS land, then whatever shell-type test is required
600 * will, by definition, fail
601 */
602#define test_test(t,tf) SKIP_FIX
603#endif
Bruce Korb0083c901998-10-16 07:00:18 +0000604
Bruce Korb1f414ac1999-03-03 07:41:52 +0000605/* * * * * * * * * * * * *
Bruce Korb5abc1f71999-10-12 14:44:18 +0000606
Bruce Korb1f414ac1999-03-03 07:41:52 +0000607 egrep_test make sure an egrep expression is found in the file text.
608 Input: a pointer to the descriptor of the test to run and
609 the pointer to the contents of the file under suspicion
Bruce Korb5abc1f71999-10-12 14:44:18 +0000610 Result: APPLY_FIX if the pattern is found, SKIP_FIX otherwise
Bruce Korb1f414ac1999-03-03 07:41:52 +0000611
Bruce Korb5abc1f71999-10-12 14:44:18 +0000612 The caller may choose to reverse meaning if the sense of the test
Bruce Korb1f414ac1999-03-03 07:41:52 +0000613 is inverted. */
614
Bruce Korb6864a6c2000-12-02 19:01:16 +0000615static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000616egrep_test (char* pz_data, tTestDesc* p_test)
Bruce Korb0083c901998-10-16 07:00:18 +0000617{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000618#ifdef DEBUG
Bruce Korb1f414ac1999-03-03 07:41:52 +0000619 if (p_test->p_test_regex == 0)
620 fprintf (stderr, "fixincl ERROR RE not compiled: `%s'\n",
621 p_test->pz_test_text);
Bruce Korb0083c901998-10-16 07:00:18 +0000622#endif
Zack Weinbergab747402003-07-08 20:42:19 +0000623 if (xregexec (p_test->p_test_regex, pz_data, 0, 0, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000624 return APPLY_FIX;
625 return SKIP_FIX;
Bruce Korb0083c901998-10-16 07:00:18 +0000626}
627
Bruce Korb11c3a682015-01-28 20:21:34 +0000628/* * * * * * * * * * * * *
629
630 cksum_test check the sum of the candidate file
631 Input: the original file contents and the file name
632 Result: APPLY_FIX if the check sum matches, SKIP_FIX otherwise
633
634 The caller may choose to reverse meaning if the sense of the test
635 is inverted. */
636
637static int
638cksum_test (char * pz_data, tTestDesc * p_test, char * fname)
639{
640 unsigned int cksum;
641
642 /*
643 * Testing is off in normal operation mode.
644 * So, in testing mode, APPLY_FIX is always returned.
645 */
646 if (fixinc_mode != TESTING_OFF)
647 return APPLY_FIX;
648
649 {
650 char * fnm = strrchr(fname, '/');
651 if (fnm != NULL)
652 fname = fnm + 1;
653
654 errno = 0;
655 cksum = (unsigned int)strtoul(p_test->pz_test_text, &fnm, 10);
656 if (errno != 0)
657 return SKIP_FIX;
658
659 if (! ISSPACE(*fnm++))
660 return SKIP_FIX;
661 while (ISSPACE(*fnm)) fnm++;
662
663 if (! ISDIGIT(*fnm++))
664 return SKIP_FIX;
665 while (ISDIGIT(*fnm)) fnm++;
666
667 if (! ISSPACE(*fnm++))
668 return SKIP_FIX;
669 while (ISSPACE(*fnm)) fnm++;
670
671 if (strcmp(fnm, fname) != 0)
672 return SKIP_FIX;
673 }
674
675 {
676 unsigned int sum = 0;
677 while (*pz_data != NUL) {
678 sum = (sum >> 1) + ((sum & 1) << 15) + (unsigned)(*pz_data++);
679 sum &= 0xFFFF;
680 }
681
682 return (sum == cksum) ? APPLY_FIX : SKIP_FIX;
683 }
684}
Bruce Korb0083c901998-10-16 07:00:18 +0000685
Bruce Korb1f414ac1999-03-03 07:41:52 +0000686/* * * * * * * * * * * * *
Bruce Korb94db2f71999-05-12 07:32:58 +0000687
688 quoted_file_exists Make sure that a file exists before we emit
689 the file name. If we emit the name, our invoking shell will try
690 to copy a non-existing file into the destination directory. */
691
Bruce Korb6864a6c2000-12-02 19:01:16 +0000692static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000693quoted_file_exists (const char* pz_src_path,
694 const char* pz_file_path,
695 const char* pz_file)
Bruce Korb94db2f71999-05-12 07:32:58 +0000696{
697 char z[ MAXPATHLEN ];
698 char* pz;
699 sprintf (z, "%s/%s/", pz_src_path, pz_file_path);
700 pz = z + strlen ( z );
701
702 for (;;) {
703 char ch = *pz_file++;
Bruce Korb5abc1f71999-10-12 14:44:18 +0000704 if (! ISGRAPH( ch ))
Bruce Korb94db2f71999-05-12 07:32:58 +0000705 return 0;
706 if (ch == '"')
707 break;
708 *pz++ = ch;
709 }
710 *pz = '\0';
711 {
712 struct stat s;
713 if (stat (z, &s) != 0)
714 return 0;
715 return S_ISREG( s.st_mode );
716 }
717}
718
719
720/* * * * * * * * * * * * *
Bruce Korb1f414ac1999-03-03 07:41:52 +0000721 *
722 extract_quoted_files
Bruce Korb5abc1f71999-10-12 14:44:18 +0000723
Bruce Korb1f414ac1999-03-03 07:41:52 +0000724 The syntax, `#include "file.h"' specifies that the compiler is to
725 search the local directory of the current file before the include
726 list. Consequently, if we have modified a header and stored it in
727 another directory, any files that are included by that modified
728 file in that fashion must also be copied into this new directory.
729 This routine finds those flavors of #include and for each one found
730 emits a triple of:
Bruce Korb5abc1f71999-10-12 14:44:18 +0000731
Bruce Korb1f414ac1999-03-03 07:41:52 +0000732 1. source directory of the original file
733 2. the relative path file name of the #includ-ed file
734 3. the full destination path for this file
735
736 Input: the text of the file, the file name and a pointer to the
737 match list where the match information was stored.
738 Result: internally nothing. The results are written to stdout
739 for interpretation by the invoking shell */
Bruce Korb0083c901998-10-16 07:00:18 +0000740
Bruce Korb94db2f71999-05-12 07:32:58 +0000741
Bruce Korb6864a6c2000-12-02 19:01:16 +0000742static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000743extract_quoted_files (char* pz_data,
744 const char* pz_fixed_file,
745 regmatch_t* p_re_match)
Bruce Korb0083c901998-10-16 07:00:18 +0000746{
Bruce Korb5abc1f71999-10-12 14:44:18 +0000747 char *pz_dir_end = strrchr (pz_fixed_file, '/');
Bruce Korb1f414ac1999-03-03 07:41:52 +0000748 char *pz_incl_quot = pz_data;
Bruce Korb0083c901998-10-16 07:00:18 +0000749
Bruce Korbb35926b1999-11-11 14:57:55 +0000750 if (VLEVEL( VERB_APPLIES ))
751 fprintf (stderr, "Quoted includes in %s\n", pz_fixed_file);
Bruce Korb0083c901998-10-16 07:00:18 +0000752
Bruce Korb5abc1f71999-10-12 14:44:18 +0000753 /* Set "pz_fixed_file" to point to the containing subdirectory of the source
Bruce Korb94db2f71999-05-12 07:32:58 +0000754 If there is none, then it is in our current directory, ".". */
Bruce Korb1f414ac1999-03-03 07:41:52 +0000755
756 if (pz_dir_end == (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000757 pz_fixed_file = ".";
Bruce Korb0083c901998-10-16 07:00:18 +0000758 else
Bruce Korb1f414ac1999-03-03 07:41:52 +0000759 *pz_dir_end = '\0';
Bruce Korb0083c901998-10-16 07:00:18 +0000760
761 for (;;)
762 {
Bruce Korb1f414ac1999-03-03 07:41:52 +0000763 pz_incl_quot += p_re_match->rm_so;
Bruce Korb0083c901998-10-16 07:00:18 +0000764
Bruce Korb1f414ac1999-03-03 07:41:52 +0000765 /* Skip forward to the included file name */
Zack Weinbergf6bbde22000-12-08 03:00:26 +0000766 while (*pz_incl_quot != '"')
Bruce Korb1f414ac1999-03-03 07:41:52 +0000767 pz_incl_quot++;
Bruce Korb0083c901998-10-16 07:00:18 +0000768
Bruce Korb5abc1f71999-10-12 14:44:18 +0000769 if (quoted_file_exists (pz_src_dir, pz_fixed_file, pz_incl_quot))
Bruce Korb94db2f71999-05-12 07:32:58 +0000770 {
771 /* Print the source directory and the subdirectory
772 of the file in question. */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000773 printf ("%s %s/", pz_src_dir, pz_fixed_file);
Bruce Korb94db2f71999-05-12 07:32:58 +0000774 pz_dir_end = pz_incl_quot;
Bruce Korb0083c901998-10-16 07:00:18 +0000775
Bruce Korb94db2f71999-05-12 07:32:58 +0000776 /* Append to the directory the relative path of the desired file */
777 while (*pz_incl_quot != '"')
778 putc (*pz_incl_quot++, stdout);
Bruce Korb0083c901998-10-16 07:00:18 +0000779
Bruce Korb94db2f71999-05-12 07:32:58 +0000780 /* Now print the destination directory appended with the
781 relative path of the desired file */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000782 printf (" %s/%s/", pz_dest_dir, pz_fixed_file);
Bruce Korb94db2f71999-05-12 07:32:58 +0000783 while (*pz_dir_end != '"')
784 putc (*pz_dir_end++, stdout);
Bruce Korb0083c901998-10-16 07:00:18 +0000785
Bruce Korb94db2f71999-05-12 07:32:58 +0000786 /* End of entry */
787 putc ('\n', stdout);
788 }
Bruce Korb0083c901998-10-16 07:00:18 +0000789
Bruce Korb1f414ac1999-03-03 07:41:52 +0000790 /* Find the next entry */
Zack Weinbergab747402003-07-08 20:42:19 +0000791 if (xregexec (&incl_quote_re, pz_incl_quot, 1, p_re_match, 0) != 0)
Bruce Korb0083c901998-10-16 07:00:18 +0000792 break;
793 }
794}
795
796
Bruce Korb5abc1f71999-10-12 14:44:18 +0000797/* * * * * * * * * * * * *
798
799 Somebody wrote a *_fix subroutine that we must call.
800 */
Daniel Berlin283da1d2000-12-02 19:46:32 +0000801#ifndef SEPARATE_FIX_PROC
Bruce Korb6864a6c2000-12-02 19:01:16 +0000802static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000803internal_fix (int read_fd, tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +0000804{
805 int fd[2];
806
807 if (pipe( fd ) != 0)
808 {
809 fprintf (stderr, "Error %d on pipe(2) call\n", errno );
810 exit (EXIT_FAILURE);
811 }
812
813 for (;;)
814 {
815 pid_t childid = fork();
816
817 switch (childid)
818 {
819 case -1:
820 break;
821
822 case 0:
823 close (fd[0]);
824 goto do_child_task;
825
826 default:
827 /*
828 * Parent process
829 */
830 close (read_fd);
831 close (fd[1]);
832 return fd[0];
833 }
834
835 /*
836 * Parent in error
837 */
Zack Weinbergf95e46b2000-02-27 00:10:15 +0000838 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
Bruce Korb5abc1f71999-10-12 14:44:18 +0000839 p_fixd->fix_name);
840 {
841 static int failCt = 0;
842 if ((errno != EAGAIN) || (++failCt > 10))
843 exit (EXIT_FAILURE);
844 sleep (1);
845 }
846 } do_child_task:;
847
848 /*
849 * Close our current stdin and stdout
850 */
851 close (STDIN_FILENO);
852 close (STDOUT_FILENO);
853 UNLOAD_DATA();
854
855 /*
856 * Make the fd passed in the stdin, and the write end of
857 * the new pipe become the stdout.
858 */
Aaron W. LaFramboisef4a8f272004-10-20 02:21:09 -0600859 dup2 (fd[1], STDOUT_FILENO);
860 dup2 (read_fd, STDIN_FILENO);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000861
Bruce Korb35dfe412000-05-11 13:41:12 +0000862 apply_fix (p_fixd, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +0000863 exit (0);
864}
Daniel Berlin283da1d2000-12-02 19:46:32 +0000865#endif /* !SEPARATE_FIX_PROC */
Bruce Korb5abc1f71999-10-12 14:44:18 +0000866
Bruce Korbbb786201999-06-02 07:08:54 +0000867
Daniel Berlin283da1d2000-12-02 19:46:32 +0000868#ifdef SEPARATE_FIX_PROC
Bruce Korb62a99402000-08-04 14:16:57 +0000869static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +0000870fix_with_system (tFixDesc* p_fixd,
871 tCC* pz_fix_file,
872 tCC* pz_file_source,
873 tCC* pz_temp_file)
Bruce Korb62a99402000-08-04 14:16:57 +0000874{
875 char* pz_cmd;
876 char* pz_scan;
877 size_t argsize;
878
879 if (p_fixd->fd_flags & FD_SUBROUTINE)
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000880 {
881 static const char z_applyfix_prog[] =
Bruce Korb11c3a682015-01-28 20:21:34 +0000882 "/../fixincludes/applyfix" EXE_EXT;
Bruce Korb62a99402000-08-04 14:16:57 +0000883
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000884 struct stat buf;
885 argsize = 32
886 + strlen (pz_orig_dir)
887 + sizeof (z_applyfix_prog)
888 + strlen (pz_fix_file)
889 + strlen (pz_file_source)
890 + strlen (pz_temp_file);
Bruce Korb62a99402000-08-04 14:16:57 +0000891
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000892 /* Allocate something sure to be big enough for our purposes */
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000893 pz_cmd = XNEWVEC (char, argsize);
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000894 strcpy (pz_cmd, pz_orig_dir);
895 pz_scan = pz_cmd + strlen (pz_orig_dir);
Bruce Korb62a99402000-08-04 14:16:57 +0000896
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000897 strcpy (pz_scan, z_applyfix_prog);
Bruce Korb62a99402000-08-04 14:16:57 +0000898
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000899 /* IF we can't find the "applyfix" executable file at the first guess,
Bruce Korb11c3a682015-01-28 20:21:34 +0000900 try one level higher up */
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000901 if (stat (pz_cmd, &buf) == -1)
Bruce Korb11c3a682015-01-28 20:21:34 +0000902 {
903 strcpy (pz_scan, "/..");
904 strcpy (pz_scan+3, z_applyfix_prog);
905 }
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000906
907 pz_scan += strlen (pz_scan);
908
909 /*
910 * Now add the fix number and file names that may be needed
911 */
Tristan Gingoldc1041242012-04-24 09:24:55 +0000912 sprintf (pz_scan, " %ld '%s' '%s' '%s'", (long) (p_fixd - fixDescList),
Bruce Korb11c3a682015-01-28 20:21:34 +0000913 pz_fix_file, pz_file_source, pz_temp_file);
Bruce Korb43c1b5d2004-11-17 04:20:36 +0000914 }
Bruce Korb62a99402000-08-04 14:16:57 +0000915 else /* NOT an "internal" fix: */
916 {
917 size_t parg_size;
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000918#if defined(__MSDOS__) && !defined(__DJGPP__)
Bruce Korb62a99402000-08-04 14:16:57 +0000919 /* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
Daniel Berlin283da1d2000-12-02 19:46:32 +0000920 dst is a temporary file anyway, so we know there's no other
921 file by that name; and DOS's system(3) doesn't mind to
Eli Zaretskiidc13bad2000-08-21 19:28:18 +0300922 clobber existing file in redirection. Besides, with DOS 8+3
923 limited file namespace, we can easily lose if dst already has
924 an extension that is 3 or more characters long.
Daniel Berlin283da1d2000-12-02 19:46:32 +0000925
926 I do not think the 8+3 issue is relevant because all the files
927 we operate on are named "*.h", making 8+2 adequate. Anyway,
928 the following bizarre use of 'cat' only works on DOS boxes.
929 It causes the file to be dropped into a temporary file for
Eli Zaretskiidc13bad2000-08-21 19:28:18 +0300930 'cat' to read (pipes do not work on DOS). */
Bruce Korbecb0d202004-11-17 05:06:41 +0000931 tSCC z_cmd_fmt[] = " '%s' | cat > '%s'";
Daniel Berlin283da1d2000-12-02 19:46:32 +0000932#else
933 /* Don't use positional formatting arguments because some lame-o
934 implementations cannot cope :-(. */
935 tSCC z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
936#endif
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000937 tSCC z_subshell_start[] = "( ";
938 tSCC z_subshell_end[] = " ) < ";
Bruce Korb62a99402000-08-04 14:16:57 +0000939 tCC** ppArgs = p_fixd->patch_args;
940
941 argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
942 + strlen( pz_file_source );
943 parg_size = argsize;
944
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000945 if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
946 {
947 argsize += strlen( z_subshell_start ) + strlen ( z_subshell_end );
948 }
Bruce Korb62a99402000-08-04 14:16:57 +0000949
950 /*
951 * Compute the size of the command line. Add lotsa extra space
952 * because some of the args to sed use lotsa single quotes.
953 * (This requires three extra bytes per quote. Here we allow
954 * for up to 8 single quotes for each argument, including the
955 * command name "sed" itself. Nobody will *ever* need more. :)
956 */
957 for (;;)
958 {
959 tCC* p_arg = *(ppArgs++);
960 if (p_arg == NULL)
961 break;
962 argsize += 24 + strlen( p_arg );
963 }
964
965 /* Estimated buffer size we will need. */
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +0000966 pz_scan = pz_cmd = XNEWVEC (char, argsize);
Bruce Korb62a99402000-08-04 14:16:57 +0000967 /* How much of it do we allot to the program name and its
968 arguments. */
969 parg_size = argsize - parg_size;
970
971 ppArgs = p_fixd->patch_args;
972
973 /*
Tadek Kijkowski716028e42016-09-30 16:36:18 +0000974 * If it's shell script, enclose it in parentheses and skip "sh -c".
975 */
976 if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
977 {
978 strcpy (pz_scan, z_subshell_start);
979 pz_scan += strlen (z_subshell_start);
980 ppArgs += 2;
981 }
982
983 /*
Bruce Korb62a99402000-08-04 14:16:57 +0000984 * Copy the program name, unquoted
985 */
986 {
987 tCC* pArg = *(ppArgs++);
988 for (;;)
989 {
990 char ch = *(pArg++);
991 if (ch == NUL)
992 break;
993 *(pz_scan++) = ch;
994 }
995 }
996
997 /*
998 * Copy the program arguments, quoted
999 */
1000 for (;;)
1001 {
1002 tCC* pArg = *(ppArgs++);
Bruce Korb11c3a682015-01-28 20:21:34 +00001003 char* pz_scan_save;
Bruce Korb62a99402000-08-04 14:16:57 +00001004 if (pArg == NULL)
1005 break;
1006 *(pz_scan++) = ' ';
1007 pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
Bruce Korb11c3a682015-01-28 20:21:34 +00001008 parg_size - (pz_scan - pz_cmd) );
1009 /*
1010 * Make sure we don't overflow the buffer due to sloppy
1011 * size estimation.
1012 */
1013 while (pz_scan == (char*)NULL)
1014 {
1015 size_t already_filled = pz_scan_save - pz_cmd;
1016 pz_cmd = xrealloc (pz_cmd, argsize += 100);
1017 pz_scan_save = pz_scan = pz_cmd + already_filled;
1018 parg_size += 100;
1019 pz_scan = make_raw_shell_str( pz_scan, pArg,
1020 parg_size - (pz_scan - pz_cmd) );
1021 }
Bruce Korb62a99402000-08-04 14:16:57 +00001022 }
1023
1024 /*
Tadek Kijkowski716028e42016-09-30 16:36:18 +00001025 * Close parenthesis if it's shell script.
1026 */
1027 if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
1028 {
1029 strcpy (pz_scan, z_subshell_end);
1030 pz_scan += strlen (z_subshell_end);
1031 }
1032
1033 /*
Bruce Korb62a99402000-08-04 14:16:57 +00001034 * add the file machinations.
1035 */
Tadek Kijkowski716028e42016-09-30 16:36:18 +00001036#if defined(__MSDOS__) && !defined(__DJGPP__)
Daniel Berlin283da1d2000-12-02 19:46:32 +00001037 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
1038#else
1039 sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
1040 pz_temp_file, pz_temp_file, pz_temp_file);
1041#endif
Bruce Korb62a99402000-08-04 14:16:57 +00001042 }
Tadek Kijkowski716028e42016-09-30 16:36:18 +00001043 system_with_shell (pz_cmd);
1044 free (pz_cmd);
Bruce Korb62a99402000-08-04 14:16:57 +00001045}
1046
Bruce Korbbb786201999-06-02 07:08:54 +00001047/* * * * * * * * * * * * *
1048
1049 This loop should only cycle for 1/2 of one loop.
1050 "chain_open" starts a process that uses "read_fd" as
1051 its stdin and returns the new fd this process will use
1052 for stdout. */
1053
Daniel Berlin283da1d2000-12-02 19:46:32 +00001054#else /* is *NOT* SEPARATE_FIX_PROC */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001055static int
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001056start_fixer (int read_fd, tFixDesc* p_fixd, char* pz_fix_file)
Bruce Korbbb786201999-06-02 07:08:54 +00001057{
Bruce Korbbb786201999-06-02 07:08:54 +00001058 tCC* pz_cmd_save;
1059 char* pz_cmd;
1060
Bruce Korb5abc1f71999-10-12 14:44:18 +00001061 if ((p_fixd->fd_flags & FD_SUBROUTINE) != 0)
1062 return internal_fix (read_fd, p_fixd);
1063
Bruce Korbbb786201999-06-02 07:08:54 +00001064 if ((p_fixd->fd_flags & FD_SHELL_SCRIPT) == 0)
James A. Morrison9cdfc8e2004-01-27 19:10:10 +00001065 {
1066 pz_cmd = NULL;
1067 pz_cmd_save = NULL;
1068 }
Bruce Korbbb786201999-06-02 07:08:54 +00001069 else
1070 {
1071 tSCC z_cmd_fmt[] = "file='%s'\n%s";
Gabriel Dos Reis03a9fcb2005-05-15 18:28:36 +00001072 pz_cmd = XNEWVEC (char, strlen (p_fixd->patch_args[2])
Bruce Korb11c3a682015-01-28 20:21:34 +00001073 + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
Bruce Korb5abc1f71999-10-12 14:44:18 +00001074 sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
Bruce Korbbb786201999-06-02 07:08:54 +00001075 pz_cmd_save = p_fixd->patch_args[2];
1076 p_fixd->patch_args[2] = pz_cmd;
1077 }
1078
Bruce Korbb35926b1999-11-11 14:57:55 +00001079 /* Start a fix process, handing off the previous read fd for its
1080 stdin and getting a new fd that reads from the fix process' stdout.
1081 We normally will not loop, but we will up to 10 times if we keep
1082 getting "EAGAIN" errors.
1083
1084 */
Bruce Korbbb786201999-06-02 07:08:54 +00001085 for (;;)
1086 {
1087 static int failCt = 0;
1088 int fd;
1089
1090 fd = chain_open (read_fd,
Bruce Korb2629a112000-12-13 20:07:46 +00001091 (tCC **) p_fixd->patch_args,
Bruce Korbbb786201999-06-02 07:08:54 +00001092 (process_chain_head == -1)
1093 ? &process_chain_head : (pid_t *) NULL);
1094
1095 if (fd != -1)
1096 {
1097 read_fd = fd;
1098 break;
1099 }
1100
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001101 fprintf (stderr, z_fork_err, errno, xstrerror (errno),
Bruce Korbbb786201999-06-02 07:08:54 +00001102 p_fixd->fix_name);
1103
1104 if ((errno != EAGAIN) || (++failCt > 10))
1105 exit (EXIT_FAILURE);
1106 sleep (1);
1107 }
1108
Bruce Korbb35926b1999-11-11 14:57:55 +00001109 /* IF we allocated a shell script command,
1110 THEN free it and restore the command format to the fix description */
Bruce Korbbb786201999-06-02 07:08:54 +00001111 if (pz_cmd != (char*)NULL)
1112 {
1113 free ((void*)pz_cmd);
1114 p_fixd->patch_args[2] = pz_cmd_save;
1115 }
1116
1117 return read_fd;
1118}
Bruce Korb62a99402000-08-04 14:16:57 +00001119#endif
Bruce Korb11c3a682015-01-28 20:21:34 +00001120#ifdef DEBUG
1121# define NOTE_SKIP(_ttyp) do { \
1122 if (VLEVEL( VERB_EVERYTHING )) \
1123 fprintf (stderr, z_failed, _ttyp, p_fixd->fix_name, \
1124 pz_fname, p_fixd->test_ct - test_ct); \
1125 } while (0)
1126#else
1127# define NOTE_SKIP(_ttyp)
1128#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001129
1130/* * * * * * * * * * * * *
Bruce Korb401be4b2007-01-06 18:03:50 +00001131 *
1132 * Process the potential fixes for a particular include file.
1133 * Input: the original text of the file and the file's name
1134 * Result: none. A new file may or may not be created.
1135 */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001136static t_bool
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001137fix_applies (tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001138{
Zack Weinbergae5c8392000-01-22 20:55:18 +00001139 const char *pz_fname = pz_curr_file;
1140 const char *pz_scan = p_fixd->file_list;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001141 int test_ct;
1142 tTestDesc *p_test;
Bruce Korb11c3a682015-01-28 20:21:34 +00001143 t_bool saw_sum_test = BOOL_FALSE;
1144 t_bool one_sum_passed = BOOL_FALSE;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001145
Tadek Kijkowski716028e42016-09-30 16:36:18 +00001146#if defined(__MSDOS__) && !defined(__DJGPP__)
Bruce Korb62a99402000-08-04 14:16:57 +00001147 /*
1148 * There is only one fix that uses a shell script as of this writing.
1149 * I hope to nuke it anyway, it does not apply to DOS and it would
1150 * be painful to implement. Therefore, no "shell" fixes for DOS.
1151 */
1152 if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
1153 return BOOL_FALSE;
Bruce Korb401be4b2007-01-06 18:03:50 +00001154#else
Bruce Korb5abc1f71999-10-12 14:44:18 +00001155 if (p_fixd->fd_flags & FD_SKIP_TEST)
1156 return BOOL_FALSE;
Bruce Korb401be4b2007-01-06 18:03:50 +00001157#endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001158
1159 /* IF there is a file name restriction,
1160 THEN ensure the current file name matches one in the pattern */
1161
Zack Weinbergae5c8392000-01-22 20:55:18 +00001162 if (pz_scan != (char *) NULL)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001163 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001164 while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
1165 pz_fname += 2;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001166
1167 for (;;)
1168 {
Bruce Korb401be4b2007-01-06 18:03:50 +00001169 if (fnmatch (pz_scan, pz_fname, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001170 break;
Bruce Korb401be4b2007-01-06 18:03:50 +00001171 pz_scan += strlen (pz_scan) + 1;
1172 if (*pz_scan == NUL)
1173 return BOOL_FALSE;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001174 }
1175 }
1176
1177 /* FOR each test, see if it fails.
Bruce Korb11c3a682015-01-28 20:21:34 +00001178 "sum" fails only if all "sum" tests fail.
Bruce Korb5abc1f71999-10-12 14:44:18 +00001179 IF it does fail, then we go on to the next test */
1180
1181 for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
1182 test_ct-- > 0;
1183 p_test++)
1184 {
1185 switch (p_test->type)
1186 {
1187 case TT_TEST:
Bruce Korbb35926b1999-11-11 14:57:55 +00001188 if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
Bruce Korb11c3a682015-01-28 20:21:34 +00001189 NOTE_SKIP("TEST");
Bruce Korb5abc1f71999-10-12 14:44:18 +00001190 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001191 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001192 break;
1193
1194 case TT_EGREP:
Bruce Korbb35926b1999-11-11 14:57:55 +00001195 if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
Bruce Korb11c3a682015-01-28 20:21:34 +00001196 NOTE_SKIP("EGREP");
Bruce Korb5abc1f71999-10-12 14:44:18 +00001197 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001198 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001199 break;
1200
1201 case TT_NEGREP:
Bruce Korbb35926b1999-11-11 14:57:55 +00001202 if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
Bruce Korb11c3a682015-01-28 20:21:34 +00001203 NOTE_SKIP("NEGREP");
Bruce Korb5abc1f71999-10-12 14:44:18 +00001204 /* Negated sense */
1205 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001206 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001207 break;
1208
Bruce Korb11c3a682015-01-28 20:21:34 +00001209 case TT_CKSUM:
1210 if (one_sum_passed)
Uros Bizjakefdfdb22015-01-31 14:14:56 +01001211 break; /* No need to check any more */
Bruce Korb11c3a682015-01-28 20:21:34 +00001212
1213 saw_sum_test = BOOL_TRUE;
1214 if (cksum_test (pz_curr_data, p_test, pz_curr_file) != APPLY_FIX) {
1215 NOTE_SKIP("CKSUM");
1216 } else {
1217 one_sum_passed = BOOL_TRUE;
1218 }
1219 break;
1220
Bruce Korb5abc1f71999-10-12 14:44:18 +00001221 case TT_FUNCTION:
1222 if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
Bruce Korbb35926b1999-11-11 14:57:55 +00001223 != APPLY_FIX) {
Bruce Korb11c3a682015-01-28 20:21:34 +00001224 NOTE_SKIP("FTEST");
Bruce Korb5abc1f71999-10-12 14:44:18 +00001225 return BOOL_FALSE;
Bruce Korbb35926b1999-11-11 14:57:55 +00001226 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001227 break;
1228 }
1229 }
1230
Bruce Korb11c3a682015-01-28 20:21:34 +00001231 if (saw_sum_test)
1232 return one_sum_passed;
1233
Bruce Korb5abc1f71999-10-12 14:44:18 +00001234 return BOOL_TRUE;
1235}
1236
1237
1238/* * * * * * * * * * * * *
1239
1240 Write out a replacement file */
1241
Bruce Korb6864a6c2000-12-02 19:01:16 +00001242static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001243write_replacement (tFixDesc* p_fixd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001244{
1245 const char* pz_text = p_fixd->patch_args[0];
1246
1247 if ((pz_text == (char*)NULL) || (*pz_text == NUL))
1248 return;
1249
1250 {
Bruce Korb6864a6c2000-12-02 19:01:16 +00001251 FILE* out_fp = create_file ();
Bruce Korb66f788b2005-11-25 05:57:10 +00001252 size_t sz = strlen (pz_text);
1253 fwrite (pz_text, sz, 1, out_fp);
1254 if (pz_text[ sz-1 ] != '\n')
1255 fputc ('\n', out_fp);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001256 fclose (out_fp);
1257 }
1258}
1259
1260
1261/* * * * * * * * * * * * *
1262
1263 We have work to do. Read back in the output
1264 of the filtering chain. Compare each byte as we read it with
1265 the contents of the original file. As soon as we find any
1266 difference, we will create the output file, write out all
1267 the matched text and then copy any remaining data from the
1268 output of the filter chain.
1269 */
Bruce Korb6864a6c2000-12-02 19:01:16 +00001270static void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001271test_for_changes (int read_fd)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001272{
1273 FILE *in_fp = fdopen (read_fd, "r");
1274 FILE *out_fp = (FILE *) NULL;
Bruce Korb90376ae2001-07-21 04:08:29 +00001275 unsigned char *pz_cmp = (unsigned char*)pz_curr_data;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001276
1277#ifdef DO_STATS
1278 fixed_ct++;
1279#endif
1280 for (;;)
1281 {
1282 int ch;
1283
1284 ch = getc (in_fp);
1285 if (ch == EOF)
1286 break;
Bruce Korb90376ae2001-07-21 04:08:29 +00001287 ch &= 0xFF; /* all bytes are 8 bits */
Bruce Korb5abc1f71999-10-12 14:44:18 +00001288
1289 /* IF we are emitting the output
1290 THEN emit this character, too.
1291 */
1292 if (out_fp != (FILE *) NULL)
1293 putc (ch, out_fp);
1294
1295 /* ELSE if this character does not match the original,
1296 THEN now is the time to start the output.
1297 */
1298 else if (ch != *pz_cmp)
1299 {
Bruce Korb6864a6c2000-12-02 19:01:16 +00001300 out_fp = create_file ();
Bruce Korb5abc1f71999-10-12 14:44:18 +00001301
1302#ifdef DO_STATS
1303 altered_ct++;
1304#endif
1305 /* IF there are matched data, write the matched part now. */
Bruce Korbc8b0c192001-07-21 04:20:08 +00001306 if ((char*)pz_cmp != pz_curr_data)
1307 fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
Bruce Korb11c3a682015-01-28 20:21:34 +00001308 1, out_fp);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001309
1310 /* Emit the current unmatching character */
1311 putc (ch, out_fp);
1312 }
1313 else
1314 /* ELSE the character matches. Advance the compare ptr */
1315 pz_cmp++;
1316 }
1317
1318 /* IF we created the output file, ... */
1319 if (out_fp != (FILE *) NULL)
1320 {
1321 regmatch_t match;
1322
1323 /* Close the file and see if we have to worry about
1324 `#include "file.h"' constructs. */
1325 fclose (out_fp);
Zack Weinbergab747402003-07-08 20:42:19 +00001326 if (xregexec (&incl_quote_re, pz_curr_data, 1, &match, 0) == 0)
Bruce Korb5abc1f71999-10-12 14:44:18 +00001327 extract_quoted_files (pz_curr_data, pz_curr_file, &match);
1328 }
1329
1330 fclose (in_fp);
1331 close (read_fd); /* probably redundant, but I'm paranoid */
1332}
1333
1334
Bruce Korb1f414ac1999-03-03 07:41:52 +00001335/* * * * * * * * * * * * *
1336
1337 Process the potential fixes for a particular include file.
1338 Input: the original text of the file and the file's name
1339 Result: none. A new file may or may not be created. */
1340
Bruce Korb0083c901998-10-16 07:00:18 +00001341void
Nathanael Nerodef4dbf932003-08-01 23:07:04 +00001342process (void)
Bruce Korb0083c901998-10-16 07:00:18 +00001343{
Bruce Korb1f414ac1999-03-03 07:41:52 +00001344 tFixDesc *p_fixd = fixDescList;
1345 int todo_ct = FIX_COUNT;
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001346 int read_fd = -1;
Daniel Berlin283da1d2000-12-02 19:46:32 +00001347# ifndef SEPARATE_FIX_PROC
Rainer Orth9f8eec31999-05-17 12:39:19 +00001348 int num_children = 0;
Daniel Berlin283da1d2000-12-02 19:46:32 +00001349# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +00001350 char* pz_file_source = pz_curr_file;
1351# endif
Bruce Korb1f414ac1999-03-03 07:41:52 +00001352
Bruce Korb5abc1f71999-10-12 14:44:18 +00001353 if (access (pz_curr_file, R_OK) != 0)
1354 {
1355 int erno = errno;
1356 fprintf (stderr, "Cannot access %s from %s\n\terror %d (%s)\n",
1357 pz_curr_file, getcwd ((char *) NULL, MAXPATHLEN),
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001358 erno, xstrerror (erno));
Bruce Korb5abc1f71999-10-12 14:44:18 +00001359 return;
1360 }
1361
1362 pz_curr_data = load_file (pz_curr_file);
1363 if (pz_curr_data == (char *) NULL)
1364 return;
1365
1366#ifdef DO_STATS
1367 process_ct++;
1368#endif
Zack Weinbergd7eb5a41999-12-17 21:49:30 +00001369 if (VLEVEL( VERB_PROGRESS ) && have_tty)
Richard Henderson1c99d802003-01-21 17:02:51 -08001370 fprintf (stderr, "%6lu %-50s \r",
Bruce Korb11c3a682015-01-28 20:21:34 +00001371 (unsigned long) data_map_size, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001372
Daniel Berlin283da1d2000-12-02 19:46:32 +00001373# ifndef SEPARATE_FIX_PROC
Bruce Korb1f414ac1999-03-03 07:41:52 +00001374 process_chain_head = NOPROCESS;
Bruce Korb5abc1f71999-10-12 14:44:18 +00001375
Bruce Korb1f414ac1999-03-03 07:41:52 +00001376 /* For every fix in our fix list, ... */
1377 for (; todo_ct > 0; p_fixd++, todo_ct--)
Bruce Korb0083c901998-10-16 07:00:18 +00001378 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001379 if (! fix_applies (p_fixd))
Bruce Korb0083c901998-10-16 07:00:18 +00001380 continue;
1381
Bruce Korbb35926b1999-11-11 14:57:55 +00001382 if (VLEVEL( VERB_APPLIES ))
1383 fprintf (stderr, "Applying %-24s to %s\n",
1384 p_fixd->fix_name, pz_curr_file);
Bruce Korb5abc1f71999-10-12 14:44:18 +00001385
1386 if (p_fixd->fd_flags & FD_REPLACEMENT)
1387 {
1388 write_replacement (p_fixd);
1389 UNLOAD_DATA();
1390 return;
1391 }
Bruce Korb1f414ac1999-03-03 07:41:52 +00001392
1393 /* IF we do not have a read pointer,
1394 THEN this is the first fix for the current file.
1395 Open the source file. That will be used as stdin for
1396 the first fix. Any subsequent fixes will use the
Bruce Korb5abc1f71999-10-12 14:44:18 +00001397 stdout descriptor of the previous fix for its stdin. */
Bruce Korb1f414ac1999-03-03 07:41:52 +00001398
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001399 if (read_fd == -1)
Bruce Korb0083c901998-10-16 07:00:18 +00001400 {
Bruce Korb5abc1f71999-10-12 14:44:18 +00001401 read_fd = open (pz_curr_file, O_RDONLY);
Alexandre Oliva48ac9ce1999-05-20 07:10:41 +00001402 if (read_fd < 0)
Bruce Korb0083c901998-10-16 07:00:18 +00001403 {
Bruce Korb1f414ac1999-03-03 07:41:52 +00001404 fprintf (stderr, "Error %d (%s) opening %s\n", errno,
Zack Weinbergf95e46b2000-02-27 00:10:15 +00001405 xstrerror (errno), pz_curr_file);
Bruce Korb1f414ac1999-03-03 07:41:52 +00001406 exit (EXIT_FAILURE);
Bruce Korb0083c901998-10-16 07:00:18 +00001407 }
Bruce Korb5abc1f71999-10-12 14:44:18 +00001408
1409 /* Ensure we do not get duplicate output */
1410
1411 fflush (stdout);
Bruce Korb0083c901998-10-16 07:00:18 +00001412 }
1413
Bruce Korb5abc1f71999-10-12 14:44:18 +00001414 read_fd = start_fixer (read_fd, p_fixd, pz_curr_file);
Bruce Korbbb786201999-06-02 07:08:54 +00001415 num_children++;
Bruce Korb0083c901998-10-16 07:00:18 +00001416 }
1417
Bruce Korb5abc1f71999-10-12 14:44:18 +00001418 /* IF we have a read-back file descriptor,
1419 THEN check for changes and write output if changed. */
Bruce Korb1f414ac1999-03-03 07:41:52 +00001420
Bruce Korb5abc1f71999-10-12 14:44:18 +00001421 if (read_fd >= 0)
1422 {
1423 test_for_changes (read_fd);
1424#ifdef DO_STATS
1425 apply_ct += num_children;
1426#endif
1427 /* Wait for child processes created by chain_open()
1428 to avoid leaving zombies. */
1429 do {
1430 wait ((int *) NULL);
1431 } while (--num_children > 0);
1432 }
Bruce Korb0083c901998-10-16 07:00:18 +00001433
Daniel Berlin283da1d2000-12-02 19:46:32 +00001434# else /* is SEPARATE_FIX_PROC */
Bruce Korb62a99402000-08-04 14:16:57 +00001435
1436 for (; todo_ct > 0; p_fixd++, todo_ct--)
1437 {
1438 if (! fix_applies (p_fixd))
1439 continue;
1440
1441 if (VLEVEL( VERB_APPLIES ))
1442 fprintf (stderr, "Applying %-24s to %s\n",
1443 p_fixd->fix_name, pz_curr_file);
1444
1445 if (p_fixd->fd_flags & FD_REPLACEMENT)
1446 {
1447 write_replacement (p_fixd);
1448 UNLOAD_DATA();
1449 return;
1450 }
1451 fix_with_system (p_fixd, pz_curr_file, pz_file_source, pz_temp_file);
1452 pz_file_source = pz_temp_file;
1453 }
1454
Daniel Berlin283da1d2000-12-02 19:46:32 +00001455 read_fd = open (pz_temp_file, O_RDONLY);
1456 if (read_fd < 0)
1457 {
Bruce Korbca21b4a2001-02-06 22:19:50 +00001458 if (errno != ENOENT)
1459 fprintf (stderr, "error %d (%s) opening output (%s) for read\n",
1460 errno, xstrerror (errno), pz_temp_file);
Daniel Berlin283da1d2000-12-02 19:46:32 +00001461 }
1462 else
1463 {
1464 test_for_changes (read_fd);
1465 /* Unlinking a file while it is still open is a Bad Idea on
1466 DOS/Windows. */
1467 close (read_fd);
1468 unlink (pz_temp_file);
1469 }
Bruce Korb62a99402000-08-04 14:16:57 +00001470
1471# endif
Bruce Korb5abc1f71999-10-12 14:44:18 +00001472 UNLOAD_DATA();
Bruce Korb0083c901998-10-16 07:00:18 +00001473}