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 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, 59 Temple Place - Suite 330, 23Boston, MA 02111-1307, 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 = xrealloc (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 = xrealloc (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 machname.h is created by black magic in the Makefile. */ 209 210#ifdef MN_NAME_PAT 211 212tSCC mn_label_pat[] = "^[ \t]*#[ \t]*(if|ifdef|ifndef)[ \t]+"; 213static regex_t mn_label_re; 214 215tSCC mn_name_pat[] = MN_NAME_PAT; 216static regex_t mn_name_re; 217 218static int mn_compiled = 0; 219 220void 221mn_get_regexps(regex_t** label_re, regex_t** name_re, tCC* who ) 222{ 223 if (! mn_compiled) 224 { 225 compile_re (mn_label_pat, &mn_label_re, 1, "label pattern", who); 226 compile_re (mn_name_pat, &mn_name_re, 1, "name pattern", who); 227 mn_compiled++; 228 } 229 *label_re = &mn_label_re; 230 *name_re = &mn_name_re; 231} 232#endif 233 234 235#ifdef SEPARATE_FIX_PROC 236 237char* 238make_raw_shell_str( char* pz_d, tCC* pz_s, size_t smax ) 239{ 240 tSCC zQ[] = "'\\''"; 241 size_t dtaSize; 242 char* pz_d_start = pz_d; 243 244 smax--; /* adjust for trailing NUL */ 245 246 dtaSize = strlen( pz_s ) + 3; 247 248 { 249 const char* pz = pz_s - 1; 250 251 for (;;) { 252 pz = strchr( pz+1, '\'' ); 253 if (pz == (char*)NULL) 254 break; 255 dtaSize += sizeof( zQ )-1; 256 } 257 } 258 if (dtaSize > smax) 259 return (char*)NULL; 260 261 *(pz_d++) = '\''; 262 263 for (;;) { 264 if (pz_d - pz_d_start >= smax) 265 return (char*)NULL; 266 switch (*(pz_d++) = *(pz_s++)) { 267 case NUL: 268 goto loopDone; 269 270 case '\'': 271 if (pz_d - pz_d_start >= smax - sizeof( zQ )-1) 272 return (char*)NULL; 273 strcpy( pz_d-1, zQ ); 274 pz_d += sizeof( zQ )-2; 275 } 276 } loopDone:; 277 pz_d[-1] = '\''; 278 *pz_d = NUL; 279 280 return pz_d; 281} 282 283#endif 284