]> git.ipfire.org Git - thirdparty/gcc.git/blame - fixincludes/fixfixes.c
[Ada] Spurious accessibility error on return aggregate in GNATprove mode
[thirdparty/gcc.git] / fixincludes / fixfixes.c
CommitLineData
5abc1f74
BK
1
2/*
3
4 Test to see if a particular fix should be applied to a header file.
5
748086b7 6 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2009
6e6a1681 7 Free Software Foundation, Inc.
5abc1f74
BK
8
9= = = = = = = = = = = = = = = = = = = = = = = = =
10
11NOTE TO DEVELOPERS
12
b7976767 13The routines you write here must work closely with fixincl.c.
5abc1f74
BK
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
ba8fcfc3 233. Put your test name into the FIXUP_TABLE.
5abc1f74
BK
24
254. Do not read anything from stdin. It is closed.
26
275. Write to stderr only in the event of a reportable error
22e50c5b 28 In such an event, call "exit (EXIT_FAILURE)".
5abc1f74 29
b7976767 306. You have access to the fixDescList entry for the fix in question.
ba8fcfc3
BK
31 This may be useful, for example, if there are interesting strings
32 or pre-compiled regular expressions stored there.
5abc1f74 33
5abc1f74
BK
34= = = = = = = = = = = = = = = = = = = = = = = = =
35
6e6a1681 36This file is part of GCC.
5abc1f74 37
6e6a1681 38GCC is free software; you can redistribute it and/or modify
5abc1f74 39it under the terms of the GNU General Public License as published by
748086b7 40the Free Software Foundation; either version 3, or (at your option)
5abc1f74
BK
41any later version.
42
6e6a1681 43GCC is distributed in the hope that it will be useful,
5abc1f74
BK
44but WITHOUT ANY WARRANTY; without even the implied warranty of
45MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46GNU General Public License for more details.
47
48You should have received a copy of the GNU General Public License
748086b7
JJ
49along with GCC; see the file COPYING3. If not see
50<http://www.gnu.org/licenses/>. */
5abc1f74
BK
51
52#include "fixlib.h"
687262b1 53#define GTYPE_SE_CT 1
5abc1f74 54
283da1d3 55#ifdef SEPARATE_FIX_PROC
62a99405
BK
56#include "fixincl.x"
57#endif
58
22e50c5b
BK
59tSCC zNeedsArg[] = "fixincl error: `%s' needs %s argument (c_fix_arg[%d])\n";
60
f4dbf936 61typedef void t_fix_proc (const char *, const char *, tFixDesc *) ;
5abc1f74
BK
62typedef struct {
63 const char* fix_name;
3af556f7 64 t_fix_proc* fix_proc;
5abc1f74
BK
65} fix_entry_t;
66
67#define FIXUP_TABLE \
27a498c9 68 _FT_( "char_macro_def", char_macro_def_fix ) \
ba8fcfc3
BK
69 _FT_( "char_macro_use", char_macro_use_fix ) \
70 _FT_( "format", format_fix ) \
71 _FT_( "machine_name", machine_name_fix ) \
687262b1
BK
72 _FT_( "wrap", wrap_fix ) \
73 _FT_( "gnu_type", gnu_type_fix )
5abc1f74
BK
74
75
f4dbf936
NN
76#define FIX_PROC_HEAD( fix ) \
77static void fix (const char* filname ATTRIBUTE_UNUSED , \
78 const char* text ATTRIBUTE_UNUSED , \
79 tFixDesc* p_fixd ATTRIBUTE_UNUSED )
5abc1f74 80
3af556f7 81#ifdef NEED_PRINT_QUOTE
5abc1f74
BK
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*
f4dbf936 89print_quote(char q, char* text )
5abc1f74
BK
90{
91 fputc( q, stdout );
92
93 for (;;)
94 {
95 char ch = *(text++);
96 fputc( ch, stdout );
97
98 switch (ch)
99 {
100 case '\\':
101 if (*text == NUL)
102 goto quote_done;
103
104 fputc( *(text++), stdout );
105 break;
106
107 case '"':
108 case '\'':
109 if (ch != q)
110 break;
111 /*FALLTHROUGH*/
112
113 case '\n':
114 case NUL:
115 goto quote_done;
116 }
117 } quote_done:;
118
119 return text;
120}
3af556f7 121#endif /* NEED_PRINT_QUOTE */
5abc1f74 122
1e248c55 123
687262b1
BK
124/*
125 * Emit the GNU standard type wrapped up in such a way that
126 * this thing can be encountered countless times during a compile
127 * and not cause even a warning.
128 */
129static const char*
f4dbf936 130emit_gnu_type (const char* text, regmatch_t* rm )
687262b1 131{
71e06bde
BK
132 char z_TYPE[ 64 ];
133 char z_type[ 64 ];
687262b1
BK
134
135 fwrite (text, rm[0].rm_so, 1, stdout);
687262b1 136
71e06bde
BK
137 {
138 const char* ps = text + rm[1].rm_so;
139 const char* pe = text + rm[1].rm_eo;
140 char* pd = z_type;
141 char* pD = z_TYPE;
687262b1 142
71e06bde 143 while (ps < pe)
f6bbde28 144 *(pD++) = TOUPPER( *(pd++) = *(ps++) );
71e06bde
BK
145
146 *pD = *pd = NUL;
147 }
687262b1
BK
148
149 /*
71e06bde
BK
150 * Now print out the reformed typedef,
151 * with a C++ guard for WCHAR
687262b1 152 */
a83b3e4f
BK
153 {
154 tSCC z_fmt[] = "\
fd589a2a 155#if !defined(_GCC_%s_T)%s\n\
71e06bde
BK
156#define _GCC_%s_T\n\
157typedef __%s_TYPE__ %s_t;\n\
158#endif\n";
a83b3e4f 159
27c38fbe 160 const char *const pz_guard = (strcmp (z_type, "wchar") == 0)
71e06bde 161 ? " && ! defined(__cplusplus)" : "";
a83b3e4f 162
71e06bde 163 printf (z_fmt, z_TYPE, pz_guard, z_TYPE, z_TYPE, z_type);
a83b3e4f 164 }
687262b1 165
71e06bde 166 return text += rm[0].rm_eo;
687262b1
BK
167}
168
169
1e248c55
BK
170/*
171 * Copy the `format' string to std out, replacing `%n' expressions
172 * with the matched text from a regular expression evaluation.
173 * Doubled '%' characters will be replaced with a single copy.
174 * '%' characters in other contexts and all other characters are
175 * copied out verbatim.
176 */
4c6d912f 177static void
f4dbf936 178format_write (tCC* format, tCC* text, regmatch_t av[] )
4c6d912f 179{
1e248c55 180 int c;
a92fa608 181
1e248c55 182 while ((c = (unsigned)*(format++)) != NUL) {
a92fa608 183
1e248c55
BK
184 if (c != '%')
185 {
186 putchar(c);
187 continue;
188 }
a92fa608 189
1e248c55
BK
190 c = (unsigned)*(format++);
191
192 /*
193 * IF the character following a '%' is not a digit,
194 * THEN we will always emit a '%' and we may or may
195 * not emit the following character. We will end on
196 * a NUL and we will emit only one of a pair of '%'.
197 */
6864a6c6 198 if (! ISDIGIT ( c ))
1e248c55
BK
199 {
200 putchar( '%' );
201 switch (c) {
202 case NUL:
203 return;
204 case '%':
205 break;
206 default:
207 putchar(c);
a92fa608 208 }
1e248c55 209 }
a92fa608 210
1e248c55
BK
211 /*
212 * Emit the matched subexpression numbered 'c'.
213 * IF, of course, there was such a match...
214 */
215 else {
216 regmatch_t* pRM = av + (c - (unsigned)'0');
217 size_t len;
a92fa608 218
1e248c55
BK
219 if (pRM->rm_so < 0)
220 continue;
a92fa608 221
1e248c55
BK
222 len = pRM->rm_eo - pRM->rm_so;
223 if (len > 0)
224 fwrite(text + pRM->rm_so, len, 1, stdout);
4c6d912f 225 }
1e248c55 226 }
4c6d912f 227}
5abc1f74 228
a92fa608 229
1e248c55
BK
230/*
231 * Search for multiple copies of a regular expression. Each block
232 * of matched text is replaced with the format string, as described
233 * above in `format_write'.
234 */
35dfe415 235FIX_PROC_HEAD( format_fix )
5abc1f74 236{
1e248c55
BK
237 tCC* pz_pat = p_fixd->patch_args[2];
238 tCC* pz_fmt = p_fixd->patch_args[1];
1e248c55
BK
239 regex_t re;
240 regmatch_t rm[10];
2629a114 241 IGNORE_ARG(filname);
1e248c55
BK
242
243 /*
244 * We must have a format
245 */
246 if (pz_fmt == (tCC*)NULL)
247 {
22e50c5b
BK
248 fprintf( stderr, zNeedsArg, p_fixd->fix_name, "replacement format", 0 );
249 exit (EXIT_BROKEN);
35dfe415 250 }
8f9ca912 251
1e248c55
BK
252 /*
253 * IF we don't have a search text, then go find the first
254 * regular expression among the tests.
255 */
256 if (pz_pat == (tCC*)NULL)
257 {
258 tTestDesc* pTD = p_fixd->p_test_desc;
259 int ct = p_fixd->test_ct;
260 for (;;)
261 {
262 if (ct-- <= 0)
263 {
22e50c5b
BK
264 fprintf( stderr, zNeedsArg, p_fixd->fix_name, "search text", 1 );
265 exit (EXIT_BROKEN);
35dfe415 266 }
8f9ca912 267
1e248c55
BK
268 if (pTD->type == TT_EGREP)
269 {
270 pz_pat = pTD->pz_test_text;
271 break;
8f9ca912
BK
272 }
273
1e248c55 274 pTD++;
8f9ca912 275 }
35dfe415 276 }
8f9ca912 277
1e248c55
BK
278 /*
279 * Replace every copy of the text we find
280 */
281 compile_re (pz_pat, &re, 1, "format search-text", "format_fix" );
ab747408 282 while (xregexec (&re, text, 10, rm, 0) == 0)
35dfe415 283 {
1e248c55
BK
284 fwrite( text, rm[0].rm_so, 1, stdout );
285 format_write( pz_fmt, text, rm );
286 text += rm[0].rm_eo;
35dfe415 287 }
8f9ca912 288
1e248c55
BK
289 /*
290 * Dump out the rest of the file
291 */
292 fputs (text, stdout);
8f9ca912
BK
293}
294
ba8fcfc3 295
5c0d5b94
ZW
296/* Scan the input file for all occurrences of text like this:
297
298 #define TIOCCONS _IO(T, 12)
299
300 and change them to read like this:
301
302 #define TIOCCONS _IO('T', 12)
303
304 which is the required syntax per the C standard. (The definition of
305 _IO also has to be tweaked - see below.) 'IO' is actually whatever you
1e248c55 306 provide as the `c_fix_arg' argument. */
4c6d912f
ZW
307
308FIX_PROC_HEAD( char_macro_use_fix )
5c0d5b94
ZW
309{
310 /* This regexp looks for a traditional-syntax #define (# in column 1)
311 of an object-like macro. */
22e50c5b
BK
312 static const char pat[] =
313 "^#[ \t]*define[ \t]+[_A-Za-z][_A-Za-z0-9]*[ \t]+";
5c0d5b94
ZW
314 static regex_t re;
315
22e50c5b
BK
316 const char* str = p_fixd->patch_args[1];
317 regmatch_t rm[1];
318 const char *p, *limit;
319 size_t len;
2629a114 320 IGNORE_ARG(filname);
4c6d912f 321
22e50c5b 322 if (str == NULL)
5c0d5b94 323 {
22e50c5b
BK
324 fprintf (stderr, zNeedsArg, p_fixd->fix_name, "ioctl type", 0);
325 exit (EXIT_BROKEN);
1e248c55 326 }
5c0d5b94 327
22e50c5b
BK
328 len = strlen (str);
329 compile_re (pat, &re, 1, "macro pattern", "char_macro_use_fix");
1e248c55 330
22e50c5b 331 for (p = text;
ab747408 332 xregexec (&re, p, 1, rm, 0) == 0;
22e50c5b 333 p = limit + 1)
1e248c55 334 {
22e50c5b
BK
335 /* p + rm[0].rm_eo is the first character of the macro replacement.
336 Find the end of the macro replacement, and the STR we were
337 sent to look for within the replacement. */
338 p += rm[0].rm_eo;
339 limit = p - 1;
340 do
341 {
342 limit = strchr (limit + 1, '\n');
343 if (!limit)
344 goto done;
345 }
346 while (limit[-1] == '\\');
1e248c55 347
22e50c5b
BK
348 do
349 {
350 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
351 goto found;
352 }
353 while (++p < limit - len);
354 /* Hit end of line. */
355 continue;
356
357 found:
358 /* Found STR on this line. If the macro needs fixing,
359 the next few chars will be whitespace or uppercase,
360 then an open paren, then a single letter. */
6864a6c6 361 while ((ISSPACE (*p) || ISUPPER (*p)) && p < limit) p++;
22e50c5b
BK
362 if (*p++ != '(')
363 continue;
6864a6c6 364 if (!ISALPHA (*p))
22e50c5b 365 continue;
0df6c2c7 366 if (ISIDNUM (p[1]))
22e50c5b
BK
367 continue;
368
369 /* Splat all preceding text into the output buffer,
370 quote the character at p, then proceed. */
371 fwrite (text, 1, p - text, stdout);
372 putchar ('\'');
373 putchar (*p);
374 putchar ('\'');
375 text = p + 1;
376 }
377 done:
5c0d5b94
ZW
378 fputs (text, stdout);
379}
380
1e248c55 381
5c0d5b94
ZW
382/* Scan the input file for all occurrences of text like this:
383
e9099386 384 #define xxxIOxx(x, y) (....'x'<<16....)
5c0d5b94
ZW
385
386 and change them to read like this:
387
e9099386 388 #define xxxIOxx(x, y) (....x<<16....)
5c0d5b94
ZW
389
390 which is the required syntax per the C standard. (The uses of _IO
1e248c55
BK
391 also has to be tweaked - see above.) 'IO' is actually whatever
392 you provide as the `c_fix_arg' argument. */
4c6d912f 393FIX_PROC_HEAD( char_macro_def_fix )
5c0d5b94 394{
22e50c5b
BK
395 /* This regexp looks for any traditional-syntax #define (# in column 1). */
396 static const char pat[] =
397 "^#[ \t]*define[ \t]+";
5c0d5b94 398 static regex_t re;
5c0d5b94 399
22e50c5b
BK
400 const char* str = p_fixd->patch_args[1];
401 regmatch_t rm[1];
402 const char *p, *limit;
403 char arg;
404 size_t len;
2629a114 405 IGNORE_ARG(filname);
4c6d912f 406
22e50c5b 407 if (str == NULL)
1e248c55 408 {
22e50c5b
BK
409 fprintf (stderr, zNeedsArg, p_fixd->fix_name, "ioctl type", 0);
410 exit (EXIT_BROKEN);
1e248c55
BK
411 }
412
22e50c5b
BK
413 len = strlen (str);
414 compile_re (pat, &re, 1, "macro pattern", "fix_char_macro_defines");
5c0d5b94 415
22e50c5b 416 for (p = text;
ab747408 417 xregexec (&re, p, 1, rm, 0) == 0;
22e50c5b 418 p = limit + 1)
5c0d5b94 419 {
22e50c5b
BK
420 /* p + rm[0].rm_eo is the first character of the macro name.
421 Find the end of the macro replacement, and the STR we were
422 sent to look for within the name. */
423 p += rm[0].rm_eo;
424 limit = p - 1;
425 do
426 {
427 limit = strchr (limit + 1, '\n');
428 if (!limit)
429 goto done;
430 }
431 while (limit[-1] == '\\');
1e248c55 432
22e50c5b
BK
433 do
434 {
435 if (*p == str[0] && !strncmp (p+1, str+1, len-1))
436 goto found;
437 p++;
438 }
0df6c2c7 439 while (ISIDNUM (*p));
22e50c5b
BK
440 /* Hit end of macro name without finding the string. */
441 continue;
442
443 found:
444 /* Found STR in this macro name. If the macro needs fixing,
445 there may be a few uppercase letters, then there will be an
446 open paren with _no_ intervening whitespace, and then a
447 single letter. */
6864a6c6 448 while (ISUPPER (*p) && p < limit) p++;
22e50c5b
BK
449 if (*p++ != '(')
450 continue;
6864a6c6 451 if (!ISALPHA (*p))
22e50c5b 452 continue;
0df6c2c7 453 if (ISIDNUM (p[1]))
22e50c5b
BK
454 continue;
455
456 /* The character at P is the one to look for in the following
457 text. */
458 arg = *p;
459 p += 2;
460
461 while (p < limit)
462 {
463 if (p[-1] == '\'' && p[0] == arg && p[1] == '\'')
464 {
465 /* Remove the quotes from this use of ARG. */
466 p--;
467 fwrite (text, 1, p - text, stdout);
468 putchar (arg);
469 p += 3;
470 text = p;
471 }
472 else
473 p++;
474 }
5c0d5b94 475 }
22e50c5b 476 done:
5c0d5b94
ZW
477 fputs (text, stdout);
478}
479
52c207e2
ZW
480/* Fix for machine name #ifdefs that are not in the namespace reserved
481 by the C standard. They won't be defined if compiling with -ansi,
482 and the headers will break. We go to some trouble to only change
483 #ifdefs where the macro is defined by GCC in non-ansi mode; this
484 minimizes the number of headers touched. */
485
486#define SCRATCHSZ 64 /* hopefully long enough */
487
488FIX_PROC_HEAD( machine_name_fix )
489{
490 regmatch_t match[2];
4c6d912f 491 const char *line, *base, *limit, *p, *q;
52c207e2
ZW
492 regex_t *label_re, *name_re;
493 char scratch[SCRATCHSZ];
494 size_t len;
2629a114
BK
495 IGNORE_ARG(filname);
496 IGNORE_ARG(p_fixd);
52c207e2 497
89b8abbf
PB
498 if (!mn_get_regexps (&label_re, &name_re, "machine_name_fix"))
499 {
500 fputs( "The target machine has no needed machine name fixes\n", stderr );
501 goto done;
502 }
78a0d70c 503
52c207e2
ZW
504 scratch[0] = '_';
505 scratch[1] = '_';
506
507 for (base = text;
ab747408 508 xregexec (label_re, base, 2, match, 0) == 0;
52c207e2
ZW
509 base = limit)
510 {
511 base += match[0].rm_eo;
512 /* We're looking at an #if or #ifdef. Scan forward for the
1e248c55 513 next non-escaped newline. */
52c207e2
ZW
514 line = limit = base;
515 do
1e248c55
BK
516 {
517 limit++;
518 limit = strchr (limit, '\n');
519 if (!limit)
520 goto done;
521 }
52c207e2
ZW
522 while (limit[-1] == '\\');
523
524 /* If the 'name_pat' matches in between base and limit, we have
1e248c55
BK
525 a bogon. It is not worth the hassle of excluding comments
526 because comments on #if/#ifdef lines are rare, and strings on
527 such lines are illegal.
52c207e2 528
1e248c55
BK
529 REG_NOTBOL means 'base' is not at the beginning of a line, which
530 shouldn't matter since the name_re has no ^ anchor, but let's
531 be accurate anyway. */
52c207e2
ZW
532
533 for (;;)
1e248c55
BK
534 {
535 again:
536 if (base == limit)
537 break;
538
ab747408 539 if (xregexec (name_re, base, 1, match, REG_NOTBOL))
1e248c55
BK
540 goto done; /* No remaining match in this file */
541
542 /* Match; is it on the line? */
543 if (match[0].rm_eo > limit - base)
544 break;
545
546 p = base + match[0].rm_so;
547 base += match[0].rm_eo;
548
549 /* One more test: if on the same line we have the same string
550 with the appropriate underscores, then leave it alone.
551 We want exactly two leading and trailing underscores. */
552 if (*p == '_')
553 {
554 len = base - p - ((*base == '_') ? 2 : 1);
555 q = p + 1;
556 }
557 else
558 {
559 len = base - p - ((*base == '_') ? 1 : 0);
560 q = p;
561 }
562 if (len + 4 > SCRATCHSZ)
563 abort ();
564 memcpy (&scratch[2], q, len);
565 len += 2;
566 scratch[len++] = '_';
567 scratch[len++] = '_';
568
569 for (q = line; q <= limit - len; q++)
570 if (*q == '_' && !strncmp (q, scratch, len))
571 goto again;
572
573 fwrite (text, 1, p - text, stdout);
574 fwrite (scratch, 1, len, stdout);
575
576 text = base;
577 }
52c207e2
ZW
578 }
579 done:
580 fputs (text, stdout);
52c207e2
ZW
581}
582
583
ba8fcfc3
BK
584FIX_PROC_HEAD( wrap_fix )
585{
283da1d3 586 tSCC z_no_wrap_pat[] = "^#if.*__need_";
2629a114 587 static regex_t no_wrapping_re; /* assume zeroed data */
283da1d3 588
871dab3e 589 tCC* pz_name = NULL;
ba8fcfc3 590
283da1d3
DB
591 if (no_wrapping_re.allocated == 0)
592 compile_re( z_no_wrap_pat, &no_wrapping_re, 0, "no-wrap pattern",
593 "wrap-fix" );
594
283da1d3
DB
595 /*
596 * IF we do *not* match the no-wrap re, then we have a double negative.
597 * A double negative means YES.
598 */
ab747408 599 if (xregexec( &no_wrapping_re, text, 0, NULL, 0 ) != 0)
283da1d3 600 {
871dab3e
BK
601 /*
602 * A single file can get wrapped more than once by different fixes.
603 * A single fix can wrap multiple files. Therefore, guard with
604 * *both* the fix name and the file name.
605 */
606 size_t ln = strlen( filname ) + strlen( p_fixd->fix_name ) + 14;
03a9fcb8 607 char* pz = XNEWVEC (char, ln);
871dab3e
BK
608 pz_name = pz;
609 sprintf( pz, "FIXINC_WRAP_%s-%s", filname, p_fixd->fix_name );
610
611 for (pz += 12; 1; pz++) {
612 char ch = *pz;
613
614 if (ch == NUL)
615 break;
616
617 if (! ISALNUM( ch )) {
618 *pz = '_';
619 }
620 else {
621 *pz = TOUPPER( ch );
622 }
623 }
624
625 printf( "#ifndef %s\n", pz_name );
626 printf( "#define %s 1\n\n", pz_name );
283da1d3 627 }
ba8fcfc3
BK
628
629 if (p_fixd->patch_args[1] == (tCC*)NULL)
630 fputs( text, stdout );
631
632 else {
633 fputs( p_fixd->patch_args[1], stdout );
634 fputs( text, stdout );
635 if (p_fixd->patch_args[2] != (tCC*)NULL)
636 fputs( p_fixd->patch_args[2], stdout );
637 }
638
871dab3e
BK
639 if (pz_name != NULL) {
640 printf( "\n#endif /* %s */\n", pz_name );
ba8fcfc3 641 free( (void*)pz_name );
871dab3e 642 }
ba8fcfc3
BK
643}
644
645
687262b1
BK
646/*
647 * Search for multiple copies of a regular expression. Each block
648 * of matched text is replaced with the format string, as described
649 * above in `format_write'.
650 */
651FIX_PROC_HEAD( gnu_type_fix )
652{
653 const char* pz_pat;
654 regex_t re;
655 regmatch_t rm[GTYPE_SE_CT+1];
2629a114 656 IGNORE_ARG(filname);
687262b1
BK
657
658 {
659 tTestDesc* pTD = p_fixd->p_test_desc;
660 int ct = p_fixd->test_ct;
661 for (;;)
662 {
663 if (ct-- <= 0)
664 {
665 fprintf (stderr, zNeedsArg, p_fixd->fix_name, "search text", 1);
666 exit (EXIT_BROKEN);
667 }
668
669 if (pTD->type == TT_EGREP)
670 {
671 pz_pat = pTD->pz_test_text;
672 break;
673 }
674
675 pTD++;
676 }
677 }
678
679 compile_re (pz_pat, &re, 1, "gnu type typedef", "gnu_type_fix");
680
ab747408 681 while (xregexec (&re, text, GTYPE_SE_CT+1, rm, 0) == 0)
687262b1 682 {
687262b1 683 text = emit_gnu_type (text, rm);
687262b1
BK
684 }
685
686 /*
687 * Dump out the rest of the file
688 */
689 fputs (text, stdout);
690}
691
692
5abc1f74
BK
693/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
694
695 test for fix selector
696
697 THIS IS THE ONLY EXPORTED ROUTINE
698
699*/
700void
f4dbf936 701apply_fix( tFixDesc* p_fixd, tCC* filname )
5abc1f74 702{
99d525c9 703#define _FT_(n,p) { n, p },
5abc1f74 704 static fix_entry_t fix_table[] = { FIXUP_TABLE { NULL, NULL }};
99d525c9 705#undef _FT_
b6a1cbae 706#define FIX_TABLE_CT (ARRAY_SIZE (fix_table)-1)
5abc1f74 707
35dfe415 708 tCC* fixname = p_fixd->patch_args[0];
5abc1f74
BK
709 char* buf;
710 int ct = FIX_TABLE_CT;
711 fix_entry_t* pfe = fix_table;
712
713 for (;;)
714 {
715 if (strcmp (pfe->fix_name, fixname) == 0)
716 break;
717 if (--ct <= 0)
8f9ca912 718 {
22e50c5b 719 fprintf (stderr, "fixincl error: the `%s' fix is unknown\n",
8f9ca912 720 fixname );
22e50c5b 721 exit (EXIT_BROKEN);
8f9ca912
BK
722 }
723 pfe++;
5abc1f74
BK
724 }
725
726 buf = load_file_data (stdin);
35dfe415 727 (*pfe->fix_proc)( filname, buf, p_fixd );
5abc1f74 728}
62a99405 729
283da1d3 730#ifdef SEPARATE_FIX_PROC
62a99405
BK
731tSCC z_usage[] =
732"USAGE: applyfix <fix-name> <file-to-fix> <file-source> <file-destination>\n";
733tSCC z_reopen[] =
734"FS error %d (%s) reopening %s as std%s\n";
735
736int
f4dbf936 737main( int argc, char** argv )
62a99405
BK
738{
739 tFixDesc* pFix;
740 char* pz_tmptmp;
741 char* pz_tmp_base;
742 char* pz_tmp_dot;
743
744 if (argc != 5)
745 {
746 usage_failure:
283da1d3 747 fputs (z_usage, stderr);
62a99405
BK
748 return EXIT_FAILURE;
749 }
750
ad643a75
PB
751 initialize_opts ();
752
62a99405
BK
753 {
754 char* pz = argv[1];
755 long idx;
756
6864a6c6 757 if (! ISDIGIT ( *pz ))
62a99405
BK
758 goto usage_failure;
759
283da1d3 760 idx = strtol (pz, &pz, 10);
62a99405
BK
761 if ((*pz != NUL) || ((unsigned)idx >= FIX_COUNT))
762 goto usage_failure;
763 pFix = fixDescList + idx;
764 }
765
283da1d3 766 if (freopen (argv[3], "r", stdin) != stdin)
62a99405 767 {
283da1d3 768 fprintf (stderr, z_reopen, errno, strerror( errno ), argv[3], "in");
62a99405
BK
769 return EXIT_FAILURE;
770 }
771
03a9fcb8 772 pz_tmptmp = XNEWVEC (char, strlen (argv[4]) + 5);
62a99405
BK
773 strcpy( pz_tmptmp, argv[4] );
774
775 /* Don't lose because "12345678" and "12345678X" map to the same
776 file under DOS restricted 8+3 file namespace. Note that DOS
777 doesn't allow more than one dot in the trunk of a file name. */
778 pz_tmp_base = basename( pz_tmptmp );
779 pz_tmp_dot = strchr( pz_tmp_base, '.' );
13cf7262 780#ifdef _PC_NAME_MAX
62a99405
BK
781 if (pathconf( pz_tmptmp, _PC_NAME_MAX ) <= 12 /* is this DOS or Windows9X? */
782 && pz_tmp_dot != (char*)NULL)
283da1d3 783 strcpy (pz_tmp_dot+1, "X"); /* nuke the original extension */
62a99405 784 else
13cf7262 785#endif /* _PC_NAME_MAX */
283da1d3
DB
786 strcat (pz_tmptmp, ".X");
787 if (freopen (pz_tmptmp, "w", stdout) != stdout)
62a99405 788 {
283da1d3 789 fprintf (stderr, z_reopen, errno, strerror( errno ), pz_tmptmp, "out");
62a99405
BK
790 return EXIT_FAILURE;
791 }
792
716028e4
TK
793 /* Second parameter of apply_fix is file name */
794 apply_fix (pFix, argv[2]);
283da1d3
DB
795 fclose (stdout);
796 fclose (stdin);
797 unlink (argv[4]);
798 if (rename (pz_tmptmp, argv[4]) != 0)
62a99405 799 {
283da1d3
DB
800 fprintf (stderr, "error %d (%s) renaming %s to %s\n", errno,
801 strerror( errno ), pz_tmptmp, argv[4]);
62a99405
BK
802 return EXIT_FAILURE;
803 }
804
805 return EXIT_SUCCESS;
806}
807#endif