Use C-coded tests and fixes for #endif/#else labels

From-SVN: r30130
This commit is contained in:
Bruce Korb 1999-10-22 13:23:43 +00:00 committed by Bruce Korb
parent 5685b5d3c2
commit 8f9ca91274
7 changed files with 344 additions and 81 deletions

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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,

View File

@ -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 );

View File

@ -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";
};

View File

@ -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'
#