files which are fixed to work correctly with ANSI C and placed in a
directory that GCC will search.
- Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2012
+ Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "fixlib.h"
+#include <fnmatch.h>
#include <sys/stat.h>
+#ifndef SEPARATE_FIX_PROC
+#include <sys/wait.h>
+#endif
#if defined( HAVE_MMAP_FILE )
#include <sys/mman.h>
original, manufacturer supplied header file. */\n\n";
int find_base_len = 0;
-
-typedef enum {
- VERB_SILENT = 0,
- VERB_FIXES,
- VERB_APPLIES,
- VERB_PROGRESS,
- VERB_TESTS,
- VERB_EVERYTHING
-} te_verbose;
-
-te_verbose verbose_level = VERB_PROGRESS;
int have_tty = 0;
-#define VLEVEL(l) ((unsigned int) verbose_level >= (unsigned int) l)
-#define NOT_SILENT VLEVEL(VERB_FIXES)
-
pid_t process_chain_head = (pid_t) -1;
char* pz_curr_file; /* name of the current file under test/fix */
#endif /* DO_STATS */
const char incl_quote_pat[] = "^[ \t]*#[ \t]*include[ \t]*\"[^/]";
-tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
regex_t incl_quote_re;
+#ifndef SEPARATE_FIX_PROC
+tSCC z_fork_err[] = "Error %d (%s) starting filter process for %s\n";
+#endif
+
static void do_version (void) ATTRIBUTE_NORETURN;
char *load_file (const char *);
void run_compiles (void);
puts (zBuf + 5);
exit (strcmp (run_shell (zBuf), program_id));
#else
- exit (system (zBuf));
+ exit (system_with_shell (zBuf));
#endif
}
/* NULL as the first argument to `tempnam' causes it to DTRT
wrt the temporary directory where the file will be created. */
pz_temp_file = tempnam( NULL, "fxinc" );
+
+#if defined(__MINGW32__)
+ fix_path_separators (pz_temp_file);
+#endif
+
# endif
signal (SIGQUIT, SIG_IGN);
static int
machine_matches( tFixDesc* p_fixd )
- {
-# ifndef SEPARATE_FIX_PROC
- tSCC case_fmt[] = "case %s in\n"; /* 9 bytes, plus string */
- tSCC esac_fmt[] =
- " )\n echo %s ;;\n* ) echo %s ;;\nesac";/* 4 bytes */
- tSCC skip[] = "skip"; /* 4 bytes */
- tSCC run[] = "run"; /* 3 bytes */
- /* total bytes to add to machine sum: 49 - see fixincl.tpl */
-
- const char **papz_machs = p_fixd->papz_machs;
- char *pz;
- const char *pz_sep = "";
- tCC *pz_if_true;
- tCC *pz_if_false;
- char cmd_buf[ MACH_LIST_SIZE_LIMIT ]; /* size lim from fixincl.tpl */
-
- /* Start the case statement */
-
- sprintf (cmd_buf, case_fmt, pz_machine);
- pz = cmd_buf + strlen (cmd_buf);
-
- /* Determine if a match means to apply the fix or not apply it */
-
- if (p_fixd->fd_flags & FD_MACH_IFNOT)
- {
- pz_if_true = skip;
- pz_if_false = run;
- }
- else
- {
- pz_if_true = run;
- pz_if_false = skip;
- }
-
- /* Emit all the machine names. If there are more than one,
- then we will insert " | \\\n" between the names */
-
- for (;;)
- {
- const char* pz_mach = *(papz_machs++);
-
- if (pz_mach == (const char*) NULL)
- break;
- sprintf (pz, "%s%s", pz_sep, pz_mach);
- pz += strlen (pz);
- pz_sep = " | \\\n";
- }
-
- /* Now emit the match and not-match actions and the esac */
-
- sprintf (pz, esac_fmt, pz_if_true, pz_if_false);
-
- /* Run the script.
- The result will start either with 's' or 'r'. */
-
- {
- int skip;
- pz = run_shell (cmd_buf);
- skip = (*pz == 's');
- free ( (void*)pz );
- if (skip)
- {
- p_fixd->fd_flags |= FD_SKIP_TEST;
- return BOOL_FALSE;
- }
- }
+{
+ char const ** papz_machs = p_fixd->papz_machs;
+ int have_match = BOOL_FALSE;
- return BOOL_TRUE;
-# else /* is SEPARATE_FIX_PROC */
- const char **papz_machs = p_fixd->papz_machs;
- int invert = (p_fixd->fd_flags & FD_MACH_IFNOT) != 0;
for (;;)
{
- const char* pz_mach = *(papz_machs++);
-
- if (pz_mach == (const char*) NULL)
+ char const * pz_mpat = *(papz_machs++);
+ if (pz_mpat == NULL)
break;
- if (strstr (pz_mach, "dos") != NULL && !invert)
- return BOOL_TRUE;
+ if (fnmatch(pz_mpat, pz_machine, 0) == 0)
+ {
+ have_match = BOOL_TRUE;
+ break;
+ }
}
- p_fixd->fd_flags |= FD_SKIP_TEST;
- return BOOL_FALSE;
-# endif
+ /* Check for sense inversion then set the "skip test" flag, if needed */
+ if (p_fixd->fd_flags & FD_MACH_IFNOT)
+ have_match = ! have_match;
+
+ if (! have_match)
+ p_fixd->fd_flags |= FD_SKIP_TEST;
+
+ return have_match;
}
/* * * * * * * * * * * * *
-
- run_compiles run all the regexp compiles for all the fixes once.
- */
+ *
+ * run_compiles run all the regexp compiles for all the fixes once.
+ */
void
run_compiles (void)
{
tFixDesc *p_fixd = fixDescList;
int fix_ct = FIX_COUNT;
- regex_t *p_re = xcalloc (REGEX_COUNT, sizeof (regex_t));
+ regex_t *p_re = XCNEWVEC (regex_t, REGEX_COUNT);
/* Make sure compile_re does not stumble across invalid data */
/* FOR every fixup, ... */
do
{
- tTestDesc *p_test = p_fixd->p_test_desc;
- int test_ct = p_fixd->test_ct;
+ tTestDesc *p_test;
+ int test_ct;
+
+ if (fixinc_mode && (p_fixd->fd_flags & FD_REPLACEMENT))
+ {
+ p_fixd->fd_flags |= FD_SKIP_TEST;
+ continue;
+ }
+
+ p_test = p_fixd->p_test_desc;
+ test_ct = p_fixd->test_ct;
/* IF the machine type pointer is not NULL (we are not in test mode)
AND this test is for or not done on particular machines
free ((void *) pz_res);
return res;
}
+#elif defined(__MINGW32__) || defined(__DJGPP__)
+static int
+test_test (tTestDesc* p_test, char* pz_test_file)
+{
+ tSCC cmd_fmt[] =
+#if defined(__DJGPP__)
+ "file=%s; test %s >/dev/null 2>/dev/null";
+#else
+ "file=%s; test %s > /dev/null 2>&1";
+#endif
+ int res;
+
+ char *cmd_buf = XNEWVEC (char, strlen(cmd_fmt) + strlen(pz_test_file) + strlen(p_test->pz_test_text));
+
+ sprintf (cmd_buf, cmd_fmt, pz_test_file, p_test->pz_test_text);
+ res = system_with_shell (cmd_buf);
+
+ free (cmd_buf);
+ return res ? SKIP_FIX : APPLY_FIX;
+}
#else
/*
* IF we are in MS-DOS land, then whatever shell-type test is required
return SKIP_FIX;
}
+/* * * * * * * * * * * * *
+
+ cksum_test check the sum of the candidate file
+ Input: the original file contents and the file name
+ Result: APPLY_FIX if the check sum matches, SKIP_FIX otherwise
+
+ The caller may choose to reverse meaning if the sense of the test
+ is inverted. */
+
+static int
+cksum_test (char * pz_data, tTestDesc * p_test, char * fname)
+{
+ unsigned int cksum;
+
+ /*
+ * Testing is off in normal operation mode.
+ * So, in testing mode, APPLY_FIX is always returned.
+ */
+ if (fixinc_mode != TESTING_OFF)
+ return APPLY_FIX;
+
+ {
+ char * fnm = strrchr(fname, '/');
+ if (fnm != NULL)
+ fname = fnm + 1;
+
+ errno = 0;
+ cksum = (unsigned int)strtoul(p_test->pz_test_text, &fnm, 10);
+ if (errno != 0)
+ return SKIP_FIX;
+
+ if (! ISSPACE(*fnm++))
+ return SKIP_FIX;
+ while (ISSPACE(*fnm)) fnm++;
+
+ if (! ISDIGIT(*fnm++))
+ return SKIP_FIX;
+ while (ISDIGIT(*fnm)) fnm++;
+
+ if (! ISSPACE(*fnm++))
+ return SKIP_FIX;
+ while (ISSPACE(*fnm)) fnm++;
+
+ if (strcmp(fnm, fname) != 0)
+ return SKIP_FIX;
+ }
+
+ {
+ unsigned int sum = 0;
+ while (*pz_data != NUL) {
+ sum = (sum >> 1) + ((sum & 1) << 15) + (unsigned)(*pz_data++);
+ sum &= 0xFFFF;
+ }
+
+ return (sum == cksum) ? APPLY_FIX : SKIP_FIX;
+ }
+}
/* * * * * * * * * * * * *
char* pz_cmd;
char* pz_scan;
size_t argsize;
- int i;
- tSCC z_applyfix_prog[2] = {
- "/../fixincludes/applyfix" EXE_EXT,
- "/../../fixincludes/applyfix" EXE_EXT };
if (p_fixd->fd_flags & FD_SUBROUTINE)
- for (i = 0; i < 2; i++)
- {
- struct stat buf;
-
- argsize = 32
- + strlen( pz_orig_dir )
- + sizeof( z_applyfix_prog )
- + strlen( pz_fix_file )
- + strlen( pz_file_source )
- + strlen( pz_temp_file );
-
- pz_cmd = xmalloc (argsize);
-
- strcpy( pz_cmd, pz_orig_dir );
- pz_scan = pz_cmd + strlen( pz_orig_dir );
- strcpy( pz_scan, z_applyfix_prog );
- pz_scan += sizeof( z_applyfix_prog ) - 1;
-
- if (stat (pz_scan, &buf) != -1)
- {
- *(pz_scan++) = ' ';
- /*
- * Now add the fix number and file names that may be needed
- */
- sprintf (pz_scan, "%ld \'%s\' \'%s\' \'%s\'", p_fixd - fixDescList,
- pz_fix_file, pz_file_source, pz_temp_file);
- break;
- }
- }
+ {
+ static const char z_applyfix_prog[] =
+ "/../fixincludes/applyfix" EXE_EXT;
+
+ struct stat buf;
+ argsize = 32
+ + strlen (pz_orig_dir)
+ + sizeof (z_applyfix_prog)
+ + strlen (pz_fix_file)
+ + strlen (pz_file_source)
+ + strlen (pz_temp_file);
+
+ /* Allocate something sure to be big enough for our purposes */
+ pz_cmd = XNEWVEC (char, argsize);
+ strcpy (pz_cmd, pz_orig_dir);
+ pz_scan = pz_cmd + strlen (pz_orig_dir);
+
+ strcpy (pz_scan, z_applyfix_prog);
+
+ /* IF we can't find the "applyfix" executable file at the first guess,
+ try one level higher up */
+ if (stat (pz_cmd, &buf) == -1)
+ {
+ strcpy (pz_scan, "/..");
+ strcpy (pz_scan+3, z_applyfix_prog);
+ }
+
+ pz_scan += strlen (pz_scan);
+
+ /*
+ * Now add the fix number and file names that may be needed
+ */
+ sprintf (pz_scan, " %ld '%s' '%s' '%s'", (long) (p_fixd - fixDescList),
+ pz_fix_file, pz_file_source, pz_temp_file);
+ }
else /* NOT an "internal" fix: */
{
size_t parg_size;
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__DJGPP__)
/* Don't use the "src > dstX; rm -f dst; mv -f dstX dst" trick:
dst is a temporary file anyway, so we know there's no other
file by that name; and DOS's system(3) doesn't mind to
the following bizarre use of 'cat' only works on DOS boxes.
It causes the file to be dropped into a temporary file for
'cat' to read (pipes do not work on DOS). */
- tSCC z_cmd_fmt[] = " \'%s\' | cat > \'%s\'";
+ tSCC z_cmd_fmt[] = " '%s' | cat > '%s'";
#else
/* Don't use positional formatting arguments because some lame-o
implementations cannot cope :-(. */
tSCC z_cmd_fmt[] = " %s > %sX ; rm -f %s; mv -f %sX %s";
#endif
+ tSCC z_subshell_start[] = "( ";
+ tSCC z_subshell_end[] = " ) < ";
tCC** ppArgs = p_fixd->patch_args;
argsize = sizeof( z_cmd_fmt ) + strlen( pz_temp_file )
+ strlen( pz_file_source );
parg_size = argsize;
+ if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
+ {
+ argsize += strlen( z_subshell_start ) + strlen ( z_subshell_end );
+ }
/*
* Compute the size of the command line. Add lotsa extra space
}
/* Estimated buffer size we will need. */
- pz_scan = pz_cmd = xmalloc (argsize);
+ pz_scan = pz_cmd = XNEWVEC (char, argsize);
/* How much of it do we allot to the program name and its
arguments. */
parg_size = argsize - parg_size;
ppArgs = p_fixd->patch_args;
+ /*
+ * If it's shell script, enclose it in parentheses and skip "sh -c".
+ */
+ if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
+ {
+ strcpy (pz_scan, z_subshell_start);
+ pz_scan += strlen (z_subshell_start);
+ ppArgs += 2;
+ }
+
/*
* Copy the program name, unquoted
*/
for (;;)
{
tCC* pArg = *(ppArgs++);
- char* pz_scan_save;
+ char* pz_scan_save;
if (pArg == NULL)
break;
*(pz_scan++) = ' ';
pz_scan = make_raw_shell_str( pz_scan_save = pz_scan, pArg,
- parg_size - (pz_scan - pz_cmd) );
- /*
- * Make sure we don't overflow the buffer due to sloppy
- * size estimation.
- */
- while (pz_scan == (char*)NULL)
- {
- size_t already_filled = pz_scan_save - pz_cmd;
- pz_cmd = xrealloc (pz_cmd, argsize += 100);
- pz_scan_save = pz_scan = pz_cmd + already_filled;
- parg_size += 100;
- pz_scan = make_raw_shell_str( pz_scan, pArg,
- parg_size - (pz_scan - pz_cmd) );
- }
+ parg_size - (pz_scan - pz_cmd) );
+ /*
+ * Make sure we don't overflow the buffer due to sloppy
+ * size estimation.
+ */
+ while (pz_scan == (char*)NULL)
+ {
+ size_t already_filled = pz_scan_save - pz_cmd;
+ pz_cmd = xrealloc (pz_cmd, argsize += 100);
+ pz_scan_save = pz_scan = pz_cmd + already_filled;
+ parg_size += 100;
+ pz_scan = make_raw_shell_str( pz_scan, pArg,
+ parg_size - (pz_scan - pz_cmd) );
+ }
+ }
+
+ /*
+ * Close parenthesis if it's shell script.
+ */
+ if (p_fixd->fd_flags & FD_SHELL_SCRIPT)
+ {
+ strcpy (pz_scan, z_subshell_end);
+ pz_scan += strlen (z_subshell_end);
}
/*
* add the file machinations.
*/
-#ifdef __MSDOS__
+#if defined(__MSDOS__) && !defined(__DJGPP__)
sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file );
#else
sprintf (pz_scan, z_cmd_fmt, pz_file_source, pz_temp_file,
pz_temp_file, pz_temp_file, pz_temp_file);
#endif
}
- system( pz_cmd );
- free( (void*)pz_cmd );
+ system_with_shell (pz_cmd);
+ free (pz_cmd);
}
/* * * * * * * * * * * * *
else
{
tSCC z_cmd_fmt[] = "file='%s'\n%s";
- pz_cmd = xmalloc (strlen (p_fixd->patch_args[2])
- + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
+ pz_cmd = XNEWVEC (char, strlen (p_fixd->patch_args[2])
+ + sizeof (z_cmd_fmt) + strlen (pz_fix_file));
sprintf (pz_cmd, z_cmd_fmt, pz_fix_file, p_fixd->patch_args[2]);
pz_cmd_save = p_fixd->patch_args[2];
p_fixd->patch_args[2] = pz_cmd;
return read_fd;
}
#endif
-
+#ifdef DEBUG
+# define NOTE_SKIP(_ttyp) do { \
+ if (VLEVEL( VERB_EVERYTHING )) \
+ fprintf (stderr, z_failed, _ttyp, p_fixd->fix_name, \
+ pz_fname, p_fixd->test_ct - test_ct); \
+ } while (0)
+#else
+# define NOTE_SKIP(_ttyp)
+#endif
/* * * * * * * * * * * * *
-
- Process the potential fixes for a particular include file.
- Input: the original text of the file and the file's name
- Result: none. A new file may or may not be created. */
-
+ *
+ * Process the potential fixes for a particular include file.
+ * Input: the original text of the file and the file's name
+ * Result: none. A new file may or may not be created.
+ */
static t_bool
fix_applies (tFixDesc* p_fixd)
{
const char *pz_scan = p_fixd->file_list;
int test_ct;
tTestDesc *p_test;
+ t_bool saw_sum_test = BOOL_FALSE;
+ t_bool one_sum_passed = BOOL_FALSE;
-# ifdef SEPARATE_FIX_PROC
+#if defined(__MSDOS__) && !defined(__DJGPP__)
/*
* There is only one fix that uses a shell script as of this writing.
* I hope to nuke it anyway, it does not apply to DOS and it would
*/
if (p_fixd->fd_flags & (FD_SHELL_SCRIPT | FD_SKIP_TEST))
return BOOL_FALSE;
-# else
+#else
if (p_fixd->fd_flags & FD_SKIP_TEST)
return BOOL_FALSE;
-# endif
+#endif
/* IF there is a file name restriction,
THEN ensure the current file name matches one in the pattern */
if (pz_scan != (char *) NULL)
{
- size_t name_len;
-
while ((pz_fname[0] == '.') && (pz_fname[1] == '/'))
pz_fname += 2;
- name_len = strlen (pz_fname);
for (;;)
{
- pz_scan = strstr (pz_scan + 1, pz_fname);
- /* IF we can't match the string at all,
- THEN bail */
- if (pz_scan == (char *) NULL)
- return BOOL_FALSE;
-
- /* IF the match is surrounded by the '|' markers,
- THEN we found a full match -- time to run the tests */
-
- if ((pz_scan[-1] == '|') && (pz_scan[name_len] == '|'))
+ if (fnmatch (pz_scan, pz_fname, 0) == 0)
break;
+ pz_scan += strlen (pz_scan) + 1;
+ if (*pz_scan == NUL)
+ return BOOL_FALSE;
}
}
/* FOR each test, see if it fails.
+ "sum" fails only if all "sum" tests fail.
IF it does fail, then we go on to the next test */
for (p_test = p_fixd->p_test_desc, test_ct = p_fixd->test_ct;
{
case TT_TEST:
if (test_test (p_test, pz_curr_file) != APPLY_FIX) {
-#ifdef DEBUG
- if (VLEVEL( VERB_EVERYTHING ))
- fprintf (stderr, z_failed, "TEST", p_fixd->fix_name,
- pz_fname, p_fixd->test_ct - test_ct);
-#endif
+ NOTE_SKIP("TEST");
return BOOL_FALSE;
}
break;
case TT_EGREP:
if (egrep_test (pz_curr_data, p_test) != APPLY_FIX) {
-#ifdef DEBUG
- if (VLEVEL( VERB_EVERYTHING ))
- fprintf (stderr, z_failed, "EGREP", p_fixd->fix_name,
- pz_fname, p_fixd->test_ct - test_ct);
-#endif
+ NOTE_SKIP("EGREP");
return BOOL_FALSE;
}
break;
case TT_NEGREP:
if (egrep_test (pz_curr_data, p_test) == APPLY_FIX) {
-#ifdef DEBUG
- if (VLEVEL( VERB_EVERYTHING ))
- fprintf (stderr, z_failed, "NEGREP", p_fixd->fix_name,
- pz_fname, p_fixd->test_ct - test_ct);
-#endif
+ NOTE_SKIP("NEGREP");
/* Negated sense */
return BOOL_FALSE;
}
break;
+ case TT_CKSUM:
+ if (one_sum_passed)
+ break; /* No need to check any more */
+
+ saw_sum_test = BOOL_TRUE;
+ if (cksum_test (pz_curr_data, p_test, pz_curr_file) != APPLY_FIX) {
+ NOTE_SKIP("CKSUM");
+ } else {
+ one_sum_passed = BOOL_TRUE;
+ }
+ break;
+
case TT_FUNCTION:
if (run_test (p_test->pz_test_text, pz_curr_file, pz_curr_data)
!= APPLY_FIX) {
-#ifdef DEBUG
- if (VLEVEL( VERB_EVERYTHING ))
- fprintf (stderr, z_failed, "FTEST", p_fixd->fix_name,
- pz_fname, p_fixd->test_ct - test_ct);
-#endif
+ NOTE_SKIP("FTEST");
return BOOL_FALSE;
}
break;
}
}
+ if (saw_sum_test)
+ return one_sum_passed;
+
return BOOL_TRUE;
}
{
FILE* out_fp = create_file ();
- fputs (pz_text, out_fp);
+ size_t sz = strlen (pz_text);
+ fwrite (pz_text, sz, 1, out_fp);
+ if (pz_text[ sz-1 ] != '\n')
+ fputc ('\n', out_fp);
fclose (out_fp);
}
}
/* IF there are matched data, write the matched part now. */
if ((char*)pz_cmp != pz_curr_data)
fwrite (pz_curr_data, (size_t)((char*)pz_cmp - pz_curr_data),
- 1, out_fp);
+ 1, out_fp);
/* Emit the current unmatching character */
putc (ch, out_fp);
#endif
if (VLEVEL( VERB_PROGRESS ) && have_tty)
fprintf (stderr, "%6lu %-50s \r",
- (unsigned long) data_map_size, pz_curr_file);
+ (unsigned long) data_map_size, pz_curr_file);
# ifndef SEPARATE_FIX_PROC
process_chain_head = NOPROCESS;