]> gcc.gnu.org Git - gcc.git/blame - gcc/fixinc/fixfixes.c
mklibgcc.in (building libgcc1): Do not use unset variables $src and $dst.
[gcc.git] / gcc / fixinc / fixfixes.c
CommitLineData
5abc1f74
BK
1
2/*
3
4 Test to see if a particular fix should be applied to a header file.
5
3852e8af 6 Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
5abc1f74
BK
7
8= = = = = = = = = = = = = = = = = = = = = = = = =
9
10NOTE TO DEVELOPERS
11
b7976767 12The routines you write here must work closely with fixincl.c.
5abc1f74
BK
13
14Here are the rules:
15
161. Every test procedure name must be suffixed with "_fix".
17 These routines will be referenced from inclhack.def, sans the suffix.
18
192. Use the "FIX_PROC_HEAD()" macro _with_ the "_fix" suffix
20 (I cannot use the ## magic from ANSI C) for defining your entry point.
21
223. Put your test name into the FIXUP_TABLE
23
244. Do not read anything from stdin. It is closed.
25
265. Write to stderr only in the event of a reportable error
27 In such an event, call "exit(1)".
28
b7976767
ZW
296. You have access to the fixDescList entry for the fix in question.
30 This may be useful, for example, if there are pre-compiled
31 selection expressions stored there.
5abc1f74
BK
32
33 For example, you may do this if you know that the first
34 test contains a useful regex. This is okay because, remember,
35 this code perforce works closely with the inclhack.def fixes!!
36
5abc1f74
BK
37 tFixDesc* pMyDesc = fixDescList + MY_FIX_NAME_FIXIDX;
38 tTestDesc* pTestList = pMyDesc->p_test_desc;
39
40 regexec (pTestList->p_test_regex, ...)
41
5abc1f74
BK
42= = = = = = = = = = = = = = = = = = = = = = = = =
43
44This file is part of GNU CC.
45
46GNU CC is free software; you can redistribute it and/or modify
47it under the terms of the GNU General Public License as published by
48the Free Software Foundation; either version 2, or (at your option)
49any later version.
50
51GNU CC is distributed in the hope that it will be useful,
52but WITHOUT ANY WARRANTY; without even the implied warranty of
53MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54GNU General Public License for more details.
55
56You should have received a copy of the GNU General Public License
57along with GNU CC; see the file COPYING. If not, write to
58the Free Software Foundation, 59 Temple Place - Suite 330,
59Boston, MA 02111-1307, USA. */
60
61#include "fixlib.h"
62
63typedef struct {
64 const char* fix_name;
65 void (*fix_proc)();
66} fix_entry_t;
67
68#define FIXUP_TABLE \
35dfe415 69 _FT_( "format", format_fix ) \
27a498c9
BK
70 _FT_( "char_macro_use", char_macro_use_fix ) \
71 _FT_( "char_macro_def", char_macro_def_fix ) \
88acf854 72 _FT_( "machine_name", machine_name_fix )
5abc1f74
BK
73
74
75#define FIX_PROC_HEAD( fix ) \
35dfe415 76static void fix ( filname, text, p_fixd ) \
5abc1f74 77 const char* filname; \
cfc9d1ee 78 const char* text; \
35dfe415 79 tFixDesc* p_fixd;
5abc1f74
BK
80
81
82/*
83 * Skip over a quoted string. Single quote strings may
84 * contain multiple characters if the first character is
85 * a backslash. Especially a backslash followed by octal digits.
86 * We are not doing a correctness syntax check here.
87 */
88static char*
89print_quote( q, text )
90 char q;
91 char* text;
92{
93 fputc( q, stdout );
94
95 for (;;)
96 {
97 char ch = *(text++);
98 fputc( ch, stdout );
99
100 switch (ch)
101 {
102 case '\\':
103 if (*text == NUL)
104 goto quote_done;
105
106 fputc( *(text++), stdout );
107 break;
108
109 case '"':
110 case '\'':
111 if (ch != q)
112 break;
113 /*FALLTHROUGH*/
114
115 case '\n':
116 case NUL:
117 goto quote_done;
118 }
119 } quote_done:;
120
121 return text;
122}
123
4c6d912f
ZW
124static void
125format_write (format, text, av)
126 tCC* format;
127 tCC* text;
128 regmatch_t av[];
129{
4c6d912f 130 int c;
a92fa608
BK
131
132 while ((c = (unsigned)*(format++)) != NUL) {
133
134 if (c != '%') {
135 putchar(c);
136 continue;
137 }
138
139 c = (unsigned)*(format++);
140
141 /*
142 * IF the character following a '%' is not a digit,
143 * THEN we will always emit a '%' and we may or may
144 * not emit the following character. We will end on
145 * a NUL and we will emit only one of a pair of '%'.
146 */
147 if (! isdigit( c )) {
148 putchar( '%' );
149 switch (c) {
150 case NUL:
151 return;
152 case '%':
153 break;
154 default:
155 putchar(c);
156 }
157 }
158
159 /*
160 * Emit the matched subexpression numbered 'c'.
161 * IF, of course, there was such a match...
162 */
163 else {
164 regmatch_t* pRM = av + (c - (unsigned)'0');
165 size_t len;
166
167 if (pRM->rm_so < 0)
168 continue;
169
170 len = pRM->rm_eo - pRM->rm_so;
171 if (len > 0)
172 fwrite(text + pRM->rm_so, len, 1, stdout);
173 }
4c6d912f
ZW
174 }
175}
5abc1f74 176
a92fa608 177
35dfe415 178FIX_PROC_HEAD( format_fix )
5abc1f74 179{
35dfe415
BK
180 tSCC zBad[] = "fixincl error: `%s' needs %s c_fix_arg\n";
181 tCC* pz_pat = p_fixd->patch_args[2];
182 tCC* pz_fmt = p_fixd->patch_args[1];
183 const char *p;
184 regex_t re;
185 regmatch_t rm[10];
186
187 /*
188 * We must have a format
189 */
190 if (pz_fmt == (tCC*)NULL) {
191 fprintf( stderr, zBad, p_fixd->fix_name, "replacement-format" );
192 exit( 3 );
193 }
8f9ca912 194
35dfe415
BK
195 /*
196 * IF we don't have a search text, then go find the first
197 * regular expression among the tests.
198 */
199 if (pz_pat == (tCC*)NULL) {
200 tTestDesc* pTD = p_fixd->p_test_desc;
201 int ct = p_fixd->test_ct;
202 for (;;) {
203 if (ct-- <= 0) {
204 fprintf( stderr, zBad, p_fixd->fix_name, "search-text" );
205 exit( 3 );
206 }
8f9ca912 207
35dfe415
BK
208 if (pTD->type == TT_EGREP) {
209 pz_pat = pTD->pz_test_text;
210 break;
8f9ca912
BK
211 }
212
35dfe415 213 pTD++;
8f9ca912 214 }
35dfe415 215 }
8f9ca912 216
35dfe415
BK
217 /*
218 * Replace every copy of the text we find
219 */
220 compile_re (pz_pat, &re, 1, "format search-text", "format_fix" );
221 while (regexec (&re, text, 10, rm, 0) == 0)
222 {
223 char* apz[10];
224 int i;
225
35dfe415 226 fwrite( text, rm[0].rm_so, 1, stdout );
4c6d912f 227 format_write( pz_fmt, text, rm );
35dfe415
BK
228 text += rm[0].rm_eo;
229 }
8f9ca912 230
35dfe415
BK
231 /*
232 * Dump out the rest of the file
233 */
234 fputs (text, stdout);
8f9ca912
BK
235}
236
5c0d5b94
ZW
237/* Scan the input file for all occurrences of text like this:
238
239 #define TIOCCONS _IO(T, 12)
240
241 and change them to read like this:
242
243 #define TIOCCONS _IO('T', 12)
244
245 which is the required syntax per the C standard. (The definition of
246 _IO also has to be tweaked - see below.) 'IO' is actually whatever you
247 provide in the STR argument. */
4c6d912f
ZW
248
249FIX_PROC_HEAD( char_macro_use_fix )
5c0d5b94
ZW
250{
251 /* This regexp looks for a traditional-syntax #define (# in column 1)
252 of an object-like macro. */
253 static const char pat[] =
3a2e9dd2 254 "^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+";
5c0d5b94
ZW
255 static regex_t re;
256
257 regmatch_t rm[1];
258 const char *p, *limit;
4c6d912f
ZW
259 const char *str = p_fixd->patch_args[0];
260 size_t len;
5c0d5b94 261
4c6d912f
ZW
262 if (str == NULL)
263 {
264 fprintf (stderr, "%s needs macro-name-string argument",
265 p_fixd->fix_name);
266 exit(3);
267 }
268
269 len = strlen (str);
5c0d5b94
ZW
270 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_uses");
271
272 for (p = text;
273 regexec (&re, p, 1, rm, 0) == 0;
274 p = limit + 1)
275 {
276 /* p + rm[0].rm_eo is the first character of the macro replacement.
277 Find the end of the macro replacement, and the STR we were
278 sent to look for within the replacement. */
279 p += rm[0].rm_eo;
280 limit = p - 1;
281 do
282 {
283 limit = strchr (limit + 1, '\n');
284 if (!limit)
285 goto done;
286 }
287 while (limit[-1] == '\\');
288
289 do
290 {
291 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
292 goto found;
293 }
294 while (++p < limit - len);
295 /* Hit end of line. */
296 continue;
297
298 found:
299 /* Found STR on this line. If the macro needs fixing,
300 the next few chars will be whitespace or uppercase,
301 then an open paren, then a single letter. */
302 while ((isspace (*p) || isupper (*p)) && p < limit) p++;
303 if (*p++ != '(')
304 continue;
305 if (!isalpha (*p))
306 continue;
307 if (isalnum (p[1]) || p[1] == '_')
308 continue;
309
310 /* Splat all preceding text into the output buffer,
311 quote the character at p, then proceed. */
312 fwrite (text, 1, p - text, stdout);
313 putchar ('\'');
314 putchar (*p);
315 putchar ('\'');
316 text = p + 1;
317 }
318 done:
319 fputs (text, stdout);
320}
321
322/* Scan the input file for all occurrences of text like this:
323
324 #define _IO(x, y) ('x'<<16+y)
325
326 and change them to read like this:
327
328 #define _IO(x, y) (x<<16+y)
329
330 which is the required syntax per the C standard. (The uses of _IO
331 also have to be tweaked - see above.) 'IO' is actually whatever
332 you provide in the STR argument. */
4c6d912f 333FIX_PROC_HEAD( char_macro_def_fix )
5c0d5b94
ZW
334{
335 /* This regexp looks for any traditional-syntax #define (# in column 1). */
336 static const char pat[] =
337 "^#[ \t]*define[ \t]+";
338 static regex_t re;
339
340 regmatch_t rm[1];
341 const char *p, *limit;
4c6d912f
ZW
342 const char *str = p_fixd->patch_args[0];
343 size_t len;
5c0d5b94
ZW
344 char arg;
345
4c6d912f
ZW
346 if (str == NULL)
347 {
348 fprintf (stderr, "%s needs macro-name-string argument",
349 p_fixd->fix_name);
350 exit(3);
351 }
352
5c0d5b94
ZW
353 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines");
354
355 for (p = text;
356 regexec (&re, p, 1, rm, 0) == 0;
357 p = limit + 1)
358 {
359 /* p + rm[0].rm_eo is the first character of the macro name.
360 Find the end of the macro replacement, and the STR we were
361 sent to look for within the name. */
362 p += rm[0].rm_eo;
363 limit = p - 1;
364 do
365 {
366 limit = strchr (limit + 1, '\n');
367 if (!limit)
368 goto done;
369 }
370 while (limit[-1] == '\\');
371
372 do
373 {
374 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
375 goto found;
3a2e9dd2 376 p++;
5c0d5b94
ZW
377 }
378 while (isalpha (*p) || isalnum (*p) || *p == '_');
379 /* Hit end of macro name without finding the string. */
380 continue;
381
382 found:
383 /* Found STR in this macro name. If the macro needs fixing,
384 there may be a few uppercase letters, then there will be an
385 open paren with _no_ intervening whitespace, and then a
386 single letter. */
387 while (isupper (*p) && p < limit) p++;
388 if (*p++ != '(')
389 continue;
390 if (!isalpha (*p))
391 continue;
392 if (isalnum (p[1]) || p[1] == '_')
393 continue;
394
395 /* The character at P is the one to look for in the following
396 text. */
397 arg = *p;
398 p += 2;
399
400 while (p < limit)
401 {
402 if (p[-1] == '\'' && p[0] == arg && p[1] == '\'')
403 {
404 /* Remove the quotes from this use of ARG. */
405 p--;
406 fwrite (text, 1, p - text, stdout);
407 putchar (arg);
408 p += 3;
409 text = p;
410 }
411 else
412 p++;
413 }
414 }
415 done:
416 fputs (text, stdout);
417}
418
52c207e2
ZW
419/* Fix for machine name #ifdefs that are not in the namespace reserved
420 by the C standard. They won't be defined if compiling with -ansi,
421 and the headers will break. We go to some trouble to only change
422 #ifdefs where the macro is defined by GCC in non-ansi mode; this
423 minimizes the number of headers touched. */
424
425#define SCRATCHSZ 64 /* hopefully long enough */
426
427FIX_PROC_HEAD( machine_name_fix )
428{
bff0dc38
BK
429#ifndef MN_NAME_PAT
430 fputs( "The target machine has no needed machine name fixes\n", stderr );
431#else
52c207e2 432 regmatch_t match[2];
4c6d912f 433 const char *line, *base, *limit, *p, *q;
52c207e2
ZW
434 regex_t *label_re, *name_re;
435 char scratch[SCRATCHSZ];
436 size_t len;
437
bff0dc38 438 mn_get_regexps (&label_re, &name_re, "machine_name_fix");
78a0d70c 439
52c207e2
ZW
440 scratch[0] = '_';
441 scratch[1] = '_';
442
443 for (base = text;
444 regexec (label_re, base, 2, match, 0) == 0;
445 base = limit)
446 {
447 base += match[0].rm_eo;
448 /* We're looking at an #if or #ifdef. Scan forward for the
449 next non-escaped newline. */
450 line = limit = base;
451 do
452 {
453 limit++;
454 limit = strchr (limit, '\n');
455 if (!limit)
456 goto done;
457 }
458 while (limit[-1] == '\\');
459
460 /* If the 'name_pat' matches in between base and limit, we have
461 a bogon. It is not worth the hassle of excluding comments
462 because comments on #if/#ifdef lines are rare, and strings on
463 such lines are illegal.
464
465 REG_NOTBOL means 'base' is not at the beginning of a line, which
466 shouldn't matter since the name_re has no ^ anchor, but let's
467 be accurate anyway. */
468
469 for (;;)
470 {
471 again:
472 if (base == limit)
473 break;
474
475 if (regexec (name_re, base, 1, match, REG_NOTBOL))
476 goto done; /* No remaining match in this file */
477
478 /* Match; is it on the line? */
479 if (match[0].rm_eo > limit - base)
480 break;
481
482 p = base + match[0].rm_so;
483 base += match[0].rm_eo;
484
485 /* One more test: if on the same line we have the same string
486 with the appropriate underscores, then leave it alone.
487 We want exactly two leading and trailing underscores. */
488 if (*p == '_')
489 {
490 len = base - p - ((*base == '_') ? 2 : 1);
491 q = p + 1;
492 }
493 else
494 {
495 len = base - p - ((*base == '_') ? 1 : 0);
496 q = p;
497 }
498 if (len + 4 > SCRATCHSZ)
499 abort ();
500 memcpy (&scratch[2], q, len);
501 len += 2;
502 scratch[len++] = '_';
503 scratch[len++] = '_';
504
505 for (q = line; q <= limit - len; q++)
506 if (*q == '_' && !strncmp (q, scratch, len))
507 goto again;
508
509 fwrite (text, 1, p - text, stdout);
510 fwrite (scratch, 1, len, stdout);
511
512 text = base;
513 }
514 }
515 done:
bff0dc38 516#endif
52c207e2 517 fputs (text, stdout);
52c207e2
ZW
518}
519
520
5abc1f74
BK
521/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
522
523 test for fix selector
524
525 THIS IS THE ONLY EXPORTED ROUTINE
526
527*/
528void
35dfe415
BK
529apply_fix( p_fixd, filname )
530 tFixDesc* p_fixd;
531 tCC* filname;
5abc1f74 532{
99d525c9 533#define _FT_(n,p) { n, p },
5abc1f74 534 static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
99d525c9
PDM
535#undef _FT_
536#define FIX_TABLE_CT ((sizeof(fix_table)/sizeof(fix_table[0]))-1)
5abc1f74 537
35dfe415 538 tCC* fixname = p_fixd->patch_args[0];
5abc1f74
BK
539 char* buf;
540 int ct = FIX_TABLE_CT;
541 fix_entry_t* pfe = fix_table;
542
543 for (;;)
544 {
545 if (strcmp (pfe->fix_name, fixname) == 0)
546 break;
547 if (--ct <= 0)
8f9ca912
BK
548 {
549 fprintf (stderr, "fixincludes error: the `%s' fix is unknown\n",
550 fixname );
551 exit (3);
552 }
553 pfe++;
5abc1f74
BK
554 }
555
556 buf = load_file_data (stdin);
35dfe415 557 (*pfe->fix_proc)( filname, buf, p_fixd );
5abc1f74 558}
This page took 0.200335 seconds and 5 git commands to generate.