4 Test to see if a particular fix should be applied to a header file.
6 Copyright (C) 1997-1999, 2000 Free Software Foundation, Inc.
8 = = = = = = = = = = = = = = = = = = = = = = = = =
12 The routines you write here must work closely with both the fixincl.c
13 and the test_need.c program.
17 1. Every test procedure name must be suffixed with "_fix".
18 These routines will be referenced from inclhack.def, sans the suffix.
20 2. Use the "FIX_PROC_HEAD()" macro _with_ the "_fix" suffix
21 (I cannot use the ## magic from ANSI C) for defining your entry point.
23 3. Put your test name into the FIXUP_TABLE
25 4. Do not read anything from stdin. It is closed.
27 5. Write to stderr only in the event of a reportable error
28 In such an event, call "exit(1)".
30 6. If "MAIN" is _not_ defined, then you have access to the fixDescList
31 entry for the fix in question. This may be useful, for example,
32 if there are pre-compiled selection expressions stored there.
34 For example, you may do this if you know that the first
35 test contains a useful regex. This is okay because, remember,
36 this code perforce works closely with the inclhack.def fixes!!
39 tFixDesc* pMyDesc = fixDescList + MY_FIX_NAME_FIXIDX;
40 tTestDesc* pTestList = pMyDesc->p_test_desc;
42 regexec (pTestList->p_test_regex, ...)
45 If MAIN _is_ defined, then you will have to compile it on
48 = = = = = = = = = = = = = = = = = = = = = = = = =
50 This file is part of GNU CC.
52 GNU CC is free software; you can redistribute it and/or modify
53 it under the terms of the GNU General Public License as published by
54 the Free Software Foundation; either version 2, or (at your option)
57 GNU CC is distributed in the hope that it will be useful,
58 but WITHOUT ANY WARRANTY; without even the implied warranty of
59 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60 GNU General Public License for more details.
62 You should have received a copy of the GNU General Public License
63 along with GNU CC; see the file COPYING. If not, write to
64 the Free Software Foundation, 59 Temple Place - Suite 330,
65 Boston, MA 02111-1307, USA. */
75 _FT_( "no_double_slash", double_slash_fix ) \
76 _FT_( "else_endif_label", else_endif_label_fix ) \
77 _FT_( "IO_use", IO_use_fix ) \
78 _FT_( "CTRL_use", CTRL_use_fix) \
79 _FT_( "IO_defn", IO_defn_fix ) \
80 _FT_( "CTRL_defn", CTRL_defn_fix ) \
81 _FT_( "machine_name", machine_name_fix )
84 #define FIX_PROC_HEAD( fix ) \
85 static void fix ( filname, text ) \
86 const char* filname; \
91 * Skip over a quoted string. Single quote strings may
92 * contain multiple characters if the first character is
93 * a backslash. Especially a backslash followed by octal digits.
94 * We are not doing a correctness syntax check here.
97 print_quote( q, text )
114 fputc( *(text++), stdout );
133 FIX_PROC_HEAD( double_slash_fix )
135 /* Now look for the comment markers in the text */
142 switch (*text) /* do not advance `text' here */
146 We found a "//" pair in open text.
147 Delete text to New-Line
149 while ((*text != '\n') && (*text != '\0')) text++;
154 /* We found a C-style comment. Skip forward to the end */
155 char* pz = strstr( (--text)+2, "*/" );
156 if (pz == (char*)NULL)
158 fputs( text, stdout );
162 fwrite (text, (pz - text), 1, stdout );
177 text = print_quote (ch, text );
190 FIX_PROC_HEAD( else_endif_label_fix )
192 static const char label_pat[] = "^[ \t]*#[ \t]*(else|endif)";
193 static regex_t label_re;
196 char* pz_next = (char*)NULL;
199 compile_re (label_pat, &label_re, 1,
200 "label pattern", "else_endif_label_fix");
202 for (;;) /* entire file */
205 See if we need to advance to the next candidate directive
206 If the scanning pointer passes over the end of the directive,
207 then the directive is inside a comment */
210 if (regexec (&label_re, text, 2, match, 0) != 0)
212 fputs( text, stdout );
216 pz_next = text + match[0].rm_eo;
220 IF the scan pointer has not reached the directive end, ... */
224 Advance the scanning pointer. If we are at the start
225 of a quoted string or a comment, then skip the entire unit */
235 char* pz = strstr( text+2, "*/" );
236 if (pz == (char*)NULL)
238 fputs( text, stdout );
242 fwrite( text, 1, (pz - text), stdout );
252 text = print_quote( ch, text+1 );
260 } /* if (still shy of directive end) */
263 The scanning pointer (text) has reached the end of the current
264 directive under test. Check for bogons here. */
265 for (;;) /* bogon check */
274 It is clean. No bogons on this directive */
275 pz_next = (char*)NULL; /* force a new regex search */
288 Skip escaped newlines. Otherwise, we have a bogon */
295 Emit the escaped newline and keep scanning for possible junk */
296 putc( '\\', stdout );
297 putc( '\n', stdout );
303 Skip comments. Otherwise, we have a bogon */
307 pz_next = strstr( text+2, "*/" );
308 if (pz_next == (char*)NULL)
310 putc( '\n', stdout );
314 fwrite( text, 1, (pz_next - text), stdout );
327 } /* for (bogon check loop) */
331 `text' points to the start of the bogus data */
335 NOT an escaped newline. Find the end of line that
336 is not preceeded by an escape character: */
337 pz_next = strchr( text, '\n' );
338 if (pz_next == (char*)NULL)
340 putc( '\n', stdout );
344 if (pz_next[-1] != '\\')
347 pz_next = (char*)NULL; /* force a new regex search */
352 The newline was escaped. We gotta keep going. */
357 } /* for (entire file) loop */
362 /* Scan the input file for all occurrences of text like this:
364 #define TIOCCONS _IO(T, 12)
366 and change them to read like this:
368 #define TIOCCONS _IO('T', 12)
370 which is the required syntax per the C standard. (The definition of
371 _IO also has to be tweaked - see below.) 'IO' is actually whatever you
372 provide in the STR argument. */
374 fix_char_macro_uses (text, str)
378 /* This regexp looks for a traditional-syntax #define (# in column 1)
379 of an object-like macro. */
380 static const char pat[] =
381 "^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+";
385 const char *p, *limit;
386 size_t len = strlen (str);
388 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_uses");
391 regexec (&re, p, 1, rm, 0) == 0;
394 /* p + rm[0].rm_eo is the first character of the macro replacement.
395 Find the end of the macro replacement, and the STR we were
396 sent to look for within the replacement. */
401 limit = strchr (limit + 1, '\n');
405 while (limit[-1] == '\\');
409 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
412 while (++p < limit - len);
413 /* Hit end of line. */
417 /* Found STR on this line. If the macro needs fixing,
418 the next few chars will be whitespace or uppercase,
419 then an open paren, then a single letter. */
420 while ((isspace (*p) || isupper (*p)) && p < limit) p++;
425 if (isalnum (p[1]) || p[1] == '_')
428 /* Splat all preceding text into the output buffer,
429 quote the character at p, then proceed. */
430 fwrite (text, 1, p - text, stdout);
437 fputs (text, stdout);
440 /* Scan the input file for all occurrences of text like this:
442 #define _IO(x, y) ('x'<<16+y)
444 and change them to read like this:
446 #define _IO(x, y) (x<<16+y)
448 which is the required syntax per the C standard. (The uses of _IO
449 also have to be tweaked - see above.) 'IO' is actually whatever
450 you provide in the STR argument. */
452 fix_char_macro_defines (text, str)
456 /* This regexp looks for any traditional-syntax #define (# in column 1). */
457 static const char pat[] =
458 "^#[ \t]*define[ \t]+";
462 const char *p, *limit;
463 size_t len = strlen (str);
466 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines");
469 regexec (&re, p, 1, rm, 0) == 0;
472 /* p + rm[0].rm_eo is the first character of the macro name.
473 Find the end of the macro replacement, and the STR we were
474 sent to look for within the name. */
479 limit = strchr (limit + 1, '\n');
483 while (limit[-1] == '\\');
487 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
491 while (isalpha (*p) || isalnum (*p) || *p == '_');
492 /* Hit end of macro name without finding the string. */
496 /* Found STR in this macro name. If the macro needs fixing,
497 there may be a few uppercase letters, then there will be an
498 open paren with _no_ intervening whitespace, and then a
500 while (isupper (*p) && p < limit) p++;
505 if (isalnum (p[1]) || p[1] == '_')
508 /* The character at P is the one to look for in the following
515 if (p[-1] == '\'' && p[0] == arg && p[1] == '\'')
517 /* Remove the quotes from this use of ARG. */
519 fwrite (text, 1, p - text, stdout);
529 fputs (text, stdout);
532 /* The various prefixes on these macros are handled automatically
533 because the fixers don't care where they start matching. */
534 FIX_PROC_HEAD( IO_use_fix )
536 fix_char_macro_uses (text, "IO");
538 FIX_PROC_HEAD( CTRL_use_fix )
540 fix_char_macro_uses (text, "CTRL");
543 FIX_PROC_HEAD( IO_defn_fix )
545 fix_char_macro_defines (text, "IO");
547 FIX_PROC_HEAD( CTRL_defn_fix )
549 fix_char_macro_defines (text, "CTRL");
553 /* Fix for machine name #ifdefs that are not in the namespace reserved
554 by the C standard. They won't be defined if compiling with -ansi,
555 and the headers will break. We go to some trouble to only change
556 #ifdefs where the macro is defined by GCC in non-ansi mode; this
557 minimizes the number of headers touched. */
559 #define SCRATCHSZ 64 /* hopefully long enough */
561 FIX_PROC_HEAD( machine_name_fix )
564 fputs( "The target machine has no needed machine name fixes\n", stderr );
567 char *line, *base, *limit, *p, *q;
568 regex_t *label_re, *name_re;
569 char scratch[SCRATCHSZ];
572 mn_get_regexps (&label_re, &name_re, "machine_name_fix");
578 regexec (label_re, base, 2, match, 0) == 0;
581 base += match[0].rm_eo;
582 /* We're looking at an #if or #ifdef. Scan forward for the
583 next non-escaped newline. */
588 limit = strchr (limit, '\n');
592 while (limit[-1] == '\\');
594 /* If the 'name_pat' matches in between base and limit, we have
595 a bogon. It is not worth the hassle of excluding comments
596 because comments on #if/#ifdef lines are rare, and strings on
597 such lines are illegal.
599 REG_NOTBOL means 'base' is not at the beginning of a line, which
600 shouldn't matter since the name_re has no ^ anchor, but let's
601 be accurate anyway. */
609 if (regexec (name_re, base, 1, match, REG_NOTBOL))
610 goto done; /* No remaining match in this file */
612 /* Match; is it on the line? */
613 if (match[0].rm_eo > limit - base)
616 p = base + match[0].rm_so;
617 base += match[0].rm_eo;
619 /* One more test: if on the same line we have the same string
620 with the appropriate underscores, then leave it alone.
621 We want exactly two leading and trailing underscores. */
624 len = base - p - ((*base == '_') ? 2 : 1);
629 len = base - p - ((*base == '_') ? 1 : 0);
632 if (len + 4 > SCRATCHSZ)
634 memcpy (&scratch[2], q, len);
636 scratch[len++] = '_';
637 scratch[len++] = '_';
639 for (q = line; q <= limit - len; q++)
640 if (*q == '_' && !strncmp (q, scratch, len))
643 fwrite (text, 1, p - text, stdout);
644 fwrite (scratch, 1, len, stdout);
651 fputs (text, stdout);
655 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
657 test for fix selector
659 THIS IS THE ONLY EXPORTED ROUTINE
663 apply_fix( fixname, filname )
667 #define _FT_(n,p) { n, p },
668 static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
670 #define FIX_TABLE_CT ((sizeof(fix_table)/sizeof(fix_table[0]))-1)
673 int ct = FIX_TABLE_CT;
674 fix_entry_t* pfe = fix_table;
678 if (strcmp (pfe->fix_name, fixname) == 0)
682 fprintf (stderr, "fixincludes error: the `%s' fix is unknown\n",
689 buf = load_file_data (stdin);
690 (*pfe->fix_proc)( filname, buf );
695 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
699 This file is both included in fixincl.c and compiled as a separate
700 program for use by the inclhack.sh script.
710 apply_fix ("No test name provided", NULL, NULL, 0 );
712 apply_fix (argv[2], argv[1]);