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 8This file is part of GCC. 9 10GCC is free software; you can redistribute it and/or modify 11it under the terms of the GNU General Public License as published by 12the Free Software Foundation; either version 2, or (at your option) 13any later version. 14 15GCC is distributed in the hope that it will be useful, 16but WITHOUT ANY WARRANTY; without even the implied warranty of 17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18GNU General Public License for more details. 19 20You should have received a copy of the GNU General Public License 21along with GCC; see the file COPYING. If not, write to 22the Free Software Foundation, 51 Franklin Street, Fifth Floor, 23Boston, 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 34char * 35load_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 82t_bool 83is_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[] = "\ 118extern[ \t]*\"C\\+\\+\"|\ 119-\\*-[ \t]*([mM]ode:[ \t]*)?[cC]\\+\\+[; \t]*-\\*-|\ 120template[ \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 */ 146tCC* 147skip_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). */ 185void 186compile_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 209tSCC mn_label_pat[] = "^[ \t]*#[ \t]*(if|ifdef|ifndef)[ \t]+"; 210static regex_t mn_label_re; 211static regex_t mn_name_re; 212 213static int mn_compiled = 0; 214 215t_bool 216mn_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 235char* 236make_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