xref: /openbsd-src/gnu/gcc/fixincludes/fixlib.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
1*404b540aSrobert 
2*404b540aSrobert /* Install modified versions of certain ANSI-incompatible system header
3*404b540aSrobert    files which are fixed to work correctly with ANSI C and placed in a
4*404b540aSrobert    directory that GCC will search.
5*404b540aSrobert 
6*404b540aSrobert    Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
7*404b540aSrobert 
8*404b540aSrobert This file is part of GCC.
9*404b540aSrobert 
10*404b540aSrobert GCC is free software; you can redistribute it and/or modify
11*404b540aSrobert it under the terms of the GNU General Public License as published by
12*404b540aSrobert the Free Software Foundation; either version 2, or (at your option)
13*404b540aSrobert any later version.
14*404b540aSrobert 
15*404b540aSrobert GCC is distributed in the hope that it will be useful,
16*404b540aSrobert but WITHOUT ANY WARRANTY; without even the implied warranty of
17*404b540aSrobert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*404b540aSrobert GNU General Public License for more details.
19*404b540aSrobert 
20*404b540aSrobert You should have received a copy of the GNU General Public License
21*404b540aSrobert along with GCC; see the file COPYING.  If not, write to
22*404b540aSrobert the Free Software Foundation, 51 Franklin Street, Fifth Floor,
23*404b540aSrobert Boston, MA 02110-1301, USA.  */
24*404b540aSrobert 
25*404b540aSrobert #include "fixlib.h"
26*404b540aSrobert 
27*404b540aSrobert /* * * * * * * * * * * * *
28*404b540aSrobert 
29*404b540aSrobert    load_file_data loads all the contents of a file into malloc-ed memory.
30*404b540aSrobert    Its argument is the file pointer of the file to read in; the returned
31*404b540aSrobert    result is the NUL terminated contents of the file.  The file
32*404b540aSrobert    is presumed to be an ASCII text file containing no NULs.  */
33*404b540aSrobert 
34*404b540aSrobert char *
load_file_data(FILE * fp)35*404b540aSrobert load_file_data (FILE* fp)
36*404b540aSrobert {
37*404b540aSrobert   char *pz_data = (char*)NULL;
38*404b540aSrobert   int    space_left = -1;  /* allow for terminating NUL */
39*404b540aSrobert   size_t space_used = 0;
40*404b540aSrobert 
41*404b540aSrobert   if (fp == (FILE*)NULL)
42*404b540aSrobert     return pz_data;
43*404b540aSrobert 
44*404b540aSrobert   do
45*404b540aSrobert     {
46*404b540aSrobert       size_t  size_read;
47*404b540aSrobert 
48*404b540aSrobert       if (space_left < 1024)
49*404b540aSrobert         {
50*404b540aSrobert           space_left += 4096;
51*404b540aSrobert 	  pz_data = XRESIZEVEC (char, pz_data, space_left + space_used + 1 );
52*404b540aSrobert         }
53*404b540aSrobert       size_read = fread (pz_data + space_used, 1, space_left, fp);
54*404b540aSrobert 
55*404b540aSrobert       if (size_read == 0)
56*404b540aSrobert         {
57*404b540aSrobert           if (feof (fp))
58*404b540aSrobert             break;
59*404b540aSrobert 
60*404b540aSrobert           if (ferror (fp))
61*404b540aSrobert             {
62*404b540aSrobert               int err = errno;
63*404b540aSrobert               if (err != EISDIR)
64*404b540aSrobert                 fprintf (stderr, "error %d (%s) reading input\n", err,
65*404b540aSrobert                          xstrerror (err));
66*404b540aSrobert               free ((void *) pz_data);
67*404b540aSrobert               return (char *) NULL;
68*404b540aSrobert             }
69*404b540aSrobert         }
70*404b540aSrobert 
71*404b540aSrobert       space_left -= size_read;
72*404b540aSrobert       space_used += size_read;
73*404b540aSrobert     } while (! feof (fp));
74*404b540aSrobert 
75*404b540aSrobert   pz_data = XRESIZEVEC (char, pz_data, space_used+1 );
76*404b540aSrobert   pz_data[ space_used ] = NUL;
77*404b540aSrobert 
78*404b540aSrobert   return pz_data;
79*404b540aSrobert }
80*404b540aSrobert 
81*404b540aSrobert #ifdef IS_CXX_HEADER_NEEDED
82*404b540aSrobert t_bool
is_cxx_header(tCC * fname,tCC * text)83*404b540aSrobert is_cxx_header (tCC* fname, tCC* text)
84*404b540aSrobert {
85*404b540aSrobert   /*  First, check to see if the file is in a C++ directory */
86*404b540aSrobert   for (;;)
87*404b540aSrobert     {
88*404b540aSrobert       switch (*(fname++))
89*404b540aSrobert         {
90*404b540aSrobert         case 'C': /* check for "CC/" */
91*404b540aSrobert           if ((fname[0] == 'C') && (fname[1] == '/'))
92*404b540aSrobert             return BOOL_TRUE;
93*404b540aSrobert           break;
94*404b540aSrobert 
95*404b540aSrobert         case 'x': /* check for "xx/" */
96*404b540aSrobert           if ((fname[0] == 'x') && (fname[1] == '/'))
97*404b540aSrobert             return BOOL_TRUE;
98*404b540aSrobert           break;
99*404b540aSrobert 
100*404b540aSrobert         case '+': /* check for "++" */
101*404b540aSrobert           if (fname[0] == '+')
102*404b540aSrobert             return BOOL_TRUE;
103*404b540aSrobert           break;
104*404b540aSrobert 
105*404b540aSrobert         case NUL:
106*404b540aSrobert           goto not_cxx_name;
107*404b540aSrobert         }
108*404b540aSrobert     } not_cxx_name:;
109*404b540aSrobert 
110*404b540aSrobert   /* Or it might contain one of several phrases which indicate C++ code.
111*404b540aSrobert      Currently recognized are:
112*404b540aSrobert      extern "C++"
113*404b540aSrobert      -*- (Mode: )? C++ -*-   (emacs mode marker)
114*404b540aSrobert      template <
115*404b540aSrobert    */
116*404b540aSrobert     {
117*404b540aSrobert       tSCC cxxpat[] = "\
118*404b540aSrobert extern[ \t]*\"C\\+\\+\"|\
119*404b540aSrobert -\\*-[ \t]*([mM]ode:[ \t]*)?[cC]\\+\\+[; \t]*-\\*-|\
120*404b540aSrobert template[ \t]*<|\
121*404b540aSrobert ^[ \t]*class[ \t]|\
122*404b540aSrobert (public|private|protected):|\
123*404b540aSrobert ^[ \t]*#[ \t]*pragma[ \t]+(interface|implementation)\
124*404b540aSrobert ";
125*404b540aSrobert       static regex_t cxxre;
126*404b540aSrobert       static int compiled;
127*404b540aSrobert 
128*404b540aSrobert       if (!compiled)
129*404b540aSrobert 	compile_re (cxxpat, &cxxre, 0, "contents check", "is_cxx_header");
130*404b540aSrobert 
131*404b540aSrobert       if (xregexec (&cxxre, text, 0, 0, 0) == 0)
132*404b540aSrobert 	return BOOL_TRUE;
133*404b540aSrobert     }
134*404b540aSrobert 
135*404b540aSrobert   return BOOL_FALSE;
136*404b540aSrobert }
137*404b540aSrobert #endif /* CXX_TYPE_NEEDED */
138*404b540aSrobert 
139*404b540aSrobert #ifdef SKIP_QUOTE_NEEDED
140*404b540aSrobert /*
141*404b540aSrobert  *  Skip over a quoted string.  Single quote strings may
142*404b540aSrobert  *  contain multiple characters if the first character is
143*404b540aSrobert  *  a backslash.  Especially a backslash followed by octal digits.
144*404b540aSrobert  *  We are not doing a correctness syntax check here.
145*404b540aSrobert  */
146*404b540aSrobert tCC*
skip_quote(char q,char * text)147*404b540aSrobert skip_quote(char q, char* text )
148*404b540aSrobert {
149*404b540aSrobert   for (;;)
150*404b540aSrobert     {
151*404b540aSrobert       char ch = *(text++);
152*404b540aSrobert       switch (ch)
153*404b540aSrobert         {
154*404b540aSrobert         case '\\':
155*404b540aSrobert           text++; /* skip over whatever character follows */
156*404b540aSrobert           break;
157*404b540aSrobert 
158*404b540aSrobert         case '"':
159*404b540aSrobert         case '\'':
160*404b540aSrobert           if (ch != q)
161*404b540aSrobert             break;
162*404b540aSrobert           /*FALLTHROUGH*/
163*404b540aSrobert 
164*404b540aSrobert         case '\n':
165*404b540aSrobert         case NUL:
166*404b540aSrobert           goto skip_done;
167*404b540aSrobert         }
168*404b540aSrobert     } skip_done:;
169*404b540aSrobert 
170*404b540aSrobert   return text;
171*404b540aSrobert }
172*404b540aSrobert #endif /* SKIP_QUOTE_NEEDED */
173*404b540aSrobert 
174*404b540aSrobert /* * * * * * * * * * * * *
175*404b540aSrobert 
176*404b540aSrobert    Compile one regular expression pattern for later use.  PAT contains
177*404b540aSrobert    the pattern, RE points to a regex_t structure (which should have
178*404b540aSrobert    been bzeroed).  MATCH is 1 if we need to know where the regex
179*404b540aSrobert    matched, 0 if not. If xregcomp fails, prints an error message and
180*404b540aSrobert    aborts; E1 and E2 are strings to shove into the error message.
181*404b540aSrobert 
182*404b540aSrobert    The patterns we search for are all egrep patterns.
183*404b540aSrobert    REG_EXTENDED|REG_NEWLINE produces identical regex syntax/semantics
184*404b540aSrobert    to egrep (verified from 4.4BSD Programmer's Reference Manual).  */
185*404b540aSrobert void
compile_re(tCC * pat,regex_t * re,int match,tCC * e1,tCC * e2)186*404b540aSrobert compile_re( tCC* pat, regex_t* re, int match, tCC* e1, tCC* e2 )
187*404b540aSrobert {
188*404b540aSrobert   tSCC z_bad_comp[] = "fixincl ERROR:  cannot compile %s regex for %s\n\
189*404b540aSrobert \texpr = `%s'\n\terror %s\n";
190*404b540aSrobert   int flags, err;
191*404b540aSrobert 
192*404b540aSrobert   flags = (match ? REG_EXTENDED|REG_NEWLINE
193*404b540aSrobert 	   : REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
194*404b540aSrobert   err = xregcomp (re, pat, flags);
195*404b540aSrobert 
196*404b540aSrobert   if (err)
197*404b540aSrobert     {
198*404b540aSrobert       char rerrbuf[1024];
199*404b540aSrobert       regerror (err, re, rerrbuf, 1024);
200*404b540aSrobert       fprintf (stderr, z_bad_comp, e1, e2, pat, rerrbuf);
201*404b540aSrobert       exit (EXIT_FAILURE);
202*404b540aSrobert     }
203*404b540aSrobert }
204*404b540aSrobert 
205*404b540aSrobert /* * * * * * * * * * * * *
206*404b540aSrobert 
207*404b540aSrobert    Helper routine and data for the machine_name test and fix.  */
208*404b540aSrobert 
209*404b540aSrobert tSCC mn_label_pat[] = "^[ \t]*#[ \t]*(if|ifdef|ifndef)[ \t]+";
210*404b540aSrobert static regex_t mn_label_re;
211*404b540aSrobert static regex_t mn_name_re;
212*404b540aSrobert 
213*404b540aSrobert static int mn_compiled = 0;
214*404b540aSrobert 
215*404b540aSrobert t_bool
mn_get_regexps(regex_t ** label_re,regex_t ** name_re,tCC * who)216*404b540aSrobert mn_get_regexps(regex_t** label_re, regex_t** name_re, tCC* who )
217*404b540aSrobert {
218*404b540aSrobert   if (! pz_mn_name_pat)
219*404b540aSrobert     return BOOL_FALSE;
220*404b540aSrobert 
221*404b540aSrobert   if (! mn_compiled)
222*404b540aSrobert     {
223*404b540aSrobert       compile_re (mn_label_pat, &mn_label_re, 1, "label pattern", who);
224*404b540aSrobert       compile_re (pz_mn_name_pat, &mn_name_re, 1, "name pattern", who);
225*404b540aSrobert       mn_compiled++;
226*404b540aSrobert     }
227*404b540aSrobert   *label_re = &mn_label_re;
228*404b540aSrobert   *name_re = &mn_name_re;
229*404b540aSrobert   return BOOL_TRUE;
230*404b540aSrobert }
231*404b540aSrobert 
232*404b540aSrobert 
233*404b540aSrobert #ifdef SEPARATE_FIX_PROC
234*404b540aSrobert 
235*404b540aSrobert char*
make_raw_shell_str(char * pz_d,tCC * pz_s,size_t smax)236*404b540aSrobert make_raw_shell_str( char* pz_d, tCC* pz_s, size_t smax )
237*404b540aSrobert {
238*404b540aSrobert   tSCC zQ[] = "'\\''";
239*404b540aSrobert   size_t     dtaSize;
240*404b540aSrobert   char*      pz_d_start = pz_d;
241*404b540aSrobert 
242*404b540aSrobert   smax--; /* adjust for trailing NUL */
243*404b540aSrobert 
244*404b540aSrobert   dtaSize = strlen( pz_s ) + 3;
245*404b540aSrobert 
246*404b540aSrobert   {
247*404b540aSrobert     const char* pz = pz_s - 1;
248*404b540aSrobert 
249*404b540aSrobert     for (;;) {
250*404b540aSrobert       pz = strchr( pz+1, '\'' );
251*404b540aSrobert       if (pz == (char*)NULL)
252*404b540aSrobert         break;
253*404b540aSrobert       dtaSize += sizeof( zQ )-1;
254*404b540aSrobert     }
255*404b540aSrobert   }
256*404b540aSrobert   if (dtaSize > smax)
257*404b540aSrobert     return (char*)NULL;
258*404b540aSrobert 
259*404b540aSrobert   *(pz_d++) = '\'';
260*404b540aSrobert 
261*404b540aSrobert   for (;;) {
262*404b540aSrobert     if (pz_d - pz_d_start >= smax)
263*404b540aSrobert       return (char*)NULL;
264*404b540aSrobert     switch (*(pz_d++) = *(pz_s++)) {
265*404b540aSrobert     case NUL:
266*404b540aSrobert       goto loopDone;
267*404b540aSrobert 
268*404b540aSrobert     case '\'':
269*404b540aSrobert       if (pz_d - pz_d_start >= smax - sizeof( zQ )-1)
270*404b540aSrobert 	return (char*)NULL;
271*404b540aSrobert       strcpy( pz_d-1, zQ );
272*404b540aSrobert       pz_d += sizeof( zQ )-2;
273*404b540aSrobert     }
274*404b540aSrobert   } loopDone:;
275*404b540aSrobert   pz_d[-1] = '\'';
276*404b540aSrobert   *pz_d    = NUL;
277*404b540aSrobert 
278*404b540aSrobert   return pz_d;
279*404b540aSrobert }
280*404b540aSrobert 
281*404b540aSrobert #endif
282