]> gcc.gnu.org Git - gcc.git/blame - gcc/fixinc/fixfixes.c
osf.h (TARGET_HAS_XFLOATING_LIBS): Define.
[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
b51207a4 6 Copyright (C) 1997-1999, 2000 Free Software Foundation, Inc.
5abc1f74
BK
7
8= = = = = = = = = = = = = = = = = = = = = = = = =
9
10NOTE TO DEVELOPERS
11
12The routines you write here must work closely with both the fixincl.c
13and the test_need.c program.
14
15Here are the rules:
16
171. Every test procedure name must be suffixed with "_fix".
18 These routines will be referenced from inclhack.def, sans the suffix.
19
202. Use the "FIX_PROC_HEAD()" macro _with_ the "_fix" suffix
21 (I cannot use the ## magic from ANSI C) for defining your entry point.
22
233. Put your test name into the FIXUP_TABLE
24
254. Do not read anything from stdin. It is closed.
26
275. Write to stderr only in the event of a reportable error
28 In such an event, call "exit(1)".
29
306. 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.
33
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!!
37
38
39 tFixDesc* pMyDesc = fixDescList + MY_FIX_NAME_FIXIDX;
40 tTestDesc* pTestList = pMyDesc->p_test_desc;
41
42 regexec (pTestList->p_test_regex, ...)
43
44
45 If MAIN _is_ defined, then you will have to compile it on
46 your own.
47
48= = = = = = = = = = = = = = = = = = = = = = = = =
49
50This file is part of GNU CC.
51
52GNU CC is free software; you can redistribute it and/or modify
53it under the terms of the GNU General Public License as published by
54the Free Software Foundation; either version 2, or (at your option)
55any later version.
56
57GNU CC is distributed in the hope that it will be useful,
58but WITHOUT ANY WARRANTY; without even the implied warranty of
59MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60GNU General Public License for more details.
61
62You should have received a copy of the GNU General Public License
63along with GNU CC; see the file COPYING. If not, write to
64the Free Software Foundation, 59 Temple Place - Suite 330,
65Boston, MA 02111-1307, USA. */
66
67#include "fixlib.h"
68
69typedef struct {
70 const char* fix_name;
71 void (*fix_proc)();
72} fix_entry_t;
73
74#define FIXUP_TABLE \
8f9ca912 75 _FT_( "no_double_slash", double_slash_fix ) \
5c0d5b94
ZW
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 ) \
52c207e2
ZW
80 _FT_( "CTRL_defn", CTRL_defn_fix ) \
81 _FT_( "machine_name", machine_name_fix )
5abc1f74
BK
82
83
84#define FIX_PROC_HEAD( fix ) \
85static void fix ( filname, text ) \
86 const char* filname; \
87 char* text;
88
89
90/*
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.
95 */
96static char*
97print_quote( q, text )
98 char q;
99 char* text;
100{
101 fputc( q, stdout );
102
103 for (;;)
104 {
105 char ch = *(text++);
106 fputc( ch, stdout );
107
108 switch (ch)
109 {
110 case '\\':
111 if (*text == NUL)
112 goto quote_done;
113
114 fputc( *(text++), stdout );
115 break;
116
117 case '"':
118 case '\'':
119 if (ch != q)
120 break;
121 /*FALLTHROUGH*/
122
123 case '\n':
124 case NUL:
125 goto quote_done;
126 }
127 } quote_done:;
128
129 return text;
130}
131
132
133FIX_PROC_HEAD( double_slash_fix )
134{
135 /* Now look for the comment markers in the text */
136 for (;;)
137 {
138 char ch = *(text++);
139 switch (ch)
140 {
141 case '/':
142 switch (*text) /* do not advance `text' here */
143 {
144 case '/':
145 /*
146 We found a "//" pair in open text.
147 Delete text to New-Line
148 */
149 while ((*text != '\n') && (*text != '\0')) text++;
150 break;
151
152 case '*':
153 {
154 /* We found a C-style comment. Skip forward to the end */
155 char* pz = strstr( (--text)+2, "*/" );
156 if (pz == (char*)NULL)
157 {
158 fputs( text, stdout );
159 goto fix_done;
160 }
161 pz += 2;
162 fwrite (text, (pz - text), 1, stdout );
163 text = pz;
164 }
165 break;
166
167 default:
168 fputc (ch, stdout );
169 }
170 break;
171
172 case NUL:
173 goto fix_done;
174
175 case '"':
176 case '\'':
177 text = print_quote (ch, text );
178 break;
179
180 default:
181 fputc (ch, stdout );
182 }
183
184 } fix_done:;
185
186 fclose (stdout);;
187}
188
8f9ca912
BK
189
190FIX_PROC_HEAD( else_endif_label_fix )
191{
192 static const char label_pat[] = "^[ \t]*#[ \t]*(else|endif)";
193 static regex_t label_re;
194
195 char ch;
196 char* pz_next = (char*)NULL;
197 regmatch_t match[2];
198
b51207a4
ZW
199 compile_re (label_pat, &label_re, 1,
200 "label pattern", "else_endif_label_fix");
8f9ca912
BK
201
202 for (;;) /* entire file */
203 {
204 /*
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 */
208 if (pz_next < text)
209 {
210 if (regexec (&label_re, text, 2, match, 0) != 0)
211 {
212 fputs( text, stdout );
213 break;
214 }
215
216 pz_next = text + match[0].rm_eo;
217 }
218
219 /*
220 IF the scan pointer has not reached the directive end, ... */
221 if (pz_next > text)
222 {
223 /*
224 Advance the scanning pointer. If we are at the start
225 of a quoted string or a comment, then skip the entire unit */
226 ch = *text;
227
228 switch (ch)
229 {
230 case '/':
231 /*
232 Skip comments */
233 if (text[1] == '*')
234 {
235 char* pz = strstr( text+2, "*/" );
236 if (pz == (char*)NULL)
237 {
238 fputs( text, stdout );
239 return;
240 }
241 pz += 2;
242 fwrite( text, 1, (pz - text), stdout );
243 text = pz;
244 continue;
245 }
246 putc( ch, stdout );
247 text++;
248 break;
249
250 case '"':
251 case '\'':
252 text = print_quote( ch, text+1 );
253 break;
254
255 default:
256 putc( ch, stdout );
257 text++;
258 } /* switch (ch) */
259 continue;
260 } /* if (still shy of directive end) */
261
262 /*
263 The scanning pointer (text) has reached the end of the current
264 directive under test. Check for bogons here. */
265 for (;;) /* bogon check */
266 {
267 char ch = *(text++);
268 if (isspace (ch))
269 {
270 putc( ch, stdout );
271 if (ch == '\n')
272 {
273 /*
274 It is clean. No bogons on this directive */
275 pz_next = (char*)NULL; /* force a new regex search */
276 goto dont_fix_bogon;
277 }
278 continue;
279 }
280
281 switch (ch)
282 {
283 case NUL:
284 return;
285
286 case '\\':
287 /*
288 Skip escaped newlines. Otherwise, we have a bogon */
289 if (*text != '\n') {
290 text--;
291 goto fix_the_bogon;
292 }
293
294 /*
295 Emit the escaped newline and keep scanning for possible junk */
296 putc( '\\', stdout );
297 putc( '\n', stdout );
298 text++;
299 break;
300
301 case '/':
302 /*
303 Skip comments. Otherwise, we have a bogon */
304 if (*text == '*')
305 {
306 text--;
307 pz_next = strstr( text+2, "*/" );
308 if (pz_next == (char*)NULL)
309 {
310 putc( '\n', stdout );
311 return;
312 }
313 pz_next += 2;
314 fwrite( text, 1, (pz_next - text), stdout );
315 text = pz_next;
316 break;
317 }
318
8f9ca912
BK
319 /* FALLTHROUGH */
320
321 default:
322 /*
323 GOTTA BE A BOGON */
324 text--;
325 goto fix_the_bogon;
326 } /* switch (ch) */
327 } /* for (bogon check loop) */
328
329 fix_the_bogon:
330 /*
331 `text' points to the start of the bogus data */
332 for (;;)
333 {
334 /*
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)
339 {
340 putc( '\n', stdout );
341 return;
342 }
343
344 if (pz_next[-1] != '\\')
345 {
346 text = pz_next;
347 pz_next = (char*)NULL; /* force a new regex search */
348 break;
349 }
350
351 /*
352 The newline was escaped. We gotta keep going. */
353 text = pz_next + 1;
354 }
355
356 dont_fix_bogon:;
357 } /* for (entire file) loop */
358
359 return;
360}
361
5c0d5b94
ZW
362/* Scan the input file for all occurrences of text like this:
363
364 #define TIOCCONS _IO(T, 12)
365
366 and change them to read like this:
367
368 #define TIOCCONS _IO('T', 12)
369
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. */
373void
374fix_char_macro_uses (text, str)
375 const char *text;
376 const char *str;
377{
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]+";
382 static regex_t re;
383
384 regmatch_t rm[1];
385 const char *p, *limit;
386 size_t len = strlen (str);
387
388 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_uses");
389
390 for (p = text;
391 regexec (&re, p, 1, rm, 0) == 0;
392 p = limit + 1)
393 {
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. */
397 p += rm[0].rm_eo;
398 limit = p - 1;
399 do
400 {
401 limit = strchr (limit + 1, '\n');
402 if (!limit)
403 goto done;
404 }
405 while (limit[-1] == '\\');
406
407 do
408 {
409 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
410 goto found;
411 }
412 while (++p < limit - len);
413 /* Hit end of line. */
414 continue;
415
416 found:
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++;
421 if (*p++ != '(')
422 continue;
423 if (!isalpha (*p))
424 continue;
425 if (isalnum (p[1]) || p[1] == '_')
426 continue;
427
428 /* Splat all preceding text into the output buffer,
429 quote the character at p, then proceed. */
430 fwrite (text, 1, p - text, stdout);
431 putchar ('\'');
432 putchar (*p);
433 putchar ('\'');
434 text = p + 1;
435 }
436 done:
437 fputs (text, stdout);
438}
439
440/* Scan the input file for all occurrences of text like this:
441
442 #define _IO(x, y) ('x'<<16+y)
443
444 and change them to read like this:
445
446 #define _IO(x, y) (x<<16+y)
447
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. */
451void
452fix_char_macro_defines (text, str)
453 const char *text;
454 const char *str;
455{
456 /* This regexp looks for any traditional-syntax #define (# in column 1). */
457 static const char pat[] =
458 "^#[ \t]*define[ \t]+";
459 static regex_t re;
460
461 regmatch_t rm[1];
462 const char *p, *limit;
463 size_t len = strlen (str);
464 char arg;
465
466 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines");
467
468 for (p = text;
469 regexec (&re, p, 1, rm, 0) == 0;
470 p = limit + 1)
471 {
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. */
475 p += rm[0].rm_eo;
476 limit = p - 1;
477 do
478 {
479 limit = strchr (limit + 1, '\n');
480 if (!limit)
481 goto done;
482 }
483 while (limit[-1] == '\\');
484
485 do
486 {
487 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
488 goto found;
489 }
490 while (isalpha (*p) || isalnum (*p) || *p == '_');
491 /* Hit end of macro name without finding the string. */
492 continue;
493
494 found:
495 /* Found STR in this macro name. If the macro needs fixing,
496 there may be a few uppercase letters, then there will be an
497 open paren with _no_ intervening whitespace, and then a
498 single letter. */
499 while (isupper (*p) && p < limit) p++;
500 if (*p++ != '(')
501 continue;
502 if (!isalpha (*p))
503 continue;
504 if (isalnum (p[1]) || p[1] == '_')
505 continue;
506
507 /* The character at P is the one to look for in the following
508 text. */
509 arg = *p;
510 p += 2;
511
512 while (p < limit)
513 {
514 if (p[-1] == '\'' && p[0] == arg && p[1] == '\'')
515 {
516 /* Remove the quotes from this use of ARG. */
517 p--;
518 fwrite (text, 1, p - text, stdout);
519 putchar (arg);
520 p += 3;
521 text = p;
522 }
523 else
524 p++;
525 }
526 }
527 done:
528 fputs (text, stdout);
529}
530
531/* The various prefixes on these macros are handled automatically
532 because the fixers don't care where they start matching. */
533FIX_PROC_HEAD( IO_use_fix )
534{
535 fix_char_macro_uses (text, "IO");
536}
537FIX_PROC_HEAD( CTRL_use_fix )
538{
539 fix_char_macro_uses (text, "CTRL");
540}
541
542FIX_PROC_HEAD( IO_defn_fix )
543{
544 fix_char_macro_defines (text, "IO");
545}
546FIX_PROC_HEAD( CTRL_defn_fix )
547{
548 fix_char_macro_defines (text, "CTRL");
549}
550
551
52c207e2
ZW
552/* Fix for machine name #ifdefs that are not in the namespace reserved
553 by the C standard. They won't be defined if compiling with -ansi,
554 and the headers will break. We go to some trouble to only change
555 #ifdefs where the macro is defined by GCC in non-ansi mode; this
556 minimizes the number of headers touched. */
557
558#define SCRATCHSZ 64 /* hopefully long enough */
559
560FIX_PROC_HEAD( machine_name_fix )
561{
562 regmatch_t match[2];
563 char *line, *base, *limit, *p, *q;
564 regex_t *label_re, *name_re;
565 char scratch[SCRATCHSZ];
566 size_t len;
567
568 mn_get_regexps (&label_re, &name_re, "machine_name_fix");
569 scratch[0] = '_';
570 scratch[1] = '_';
571
572 for (base = text;
573 regexec (label_re, base, 2, match, 0) == 0;
574 base = limit)
575 {
576 base += match[0].rm_eo;
577 /* We're looking at an #if or #ifdef. Scan forward for the
578 next non-escaped newline. */
579 line = limit = base;
580 do
581 {
582 limit++;
583 limit = strchr (limit, '\n');
584 if (!limit)
585 goto done;
586 }
587 while (limit[-1] == '\\');
588
589 /* If the 'name_pat' matches in between base and limit, we have
590 a bogon. It is not worth the hassle of excluding comments
591 because comments on #if/#ifdef lines are rare, and strings on
592 such lines are illegal.
593
594 REG_NOTBOL means 'base' is not at the beginning of a line, which
595 shouldn't matter since the name_re has no ^ anchor, but let's
596 be accurate anyway. */
597
598 for (;;)
599 {
600 again:
601 if (base == limit)
602 break;
603
604 if (regexec (name_re, base, 1, match, REG_NOTBOL))
605 goto done; /* No remaining match in this file */
606
607 /* Match; is it on the line? */
608 if (match[0].rm_eo > limit - base)
609 break;
610
611 p = base + match[0].rm_so;
612 base += match[0].rm_eo;
613
614 /* One more test: if on the same line we have the same string
615 with the appropriate underscores, then leave it alone.
616 We want exactly two leading and trailing underscores. */
617 if (*p == '_')
618 {
619 len = base - p - ((*base == '_') ? 2 : 1);
620 q = p + 1;
621 }
622 else
623 {
624 len = base - p - ((*base == '_') ? 1 : 0);
625 q = p;
626 }
627 if (len + 4 > SCRATCHSZ)
628 abort ();
629 memcpy (&scratch[2], q, len);
630 len += 2;
631 scratch[len++] = '_';
632 scratch[len++] = '_';
633
634 for (q = line; q <= limit - len; q++)
635 if (*q == '_' && !strncmp (q, scratch, len))
636 goto again;
637
638 fwrite (text, 1, p - text, stdout);
639 fwrite (scratch, 1, len, stdout);
640
641 text = base;
642 }
643 }
644 done:
645 fputs (text, stdout);
52c207e2
ZW
646}
647
648
5abc1f74
BK
649/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
650
651 test for fix selector
652
653 THIS IS THE ONLY EXPORTED ROUTINE
654
655*/
656void
657apply_fix( fixname, filname )
658 const char* fixname;
659 const char* filname;
660{
99d525c9 661#define _FT_(n,p) { n, p },
5abc1f74 662 static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
99d525c9
PDM
663#undef _FT_
664#define FIX_TABLE_CT ((sizeof(fix_table)/sizeof(fix_table[0]))-1)
5abc1f74
BK
665
666 char* buf;
667 int ct = FIX_TABLE_CT;
668 fix_entry_t* pfe = fix_table;
669
670 for (;;)
671 {
672 if (strcmp (pfe->fix_name, fixname) == 0)
673 break;
674 if (--ct <= 0)
8f9ca912
BK
675 {
676 fprintf (stderr, "fixincludes error: the `%s' fix is unknown\n",
677 fixname );
678 exit (3);
679 }
680 pfe++;
5abc1f74
BK
681 }
682
683 buf = load_file_data (stdin);
684 (*pfe->fix_proc)( filname, buf );
685}
686
687#ifdef MAIN
688
689/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
690
691 MAIN ROUTINE
692
693 This file is both included in fixincl.c and compiled as a separate
694 program for use by the inclhack.sh script.
695
696*/
697
698int
699main( argc, argv )
700 int argc;
701 char** argv;
702{
703 if (argc != 3)
704 apply_fix ("No test name provided", NULL, NULL, 0 );
705
706 apply_fix (argv[2], argv[1]);
707 return 0;
708}
709
710#endif
This page took 0.152957 seconds and 5 git commands to generate.