Use C-coded tests and fixes for #endif/#else labels
From-SVN: r30130
This commit is contained in:
parent
5685b5d3c2
commit
8f9ca91274
7 changed files with 344 additions and 81 deletions
|
@ -1,3 +1,13 @@
|
|||
1999-10-22 Bruce Korb <autogen@linuxbox.com>
|
||||
|
||||
* fixinc/README: document the "mach" machine matching test
|
||||
* fixinc/fixfixes.c: Implement the #else/#endif label fix
|
||||
* fixinc/fixtests.c: Implement the #else/#endif label test
|
||||
* fixinc/inclhack.def: utilize these tests and fixes
|
||||
* fixinc/inclhack.sh: regen
|
||||
* fixinc/fixincl.x: regen
|
||||
* fixinc/fixincl.sh: regen
|
||||
|
||||
Thu Oct 21 20:37:19 1999 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* Makefile.in (cse.o): Depend on hashtab.h, not splay-tree.h. Also
|
||||
|
|
|
@ -71,7 +71,10 @@ Here are the rules for making fixes in the inclhack.def file:
|
|||
"c_test" because they are performed internally. "test" sends
|
||||
a command to a server shell that actually fires off one or more
|
||||
processes to do the testing. Avoid it, if you can, but it is
|
||||
still more efficient than a fix process.
|
||||
still more efficient than a fix process. Also available is
|
||||
"mach". If the target machine matches any of the named
|
||||
globbing-style patterns, then the machine name test will pass.
|
||||
It is desired, however, to limit the use of this test.
|
||||
|
||||
These tests are required to:
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ typedef struct {
|
|||
} fix_entry_t;
|
||||
|
||||
#define FIXUP_TABLE \
|
||||
_FT_( "no_double_slash", double_slash_fix )
|
||||
_FT_( "no_double_slash", double_slash_fix ) \
|
||||
_FT_( "else_endif_label", else_endif_label_fix )
|
||||
|
||||
|
||||
#define FIX_PROC_HEAD( fix ) \
|
||||
|
@ -180,6 +181,184 @@ FIX_PROC_HEAD( double_slash_fix )
|
|||
fclose (stdout);;
|
||||
}
|
||||
|
||||
|
||||
FIX_PROC_HEAD( else_endif_label_fix )
|
||||
{
|
||||
static const char label_pat[] = "^[ \t]*#[ \t]*(else|endif)";
|
||||
static regex_t label_re;
|
||||
|
||||
char ch;
|
||||
char* pz_next = (char*)NULL;
|
||||
regmatch_t match[2];
|
||||
|
||||
re_set_syntax (RE_SYNTAX_EGREP);
|
||||
(void)re_compile_pattern (label_pat, sizeof (label_pat)-1,
|
||||
&label_re);
|
||||
|
||||
for (;;) /* entire file */
|
||||
{
|
||||
/*
|
||||
See if we need to advance to the next candidate directive
|
||||
If the scanning pointer passes over the end of the directive,
|
||||
then the directive is inside a comment */
|
||||
if (pz_next < text)
|
||||
{
|
||||
if (regexec (&label_re, text, 2, match, 0) != 0)
|
||||
{
|
||||
fputs( text, stdout );
|
||||
break;
|
||||
}
|
||||
|
||||
pz_next = text + match[0].rm_eo;
|
||||
}
|
||||
|
||||
/*
|
||||
IF the scan pointer has not reached the directive end, ... */
|
||||
if (pz_next > text)
|
||||
{
|
||||
/*
|
||||
Advance the scanning pointer. If we are at the start
|
||||
of a quoted string or a comment, then skip the entire unit */
|
||||
ch = *text;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '/':
|
||||
/*
|
||||
Skip comments */
|
||||
if (text[1] == '*')
|
||||
{
|
||||
char* pz = strstr( text+2, "*/" );
|
||||
if (pz == (char*)NULL)
|
||||
{
|
||||
fputs( text, stdout );
|
||||
return;
|
||||
}
|
||||
pz += 2;
|
||||
fwrite( text, 1, (pz - text), stdout );
|
||||
text = pz;
|
||||
continue;
|
||||
}
|
||||
putc( ch, stdout );
|
||||
text++;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
text = print_quote( ch, text+1 );
|
||||
break;
|
||||
|
||||
default:
|
||||
putc( ch, stdout );
|
||||
text++;
|
||||
} /* switch (ch) */
|
||||
continue;
|
||||
} /* if (still shy of directive end) */
|
||||
|
||||
/*
|
||||
The scanning pointer (text) has reached the end of the current
|
||||
directive under test. Check for bogons here. */
|
||||
for (;;) /* bogon check */
|
||||
{
|
||||
char ch = *(text++);
|
||||
if (isspace (ch))
|
||||
{
|
||||
putc( ch, stdout );
|
||||
if (ch == '\n')
|
||||
{
|
||||
/*
|
||||
It is clean. No bogons on this directive */
|
||||
pz_next = (char*)NULL; /* force a new regex search */
|
||||
goto dont_fix_bogon;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case NUL:
|
||||
return;
|
||||
|
||||
case '\\':
|
||||
/*
|
||||
Skip escaped newlines. Otherwise, we have a bogon */
|
||||
if (*text != '\n') {
|
||||
text--;
|
||||
goto fix_the_bogon;
|
||||
}
|
||||
|
||||
/*
|
||||
Emit the escaped newline and keep scanning for possible junk */
|
||||
putc( '\\', stdout );
|
||||
putc( '\n', stdout );
|
||||
text++;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
/*
|
||||
Skip comments. Otherwise, we have a bogon */
|
||||
if (*text == '*')
|
||||
{
|
||||
text--;
|
||||
pz_next = strstr( text+2, "*/" );
|
||||
if (pz_next == (char*)NULL)
|
||||
{
|
||||
putc( '\n', stdout );
|
||||
return;
|
||||
}
|
||||
pz_next += 2;
|
||||
fwrite( text, 1, (pz_next - text), stdout );
|
||||
text = pz_next;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: if this is a C++ file, then a double slash comment
|
||||
is allowed to follow the directive. */
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
/*
|
||||
GOTTA BE A BOGON */
|
||||
text--;
|
||||
goto fix_the_bogon;
|
||||
} /* switch (ch) */
|
||||
} /* for (bogon check loop) */
|
||||
|
||||
fix_the_bogon:
|
||||
/*
|
||||
`text' points to the start of the bogus data */
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
NOT an escaped newline. Find the end of line that
|
||||
is not preceeded by an escape character: */
|
||||
pz_next = strchr( text, '\n' );
|
||||
if (pz_next == (char*)NULL)
|
||||
{
|
||||
putc( '\n', stdout );
|
||||
return;
|
||||
}
|
||||
|
||||
if (pz_next[-1] != '\\')
|
||||
{
|
||||
text = pz_next;
|
||||
pz_next = (char*)NULL; /* force a new regex search */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
The newline was escaped. We gotta keep going. */
|
||||
text = pz_next + 1;
|
||||
}
|
||||
|
||||
dont_fix_bogon:;
|
||||
} /* for (entire file) loop */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
test for fix selector
|
||||
|
@ -206,11 +385,12 @@ apply_fix( fixname, filname )
|
|||
if (strcmp (pfe->fix_name, fixname) == 0)
|
||||
break;
|
||||
if (--ct <= 0)
|
||||
{
|
||||
fprintf (stderr, "fixincludes error: the `%s' fix is unknown\n",
|
||||
fixname );
|
||||
exit (3);
|
||||
}
|
||||
{
|
||||
fprintf (stderr, "fixincludes error: the `%s' fix is unknown\n",
|
||||
fixname );
|
||||
exit (3);
|
||||
}
|
||||
pfe++;
|
||||
}
|
||||
|
||||
buf = load_file_data (stdin);
|
||||
|
|
|
@ -994,30 +994,19 @@ tSCC zEnd_Else_LabelName[] =
|
|||
#define apzEnd_Else_LabelMachs (const char**)NULL
|
||||
|
||||
/*
|
||||
* content selection pattern - do fix if pattern found
|
||||
* perform the C function call test
|
||||
*/
|
||||
tSCC zEnd_Else_LabelSelect0[] =
|
||||
"^[ \t]*#[ \t]*(else|endif)[ \t]+([!-.0-z\\{\\|\\}\\~]|/[^\\*])";
|
||||
tSCC zEnd_Else_LabelFTst0[] = "else_endif_label";
|
||||
|
||||
#define END_ELSE_LABEL_TEST_CT 1
|
||||
#define END_ELSE_LABEL_RE_CT 1
|
||||
#define END_ELSE_LABEL_RE_CT 0
|
||||
tTestDesc aEnd_Else_LabelTests[] = {
|
||||
{ TT_EGREP, zEnd_Else_LabelSelect0, (regex_t*)NULL }, };
|
||||
{ TT_FUNCTION, zEnd_Else_LabelFTst0, 0 /* unused */ }, };
|
||||
|
||||
/*
|
||||
* Fix Command Arguments for End_Else_Label
|
||||
*/
|
||||
const char* apzEnd_Else_LabelPatch[] = { "sed",
|
||||
"-e", ":loop\n\
|
||||
/\\\\$/N\n\
|
||||
s/\\\\$/\\\\+++fixinc_eol+++/\n\
|
||||
/\\\\$/b loop\n\
|
||||
s/\\\\+++fixinc_eol+++/\\\\/g\n\
|
||||
s%^\\([ \t]*#[ \t]*else\\)[ \t][ \t]*/[^*].*%\\1%\n\
|
||||
s%^\\([ \t]*#[ \t]*else\\)[ \t][ \t]*[^/ \t].*%\\1%\n\
|
||||
s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*/[^*].*%\\1%\n\
|
||||
s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*\\*[^/].*%\\1%\n\
|
||||
s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*[^/* \t].*%\\1%",
|
||||
const char* apzEnd_Else_LabelPatch[] = {"else_endif_label",
|
||||
(char*)NULL };
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
|
@ -4042,7 +4031,7 @@ extern char *\tsprintf();\\\n\
|
|||
*
|
||||
* List of all fixes
|
||||
*/
|
||||
#define REGEX_COUNT 75
|
||||
#define REGEX_COUNT 74
|
||||
#define MACH_LIST_SIZE_LIMIT 154
|
||||
#define FIX_COUNT 107
|
||||
|
||||
|
@ -4179,7 +4168,7 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
|
|||
|
||||
{ zEnd_Else_LabelName, zEnd_Else_LabelList,
|
||||
apzEnd_Else_LabelMachs, (regex_t*)NULL,
|
||||
END_ELSE_LABEL_TEST_CT, FD_MACH_ONLY,
|
||||
END_ELSE_LABEL_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
|
||||
aEnd_Else_LabelTests, apzEnd_Else_LabelPatch },
|
||||
|
||||
{ zHp_InlineName, zHp_InlineList,
|
||||
|
|
|
@ -62,7 +62,8 @@ typedef struct {
|
|||
} test_entry_t;
|
||||
|
||||
#define FIX_TEST_TABLE \
|
||||
_FT_( "double_slash", double_slash_test )
|
||||
_FT_( "double_slash", double_slash_test ) \
|
||||
_FT_( "else_endif_label", else_endif_label_test )
|
||||
|
||||
|
||||
#define TEST_FOR_FIX_PROC_HEAD( test ) \
|
||||
|
@ -154,6 +155,133 @@ TEST_FOR_FIX_PROC_HEAD( double_slash_test )
|
|||
return SKIP_FIX;
|
||||
}
|
||||
|
||||
|
||||
TEST_FOR_FIX_PROC_HEAD( else_endif_label_test )
|
||||
{
|
||||
static int compiled = 0;
|
||||
static const char label_pat[] = "^[ \t]*#[ \t]*(else|endif)";
|
||||
static regex_t label_re;
|
||||
|
||||
char ch;
|
||||
const char* pz_next = (char*)NULL;
|
||||
regmatch_t match[2];
|
||||
|
||||
/*
|
||||
This routine may be run many times within a single execution.
|
||||
Do the compile once only in that case. In the standalone case,
|
||||
we waste 10 bytes of memory and a test, branch and increment delay. */
|
||||
if (! compiled)
|
||||
{
|
||||
compiled++;
|
||||
re_set_syntax (RE_SYNTAX_EGREP);
|
||||
(void)re_compile_pattern (label_pat, sizeof (label_pat)-1,
|
||||
&label_re);
|
||||
}
|
||||
|
||||
for (;;) /* entire file */
|
||||
{
|
||||
/*
|
||||
See if we need to advance to the next candidate directive
|
||||
If the scanning pointer passes over the end of the directive,
|
||||
then the directive is inside a comment */
|
||||
if (pz_next < text)
|
||||
{
|
||||
if (regexec (&label_re, text, 2, match, 0) != 0)
|
||||
break;
|
||||
pz_next = text + match[0].rm_eo;
|
||||
}
|
||||
|
||||
/*
|
||||
IF the scan pointer has not reached the directive end, ... */
|
||||
if (pz_next > text)
|
||||
{
|
||||
/*
|
||||
Advance the scanning pointer. If we are at the start
|
||||
of a quoted string or a comment, then skip the entire unit */
|
||||
ch = *(text++);
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '/':
|
||||
/*
|
||||
Skip comments */
|
||||
if (*text == '*')
|
||||
{
|
||||
text = strstr( text+1, "*/" );
|
||||
if (text == (char*)NULL)
|
||||
return SKIP_FIX;
|
||||
text += 2;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case '"':
|
||||
case '\'':
|
||||
text = skip_quote( ch, text );
|
||||
break;
|
||||
} /* switch (ch) */
|
||||
continue;
|
||||
} /* if (still shy of directive end) */
|
||||
|
||||
/*
|
||||
The scanning pointer (text) has reached the end of the current
|
||||
directive under test, then check for bogons here */
|
||||
for (;;) /* bogon check */
|
||||
{
|
||||
char ch = *(pz_next++);
|
||||
if (isspace (ch))
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
/*
|
||||
It is clean. No bogons on this directive */
|
||||
text = pz_next;
|
||||
pz_next = (char*)NULL; /* force a new regex search */
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case '\\':
|
||||
/*
|
||||
Skip escaped newlines. Otherwise, we have a bogon */
|
||||
if (*pz_next != '\n')
|
||||
return APPLY_FIX;
|
||||
|
||||
pz_next++;
|
||||
break;
|
||||
|
||||
case '/':
|
||||
/*
|
||||
Skip comments. Otherwise, we have a bogon */
|
||||
if (*pz_next == '*')
|
||||
{
|
||||
pz_next = strstr( pz_next+1, "*/" );
|
||||
if (pz_next == (char*)NULL)
|
||||
return SKIP_FIX;
|
||||
pz_next += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: if this is a C++ file, then a double slash comment
|
||||
is allowed to follow the directive. */
|
||||
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
/*
|
||||
GOTTA BE A BOGON */
|
||||
return APPLY_FIX;
|
||||
} /* switch (ch) */
|
||||
} /* for (bogon check loop) */
|
||||
} /* for (entire file) loop */
|
||||
|
||||
return SKIP_FIX;
|
||||
}
|
||||
|
||||
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
|
||||
|
||||
test for fix selector
|
||||
|
@ -179,6 +307,7 @@ run_test( tname, fname, text )
|
|||
{
|
||||
if (strcmp( pte->test_name, tname ) == 0)
|
||||
return (*pte->test_proc)( fname, text );
|
||||
pte++;
|
||||
} while (--ct > 0);
|
||||
fprintf( stderr, "fixincludes error: the `%s' fix test is unknown\n",
|
||||
tname );
|
||||
|
|
|
@ -527,47 +527,10 @@ fix = {
|
|||
|
||||
/*
|
||||
* Select files that contain '#endif' or '#else' directives with
|
||||
* some sort of following junk. (Between the ascii '.'
|
||||
* and '0' lies the character '/'. This will *NOT*
|
||||
* match '#endif / * foo * /', but it also wont match
|
||||
* '#endif / done' either.
|
||||
*
|
||||
* We have a second regexp in the selector to detect
|
||||
* #endif followed by a / followed by anything other
|
||||
* than a *. For example "#endif / * foo * /" or
|
||||
* "#endif /% blah %/ which appear on OSF4.0A and AIX4.2
|
||||
* repsectively.
|
||||
*
|
||||
* We use the pattern [!-.0-z{|}~] instead of [^/ \t] to match a
|
||||
* noncomment following #else or #endif because some buggy egreps
|
||||
* think [^/] matches newline, and they thus think `#else ' matches
|
||||
* `#e[ndiflse]*[ \t]+[^/ \t]'.
|
||||
* [!-.0-~] does not work properly on AIX 4.1.
|
||||
* some sort of following junk.
|
||||
*/
|
||||
select = "^[ \t]*#[ \t]*(else|endif)[ \t]+"
|
||||
"(" '[!-.0-z\{\|\}\~]' "|" '/[^\*]' ")";
|
||||
|
||||
/*
|
||||
* First, join the continued input lines.
|
||||
* IF the resulting line is an endif preprocessing directive,
|
||||
* then trim off the following patterns:
|
||||
* 1. sequences that start with '/' and is *NOT* followed by '*'
|
||||
* 2. Sequences that start with '*' and is *NOT* followed by '/'
|
||||
* 3. sequences that do not start with any of '/', '*', '\t' or ' '.
|
||||
*
|
||||
* The fixinc_eol stuff is to work around a bug in the sed
|
||||
*/
|
||||
sed = ":loop\n"
|
||||
'/\\\\$/' "N\n"
|
||||
's/\\\\$/\\\\+++fixinc_eol+++/' "\n"
|
||||
'/\\\\$/' "b loop\n"
|
||||
's/\\\\+++fixinc_eol+++/\\\\/g' "\n"
|
||||
|
||||
"s%^\\([ \t]*#[ \t]*else\\)[ \t][ \t]*/[^*].*%\\1%\n"
|
||||
"s%^\\([ \t]*#[ \t]*else\\)[ \t][ \t]*[^/ \t].*%\\1%\n"
|
||||
"s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*/[^*].*%\\1%\n"
|
||||
"s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*\\*[^/].*%\\1%\n"
|
||||
"s%^\\([ \t]*#[ \t]*endif\\)[ \t][ \t]*[^/* \t].*%\\1%";
|
||||
c_test = "else_endif_label";
|
||||
c_fix = "else_endif_label";
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -979,28 +979,17 @@ extern "C"\
|
|||
#
|
||||
# Fix 27: End_Else_Label
|
||||
#
|
||||
if ( test -n "`egrep '^[ ]*#[ ]*(else|endif)[ ]+([!-.0-z\\{\\|\\}\\~]|/[^\\*])' ${file}`"
|
||||
) > /dev/null 2>&1 ; then
|
||||
if ${FIXTESTS} ${file} else_endif_label
|
||||
then
|
||||
fixlist="${fixlist}
|
||||
end_else_label"
|
||||
if [ ! -r ${DESTFILE} ]
|
||||
then infile=${file}
|
||||
else infile=${DESTFILE} ; fi
|
||||
|
||||
sed -e ':loop
|
||||
/\\$/N
|
||||
s/\\$/\\+++fixinc_eol+++/
|
||||
/\\$/b loop
|
||||
s/\\+++fixinc_eol+++/\\/g
|
||||
s%^\([ ]*#[ ]*else\)[ ][ ]*/[^*].*%\1%
|
||||
s%^\([ ]*#[ ]*else\)[ ][ ]*[^/ ].*%\1%
|
||||
s%^\([ ]*#[ ]*endif\)[ ][ ]*/[^*].*%\1%
|
||||
s%^\([ ]*#[ ]*endif\)[ ][ ]*\*[^/].*%\1%
|
||||
s%^\([ ]*#[ ]*endif\)[ ][ ]*[^/* ].*%\1%' \
|
||||
< $infile > ${DESTDIR}/fixinc.tmp
|
||||
${FIXFIXES} ${file} else_endif_label < $infile > ${DESTDIR}/fixinc.tmp
|
||||
rm -f ${DESTFILE}
|
||||
mv -f ${DESTDIR}/fixinc.tmp ${DESTFILE}
|
||||
fi # end of select 'if'
|
||||
fi # end of c_test 'if'
|
||||
|
||||
|
||||
#
|
||||
|
|
Loading…
Add table
Reference in a new issue