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