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