Commit 1e248c55 by Bruce Korb Committed by Bruce Korb

corrected and rewrote char_macro_* fixes to parse the text with regexes

From-SVN: r33931
parent 79589c4d
2000-05-16 Bruce Korb <bkorb@gnu.org>
* fixinc/README: corrected return address
* fixinc/check.diff: regenerate, now that test works
* fixinc/fixfixes.c(format_fix,format_write): reformatted
(char_macro_def_fix,char_macro_use_fix): corrected and
rewrote to use regex to parse the text
* fixinc/inclhack.def: more testing
* fixinc/fixincl.x: regenerated
2000-05-16 Alexandre Oliva <aoliva@cygnus.com> 2000-05-16 Alexandre Oliva <aoliva@cygnus.com>
* config/mn10300/mn10300.h (ASM_OUTPUT_DWARF2_ADDR_CONST): Remove. * config/mn10300/mn10300.h (ASM_OUTPUT_DWARF2_ADDR_CONST): Remove.
......
...@@ -33,7 +33,7 @@ broken by the manufacturer, or is broken by the fixinclude process, ...@@ -33,7 +33,7 @@ broken by the manufacturer, or is broken by the fixinclude process,
then you will need to alter or add information to the include fix then you will need to alter or add information to the include fix
definitions file, ``inclhack.def''. Please also send relevant definitions file, ``inclhack.def''. Please also send relevant
information to gcc-bugs@gcc.gnu.org, gcc-patches@gcc.gnu.org and, information to gcc-bugs@gcc.gnu.org, gcc-patches@gcc.gnu.org and,
please, to me: autogen@linuxbox.com. please, to me: bkorb@gnu.org.
Here are the rules for making fixes in the inclhack.def file: Here are the rules for making fixes in the inclhack.def file:
...@@ -109,6 +109,8 @@ Here are the rules for making fixes in the inclhack.def file: ...@@ -109,6 +109,8 @@ Here are the rules for making fixes in the inclhack.def file:
3. A C language subroutine method for both tests and fixes. 3. A C language subroutine method for both tests and fixes.
See ``fixtests.c'' for instructions on writing C-language See ``fixtests.c'' for instructions on writing C-language
applicability tests and ``fixfixes.c'' for C-language fixing. applicability tests and ``fixfixes.c'' for C-language fixing.
These files also contain tables that describe the currently
implemented fixes and tests.
4. Replacement text. If the replacement is empty, then no 4. Replacement text. If the replacement is empty, then no
fix is applied. Otherwise, the replacement text is fix is applied. Otherwise, the replacement text is
......
...@@ -704,16 +704,6 @@ ...@@ -704,16 +704,6 @@
*** 1,33 **** *** 1,33 ****
#ifndef IO_QUOTES_DEF_CHECK
! #define BSD43__IOWR(n, x) (('n'<<8)+x)
#endif /* IO_QUOTES_DEF_CHECK */
#ifndef IO_QUOTES_USE_CHECK
! #define TIOCFOO BSD43__IOWR(T, 1)
#endif /* IO_QUOTES_USE_CHECK */
#ifndef CTRL_QUOTES_DEF_CHECK #ifndef CTRL_QUOTES_DEF_CHECK
! #define BSD43_CTRL(n, x) (('n'<<8)+x) ! #define BSD43_CTRL(n, x) (('n'<<8)+x)
#endif /* CTRL_QUOTES_DEF_CHECK */ #endif /* CTRL_QUOTES_DEF_CHECK */
...@@ -724,6 +714,16 @@ ...@@ -724,6 +714,16 @@
#endif /* CTRL_QUOTES_USE_CHECK */ #endif /* CTRL_QUOTES_USE_CHECK */
#ifndef IO_QUOTES_DEF_CHECK
! #define BSD43__IOWR(n, x) (('n'<<8)+x)
#endif /* IO_QUOTES_DEF_CHECK */
#ifndef IO_QUOTES_USE_CHECK
! #define TIOCFOO BSD43__IOWR(T, 1)
#endif /* IO_QUOTES_USE_CHECK */
#ifndef MACHINE_NAME_CHECK #ifndef MACHINE_NAME_CHECK
! #ifdef i386 /* no uniform machine_name test, so ! #ifdef i386 /* no uniform machine_name test, so
this only works on i?86 machines */ this only works on i?86 machines */
...@@ -738,16 +738,6 @@ ...@@ -738,16 +738,6 @@
--- 1,37 ---- --- 1,37 ----
#ifndef IO_QUOTES_DEF_CHECK
! #define BSD43__IOWR(n, x) ((n<<8)+x)
#endif /* IO_QUOTES_DEF_CHECK */
#ifndef IO_QUOTES_USE_CHECK
! #define TIOCFOO BSD43__IOWR('T', 1)
#endif /* IO_QUOTES_USE_CHECK */
#ifndef CTRL_QUOTES_DEF_CHECK #ifndef CTRL_QUOTES_DEF_CHECK
! #define BSD43_CTRL(n, x) ((n<<8)+x) ! #define BSD43_CTRL(n, x) ((n<<8)+x)
#endif /* CTRL_QUOTES_DEF_CHECK */ #endif /* CTRL_QUOTES_DEF_CHECK */
...@@ -758,6 +748,16 @@ ...@@ -758,6 +748,16 @@
#endif /* CTRL_QUOTES_USE_CHECK */ #endif /* CTRL_QUOTES_USE_CHECK */
#ifndef IO_QUOTES_DEF_CHECK
! #define BSD43__IOWR(n, x) ((n<<8)+x)
#endif /* IO_QUOTES_DEF_CHECK */
#ifndef IO_QUOTES_USE_CHECK
! #define TIOCFOO BSD43__IOWR('T', 1)
#endif /* IO_QUOTES_USE_CHECK */
#ifndef MACHINE_NAME_CHECK #ifndef MACHINE_NAME_CHECK
! #ifdef __i386__ /* no uniform machine_name test, so ! #ifdef __i386__ /* no uniform machine_name test, so
this only works on i?86 machines */ this only works on i?86 machines */
......
...@@ -121,117 +121,137 @@ print_quote( q, text ) ...@@ -121,117 +121,137 @@ print_quote( q, text )
return text; return text;
} }
/*
* Copy the `format' string to std out, replacing `%n' expressions
* with the matched text from a regular expression evaluation.
* Doubled '%' characters will be replaced with a single copy.
* '%' characters in other contexts and all other characters are
* copied out verbatim.
*/
static void static void
format_write (format, text, av) format_write (format, text, av)
tCC* format; tCC* format;
tCC* text; tCC* text;
regmatch_t av[]; regmatch_t av[];
{ {
int c; int c;
while ((c = (unsigned)*(format++)) != NUL) { while ((c = (unsigned)*(format++)) != NUL) {
if (c != '%') { if (c != '%')
putchar(c); {
continue; putchar(c);
} continue;
}
c = (unsigned)*(format++); c = (unsigned)*(format++);
/* /*
* IF the character following a '%' is not a digit, * IF the character following a '%' is not a digit,
* THEN we will always emit a '%' and we may or may * THEN we will always emit a '%' and we may or may
* not emit the following character. We will end on * not emit the following character. We will end on
* a NUL and we will emit only one of a pair of '%'. * a NUL and we will emit only one of a pair of '%'.
*/ */
if (! isdigit( c )) { if (! isdigit( c ))
putchar( '%' ); {
switch (c) { putchar( '%' );
case NUL: switch (c) {
return; case NUL:
case '%': return;
break; case '%':
default: break;
putchar(c); default:
} putchar(c);
} }
}
/* /*
* Emit the matched subexpression numbered 'c'. * Emit the matched subexpression numbered 'c'.
* IF, of course, there was such a match... * IF, of course, there was such a match...
*/ */
else { else {
regmatch_t* pRM = av + (c - (unsigned)'0'); regmatch_t* pRM = av + (c - (unsigned)'0');
size_t len; size_t len;
if (pRM->rm_so < 0) if (pRM->rm_so < 0)
continue; continue;
len = pRM->rm_eo - pRM->rm_so; len = pRM->rm_eo - pRM->rm_so;
if (len > 0) if (len > 0)
fwrite(text + pRM->rm_so, len, 1, stdout); fwrite(text + pRM->rm_so, len, 1, stdout);
}
} }
}
} }
/*
* Search for multiple copies of a regular expression. Each block
* of matched text is replaced with the format string, as described
* above in `format_write'.
*/
FIX_PROC_HEAD( format_fix ) FIX_PROC_HEAD( format_fix )
{ {
tSCC zBad[] = "fixincl error: `%s' needs %s c_fix_arg\n"; tSCC zBad[] = "fixincl error: `%s' needs %s c_fix_arg\n";
tCC* pz_pat = p_fixd->patch_args[2]; tCC* pz_pat = p_fixd->patch_args[2];
tCC* pz_fmt = p_fixd->patch_args[1]; tCC* pz_fmt = p_fixd->patch_args[1];
const char *p; const char *p;
regex_t re; regex_t re;
regmatch_t rm[10]; regmatch_t rm[10];
/* /*
* We must have a format * We must have a format
*/ */
if (pz_fmt == (tCC*)NULL) { if (pz_fmt == (tCC*)NULL)
fprintf( stderr, zBad, p_fixd->fix_name, "replacement-format" ); {
exit( 3 ); fprintf( stderr, zBad, p_fixd->fix_name, "replacement-format" );
exit( 3 );
} }
/* /*
* IF we don't have a search text, then go find the first * IF we don't have a search text, then go find the first
* regular expression among the tests. * regular expression among the tests.
*/ */
if (pz_pat == (tCC*)NULL) { if (pz_pat == (tCC*)NULL)
tTestDesc* pTD = p_fixd->p_test_desc; {
int ct = p_fixd->test_ct; tTestDesc* pTD = p_fixd->p_test_desc;
for (;;) { int ct = p_fixd->test_ct;
if (ct-- <= 0) { for (;;)
fprintf( stderr, zBad, p_fixd->fix_name, "search-text" ); {
exit( 3 ); if (ct-- <= 0)
{
fprintf( stderr, zBad, p_fixd->fix_name, "search-text" );
exit( 3 );
} }
if (pTD->type == TT_EGREP) { if (pTD->type == TT_EGREP)
pz_pat = pTD->pz_test_text; {
break; pz_pat = pTD->pz_test_text;
break;
} }
pTD++; pTD++;
} }
} }
/* /*
* Replace every copy of the text we find * Replace every copy of the text we find
*/ */
compile_re (pz_pat, &re, 1, "format search-text", "format_fix" ); compile_re (pz_pat, &re, 1, "format search-text", "format_fix" );
while (regexec (&re, text, 10, rm, 0) == 0) while (regexec (&re, text, 10, rm, 0) == 0)
{ {
char* apz[10]; char* apz[10];
int i; int i;
fwrite( text, rm[0].rm_so, 1, stdout ); fwrite( text, rm[0].rm_so, 1, stdout );
format_write( pz_fmt, text, rm ); format_write( pz_fmt, text, rm );
text += rm[0].rm_eo; text += rm[0].rm_eo;
} }
/* /*
* Dump out the rest of the file * Dump out the rest of the file
*/ */
fputs (text, stdout); fputs (text, stdout);
} }
...@@ -245,175 +265,184 @@ FIX_PROC_HEAD( format_fix ) ...@@ -245,175 +265,184 @@ FIX_PROC_HEAD( format_fix )
which is the required syntax per the C standard. (The definition of which is the required syntax per the C standard. (The definition of
_IO also has to be tweaked - see below.) 'IO' is actually whatever you _IO also has to be tweaked - see below.) 'IO' is actually whatever you
provide in the STR argument. */ provide as the `c_fix_arg' argument. */
FIX_PROC_HEAD( char_macro_use_fix ) FIX_PROC_HEAD( char_macro_use_fix )
{ {
/* This regexp looks for a traditional-syntax #define (# in column 1) /* This regexp looks for a traditional-syntax #define (# in column 1)
of an object-like macro. */ of an object-like macro. */
static const char pat[] = static const char zPatFmt[] =
"^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+"; #ifdef __STDC__
/*
* Match up to the replacement text
*/
"^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+"
/*
* Match the replacement macro name and openening parenthesis
*/
"[_A-Z][_A-Z0-9]*%s[A-Z]*\\("
/*
* Match the single character that must be single-quoted,
* plus some other non-name type character
*/
"([A-Za-z])[^a-zA-Z0-9_]"
#else
/*
* Indecipherable gobbeldygook:
*/
"^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+[_A-Z][_A-Z0-9]*\
%s[A-Z]*\\(([A-Za-z])[^a-zA-Z0-9_]"
#endif
;
char zPat[ sizeof( zPatFmt ) + 32 ];
static regex_t re; static regex_t re;
regmatch_t rm[1]; regmatch_t rm[2];
const char *p, *limit;
const char *str = p_fixd->patch_args[0];
size_t len;
if (str == NULL) if (p_fixd->patch_args[1] == NULL)
{ {
fprintf (stderr, "%s needs macro-name-string argument", fprintf (stderr, "%s needs macro-name-string argument",
p_fixd->fix_name); p_fixd->fix_name);
exit(3); exit(3);
} }
len = strlen (str); if (sprintf( zPat, zPatFmt, p_fixd->patch_args[1] ) >= sizeof( zPat ))
compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_uses");
for (p = text;
regexec (&re, p, 1, rm, 0) == 0;
p = limit + 1)
{ {
/* p + rm[0].rm_eo is the first character of the macro replacement. fprintf( stderr, "Oversize format: %s\n", zPat );
Find the end of the macro replacement, and the STR we were exit(3);
sent to look for within the replacement. */ }
p += rm[0].rm_eo;
limit = p - 1;
do
{
limit = strchr (limit + 1, '\n');
if (!limit)
goto done;
}
while (limit[-1] == '\\');
do compile_re (zPat, &re, 2, "macro pattern", "char_macro_use_fix");
{
if (*p == str[0] && !strncmp (p+1, str+1, len-1)) while (regexec (&re, text, 3, rm, 0) == 0)
goto found; {
} const char* pz = text + rm[1].rm_so;
while (++p < limit - len);
/* Hit end of line. */ /*
continue; * Write up to, but not including, the character we must quote
*/
found: fwrite( text, 1, rm[1].rm_so, stdout );
/* Found STR on this line. If the macro needs fixing, fputc( '\'', stdout );
the next few chars will be whitespace or uppercase, fputc( *(pz++), stdout );
then an open paren, then a single letter. */ fputc( '\'', stdout );
while ((isspace (*p) || isupper (*p)) && p < limit) p++; text = pz;
if (*p++ != '(')
continue;
if (!isalpha (*p))
continue;
if (isalnum (p[1]) || p[1] == '_')
continue;
/* Splat all preceding text into the output buffer,
quote the character at p, then proceed. */
fwrite (text, 1, p - text, stdout);
putchar ('\'');
putchar (*p);
putchar ('\'');
text = p + 1;
} }
done:
fputs (text, stdout); fputs (text, stdout);
} }
/* Scan the input file for all occurrences of text like this: /* Scan the input file for all occurrences of text like this:
#define _IO(x, y) ('x'<<16+y) #define xxxIOxx(x, y) ('x'<<16+y)
and change them to read like this: and change them to read like this:
#define _IO(x, y) (x<<16+y) #define xxxIOxx(x, y) (x<<16+y)
which is the required syntax per the C standard. (The uses of _IO which is the required syntax per the C standard. (The uses of _IO
also have to be tweaked - see above.) 'IO' is actually whatever also has to be tweaked - see above.) 'IO' is actually whatever
you provide in the STR argument. */ you provide as the `c_fix_arg' argument. */
FIX_PROC_HEAD( char_macro_def_fix ) FIX_PROC_HEAD( char_macro_def_fix )
{ {
/* This regexp looks for any traditional-syntax #define (# in col 1). */ static const char zPatFmt[] =
static const char pat[] = #ifdef __STDC__
"^#[ \t]*define[ \t]+"; /*
* Find a #define name and opening parenthesis
*/
"^#[ \t]*define[ \t]+[_A-Z][A-Z0-9_]*%s[A-Z]*\\("
/*
* The next character must be alphabetic without a name-type
* character following it
*/
"([a-zA-Z])[^a-zA-Z0-9_]" /* rm[1] */
/*
* now match over the argument list, intervening white space
* and opening parentheses, and on through a single quote character
*/
"[^)]*\\)[ \t]+\\([ \t(]*'"
/*
* Match the character that must match the remembered char above
*/
"([a-zA-Z])'" /* rm[2] */
#else
/*
* Indecipherable gobbeldygook:
*/
"^#[ \t]*define[ \t]+[_A-Z][A-Z0-9_]*%s[A-Z]*\\(([a-zA-Z])[^a-zA-Z0-9_]\
[^)]*\\)[ \t]+\\([ \t(]*'([a-zA-Z])'"
#endif
;
char zPat[ sizeof( zPatFmt ) + 32 ];
static regex_t re; static regex_t re;
regmatch_t rm[1]; regmatch_t rm[3];
const char *p, *limit; const char *p;
const char *str = p_fixd->patch_args[0]; int rerr;
size_t len;
char arg;
if (str == NULL) if (p_fixd->patch_args[1] == NULL)
{ {
fprintf (stderr, "%s needs macro-name-string argument", fprintf (stderr, "%s needs macro-name-string argument",
p_fixd->fix_name); p_fixd->fix_name);
exit(3); exit(3);
} }
compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines"); if (sprintf( zPat, zPatFmt, p_fixd->patch_args[1] ) >= sizeof( zPat ))
{
fprintf( stderr, "Oversize format: %s\n", zPat );
exit(3);
}
compile_re (zPat, &re, 1, "macro pattern", "char_macro_def_fix");
for (p = text; if ((rerr = regexec (&re, text, 3, rm, 0)) != 0)
regexec (&re, p, 1, rm, 0) == 0;
p = limit + 1)
{ {
/* p + rm[0].rm_eo is the first character of the macro name. fprintf( stderr, "Match error %d:\n%s\n", rerr, zPat );
Find the end of the macro replacement, and the STR we were exit(3);
sent to look for within the name. */ }
p += rm[0].rm_eo;
limit = p - 1;
do
{
limit = strchr (limit + 1, '\n');
if (!limit)
goto done;
}
while (limit[-1] == '\\');
do while ((rerr = regexec (&re, text, 3, rm, 0)) == 0)
{ {
if (*p == str[0] && !strncmp (p+1, str+1, len-1)) const char* pz = text + rm[2].rm_so;
goto found;
p++; /*
} * Write up to, but not including, the opening single quote.
while (isalpha (*p) || isalnum (*p) || *p == '_'); */
/* Hit end of macro name without finding the string. */ fwrite( text, 1, rm[2].rm_so-1, stdout );
continue;
/*
found: * The character inside the single quotes must match the
/* Found STR in this macro name. If the macro needs fixing, * first single-character macro argument
there may be a few uppercase letters, then there will be an */
open paren with _no_ intervening whitespace, and then a if (text[ rm[1].rm_so ] != *pz)
single letter. */ {
while (isupper (*p) && p < limit) p++; /*
if (*p++ != '(') * Advance text past what we have written out and continue
continue; */
if (!isalpha (*p)) text = pz-1;
continue; continue;
if (isalnum (p[1]) || p[1] == '_') }
continue;
/*
/* The character at P is the one to look for in the following * emit the now unquoted character
text. */ */
arg = *p; putchar( *pz );
p += 2;
/*
while (p < limit) * Point text to the character after the closing single quote
{ */
if (p[-1] == '\'' && p[0] == arg && p[1] == '\'') text = pz+2;
{
/* Remove the quotes from this use of ARG. */
p--;
fwrite (text, 1, p - text, stdout);
putchar (arg);
p += 3;
text = p;
}
else
p++;
}
} }
done:
/*
* Emit the rest of the text
*/
fputs (text, stdout); fputs (text, stdout);
} }
...@@ -447,71 +476,71 @@ FIX_PROC_HEAD( machine_name_fix ) ...@@ -447,71 +476,71 @@ FIX_PROC_HEAD( machine_name_fix )
{ {
base += match[0].rm_eo; base += match[0].rm_eo;
/* We're looking at an #if or #ifdef. Scan forward for the /* We're looking at an #if or #ifdef. Scan forward for the
next non-escaped newline. */ next non-escaped newline. */
line = limit = base; line = limit = base;
do do
{ {
limit++; limit++;
limit = strchr (limit, '\n'); limit = strchr (limit, '\n');
if (!limit) if (!limit)
goto done; goto done;
} }
while (limit[-1] == '\\'); while (limit[-1] == '\\');
/* If the 'name_pat' matches in between base and limit, we have /* If the 'name_pat' matches in between base and limit, we have
a bogon. It is not worth the hassle of excluding comments a bogon. It is not worth the hassle of excluding comments
because comments on #if/#ifdef lines are rare, and strings on because comments on #if/#ifdef lines are rare, and strings on
such lines are illegal. such lines are illegal.
REG_NOTBOL means 'base' is not at the beginning of a line, which REG_NOTBOL means 'base' is not at the beginning of a line, which
shouldn't matter since the name_re has no ^ anchor, but let's shouldn't matter since the name_re has no ^ anchor, but let's
be accurate anyway. */ be accurate anyway. */
for (;;) for (;;)
{ {
again: again:
if (base == limit) if (base == limit)
break; break;
if (regexec (name_re, base, 1, match, REG_NOTBOL)) if (regexec (name_re, base, 1, match, REG_NOTBOL))
goto done; /* No remaining match in this file */ goto done; /* No remaining match in this file */
/* Match; is it on the line? */ /* Match; is it on the line? */
if (match[0].rm_eo > limit - base) if (match[0].rm_eo > limit - base)
break; break;
p = base + match[0].rm_so; p = base + match[0].rm_so;
base += match[0].rm_eo; base += match[0].rm_eo;
/* One more test: if on the same line we have the same string /* One more test: if on the same line we have the same string
with the appropriate underscores, then leave it alone. with the appropriate underscores, then leave it alone.
We want exactly two leading and trailing underscores. */ We want exactly two leading and trailing underscores. */
if (*p == '_') if (*p == '_')
{ {
len = base - p - ((*base == '_') ? 2 : 1); len = base - p - ((*base == '_') ? 2 : 1);
q = p + 1; q = p + 1;
} }
else else
{ {
len = base - p - ((*base == '_') ? 1 : 0); len = base - p - ((*base == '_') ? 1 : 0);
q = p; q = p;
} }
if (len + 4 > SCRATCHSZ) if (len + 4 > SCRATCHSZ)
abort (); abort ();
memcpy (&scratch[2], q, len); memcpy (&scratch[2], q, len);
len += 2; len += 2;
scratch[len++] = '_'; scratch[len++] = '_';
scratch[len++] = '_'; scratch[len++] = '_';
for (q = line; q <= limit - len; q++) for (q = line; q <= limit - len; q++)
if (*q == '_' && !strncmp (q, scratch, len)) if (*q == '_' && !strncmp (q, scratch, len))
goto again; goto again;
fwrite (text, 1, p - text, stdout); fwrite (text, 1, p - text, stdout);
fwrite (scratch, 1, len, stdout); fwrite (scratch, 1, len, stdout);
text = base; text = base;
} }
} }
done: done:
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment