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