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