14fee23f9Smrg
24fee23f9Smrg /* Install modified versions of certain ANSI-incompatible system header
34fee23f9Smrg files which are fixed to work correctly with ANSI C and placed in a
44fee23f9Smrg directory that GCC will search.
54fee23f9Smrg
64fee23f9Smrg Copyright (C) 1999, 2000, 2001, 2004, 2009 Free Software Foundation, Inc.
74fee23f9Smrg
84fee23f9Smrg This file is part of GCC.
94fee23f9Smrg
104fee23f9Smrg GCC is free software; you can redistribute it and/or modify
114fee23f9Smrg it under the terms of the GNU General Public License as published by
124fee23f9Smrg the Free Software Foundation; either version 3, or (at your option)
134fee23f9Smrg any later version.
144fee23f9Smrg
154fee23f9Smrg GCC is distributed in the hope that it will be useful,
164fee23f9Smrg but WITHOUT ANY WARRANTY; without even the implied warranty of
174fee23f9Smrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
184fee23f9Smrg GNU General Public License for more details.
194fee23f9Smrg
204fee23f9Smrg You should have received a copy of the GNU General Public License
214fee23f9Smrg along with GCC; see the file COPYING3. If not see
224fee23f9Smrg <http://www.gnu.org/licenses/>. */
234fee23f9Smrg
244fee23f9Smrg #include "fixlib.h"
254fee23f9Smrg
264fee23f9Smrg /* * * * * * * * * * * * *
274fee23f9Smrg
284fee23f9Smrg load_file_data loads all the contents of a file into malloc-ed memory.
294fee23f9Smrg Its argument is the file pointer of the file to read in; the returned
304fee23f9Smrg result is the NUL terminated contents of the file. The file
314fee23f9Smrg is presumed to be an ASCII text file containing no NULs. */
324fee23f9Smrg
334fee23f9Smrg char *
load_file_data(FILE * fp)344fee23f9Smrg load_file_data (FILE* fp)
354fee23f9Smrg {
364fee23f9Smrg char *pz_data = (char*)NULL;
374fee23f9Smrg int space_left = -1; /* allow for terminating NUL */
384fee23f9Smrg size_t space_used = 0;
394fee23f9Smrg
404fee23f9Smrg if (fp == (FILE*)NULL)
414fee23f9Smrg return pz_data;
424fee23f9Smrg
434fee23f9Smrg do
444fee23f9Smrg {
454fee23f9Smrg size_t size_read;
464fee23f9Smrg
474fee23f9Smrg if (space_left < 1024)
484fee23f9Smrg {
494fee23f9Smrg space_left += 4096;
504fee23f9Smrg pz_data = XRESIZEVEC (char, pz_data, space_left + space_used + 1 );
514fee23f9Smrg }
524fee23f9Smrg size_read = fread (pz_data + space_used, 1, space_left, fp);
534fee23f9Smrg
544fee23f9Smrg if (size_read == 0)
554fee23f9Smrg {
564fee23f9Smrg if (feof (fp))
574fee23f9Smrg break;
584fee23f9Smrg
594fee23f9Smrg if (ferror (fp))
604fee23f9Smrg {
614fee23f9Smrg int err = errno;
624fee23f9Smrg if (err != EISDIR)
634fee23f9Smrg fprintf (stderr, "error %d (%s) reading input\n", err,
644fee23f9Smrg xstrerror (err));
654fee23f9Smrg free ((void *) pz_data);
664fee23f9Smrg return (char *) NULL;
674fee23f9Smrg }
684fee23f9Smrg }
694fee23f9Smrg
704fee23f9Smrg space_left -= size_read;
714fee23f9Smrg space_used += size_read;
724fee23f9Smrg } while (! feof (fp));
734fee23f9Smrg
744fee23f9Smrg pz_data = XRESIZEVEC (char, pz_data, space_used+1 );
754fee23f9Smrg pz_data[ space_used ] = NUL;
764fee23f9Smrg
774fee23f9Smrg return pz_data;
784fee23f9Smrg }
794fee23f9Smrg
804fee23f9Smrg #ifdef IS_CXX_HEADER_NEEDED
814fee23f9Smrg t_bool
is_cxx_header(tCC * fname,tCC * text)824fee23f9Smrg is_cxx_header (tCC* fname, tCC* text)
834fee23f9Smrg {
844fee23f9Smrg /* First, check to see if the file is in a C++ directory */
854fee23f9Smrg for (;;)
864fee23f9Smrg {
874fee23f9Smrg switch (*(fname++))
884fee23f9Smrg {
894fee23f9Smrg case 'C': /* check for "CC/" */
904fee23f9Smrg if ((fname[0] == 'C') && (fname[1] == '/'))
914fee23f9Smrg return BOOL_TRUE;
924fee23f9Smrg break;
934fee23f9Smrg
944fee23f9Smrg case 'x': /* check for "xx/" */
954fee23f9Smrg if ((fname[0] == 'x') && (fname[1] == '/'))
964fee23f9Smrg return BOOL_TRUE;
974fee23f9Smrg break;
984fee23f9Smrg
994fee23f9Smrg case '+': /* check for "++" */
1004fee23f9Smrg if (fname[0] == '+')
1014fee23f9Smrg return BOOL_TRUE;
1024fee23f9Smrg break;
1034fee23f9Smrg
1044fee23f9Smrg case NUL:
1054fee23f9Smrg goto not_cxx_name;
1064fee23f9Smrg }
1074fee23f9Smrg } not_cxx_name:;
1084fee23f9Smrg
1094fee23f9Smrg /* Or it might contain one of several phrases which indicate C++ code.
1104fee23f9Smrg Currently recognized are:
1114fee23f9Smrg extern "C++"
1124fee23f9Smrg -*- (Mode: )? C++ -*- (emacs mode marker)
1134fee23f9Smrg template <
1144fee23f9Smrg */
1154fee23f9Smrg {
1164fee23f9Smrg tSCC cxxpat[] = "\
1174fee23f9Smrg extern[ \t]*\"C\\+\\+\"|\
1184fee23f9Smrg -\\*-[ \t]*([mM]ode:[ \t]*)?[cC]\\+\\+[; \t]*-\\*-|\
1194fee23f9Smrg template[ \t]*<|\
1204fee23f9Smrg ^[ \t]*class[ \t]|\
1214fee23f9Smrg (public|private|protected):|\
1224fee23f9Smrg ^[ \t]*#[ \t]*pragma[ \t]+(interface|implementation)\
1234fee23f9Smrg ";
1244fee23f9Smrg static regex_t cxxre;
1254fee23f9Smrg static int compiled;
1264fee23f9Smrg
1274fee23f9Smrg if (!compiled)
1284fee23f9Smrg compile_re (cxxpat, &cxxre, 0, "contents check", "is_cxx_header");
1294fee23f9Smrg
1304fee23f9Smrg if (xregexec (&cxxre, text, 0, 0, 0) == 0)
1314fee23f9Smrg return BOOL_TRUE;
1324fee23f9Smrg }
1334fee23f9Smrg
1344fee23f9Smrg return BOOL_FALSE;
1354fee23f9Smrg }
1364fee23f9Smrg #endif /* CXX_TYPE_NEEDED */
1374fee23f9Smrg
1384fee23f9Smrg #ifdef SKIP_QUOTE_NEEDED
1394fee23f9Smrg /*
1404fee23f9Smrg * Skip over a quoted string. Single quote strings may
1414fee23f9Smrg * contain multiple characters if the first character is
1424fee23f9Smrg * a backslash. Especially a backslash followed by octal digits.
1434fee23f9Smrg * We are not doing a correctness syntax check here.
1444fee23f9Smrg */
1454fee23f9Smrg tCC*
skip_quote(char q,char * text)1464fee23f9Smrg skip_quote(char q, char* text )
1474fee23f9Smrg {
1484fee23f9Smrg for (;;)
1494fee23f9Smrg {
1504fee23f9Smrg char ch = *(text++);
1514fee23f9Smrg switch (ch)
1524fee23f9Smrg {
1534fee23f9Smrg case '\\':
1544fee23f9Smrg text++; /* skip over whatever character follows */
1554fee23f9Smrg break;
1564fee23f9Smrg
1574fee23f9Smrg case '"':
1584fee23f9Smrg case '\'':
1594fee23f9Smrg if (ch != q)
1604fee23f9Smrg break;
1614fee23f9Smrg /*FALLTHROUGH*/
1624fee23f9Smrg
1634fee23f9Smrg case '\n':
1644fee23f9Smrg case NUL:
1654fee23f9Smrg goto skip_done;
1664fee23f9Smrg }
1674fee23f9Smrg } skip_done:;
1684fee23f9Smrg
1694fee23f9Smrg return text;
1704fee23f9Smrg }
1714fee23f9Smrg #endif /* SKIP_QUOTE_NEEDED */
1724fee23f9Smrg
1734fee23f9Smrg /* * * * * * * * * * * * *
1744fee23f9Smrg
1754fee23f9Smrg Compile one regular expression pattern for later use. PAT contains
1764fee23f9Smrg the pattern, RE points to a regex_t structure (which should have
1774fee23f9Smrg been bzeroed). MATCH is 1 if we need to know where the regex
1784fee23f9Smrg matched, 0 if not. If xregcomp fails, prints an error message and
1794fee23f9Smrg aborts; E1 and E2 are strings to shove into the error message.
1804fee23f9Smrg
1814fee23f9Smrg The patterns we search for are all egrep patterns.
1824fee23f9Smrg REG_EXTENDED|REG_NEWLINE produces identical regex syntax/semantics
1834fee23f9Smrg to egrep (verified from 4.4BSD Programmer's Reference Manual). */
1844fee23f9Smrg void
compile_re(tCC * pat,regex_t * re,int match,tCC * e1,tCC * e2)1854fee23f9Smrg compile_re( tCC* pat, regex_t* re, int match, tCC* e1, tCC* e2 )
1864fee23f9Smrg {
1874fee23f9Smrg tSCC z_bad_comp[] = "fixincl ERROR: cannot compile %s regex for %s\n\
1884fee23f9Smrg \texpr = `%s'\n\terror %s\n";
1894fee23f9Smrg int flags, err;
1904fee23f9Smrg
1914fee23f9Smrg flags = (match ? REG_EXTENDED|REG_NEWLINE
1924fee23f9Smrg : REG_EXTENDED|REG_NEWLINE|REG_NOSUB);
1934fee23f9Smrg err = xregcomp (re, pat, flags);
1944fee23f9Smrg
1954fee23f9Smrg if (err)
1964fee23f9Smrg {
1974fee23f9Smrg char rerrbuf[1024];
1984fee23f9Smrg regerror (err, re, rerrbuf, 1024);
1994fee23f9Smrg fprintf (stderr, z_bad_comp, e1, e2, pat, rerrbuf);
2004fee23f9Smrg exit (EXIT_FAILURE);
2014fee23f9Smrg }
2024fee23f9Smrg }
2034fee23f9Smrg
2044fee23f9Smrg /* * * * * * * * * * * * *
2054fee23f9Smrg
2064fee23f9Smrg Helper routine and data for the machine_name test and fix. */
2074fee23f9Smrg
2084fee23f9Smrg tSCC mn_label_pat[] = "^[ \t]*#[ \t]*(if|ifdef|ifndef)[ \t]+";
2094fee23f9Smrg static regex_t mn_label_re;
2104fee23f9Smrg static regex_t mn_name_re;
2114fee23f9Smrg
2124fee23f9Smrg static int mn_compiled = 0;
2134fee23f9Smrg
2144fee23f9Smrg t_bool
mn_get_regexps(regex_t ** label_re,regex_t ** name_re,tCC * who)2154fee23f9Smrg mn_get_regexps(regex_t** label_re, regex_t** name_re, tCC* who )
2164fee23f9Smrg {
2174fee23f9Smrg if (! pz_mn_name_pat)
2184fee23f9Smrg return BOOL_FALSE;
2194fee23f9Smrg
2204fee23f9Smrg if (! mn_compiled)
2214fee23f9Smrg {
2224fee23f9Smrg compile_re (mn_label_pat, &mn_label_re, 1, "label pattern", who);
2234fee23f9Smrg compile_re (pz_mn_name_pat, &mn_name_re, 1, "name pattern", who);
2244fee23f9Smrg mn_compiled++;
2254fee23f9Smrg }
2264fee23f9Smrg *label_re = &mn_label_re;
2274fee23f9Smrg *name_re = &mn_name_re;
2284fee23f9Smrg return BOOL_TRUE;
2294fee23f9Smrg }
2304fee23f9Smrg
2314fee23f9Smrg
2324fee23f9Smrg #ifdef SEPARATE_FIX_PROC
2334fee23f9Smrg
2344fee23f9Smrg char*
make_raw_shell_str(char * pz_d,tCC * pz_s,size_t smax)2354fee23f9Smrg make_raw_shell_str( char* pz_d, tCC* pz_s, size_t smax )
2364fee23f9Smrg {
2374fee23f9Smrg tSCC zQ[] = "'\\''";
2384fee23f9Smrg size_t dtaSize;
2394fee23f9Smrg char* pz_d_start = pz_d;
2404fee23f9Smrg
2414fee23f9Smrg smax--; /* adjust for trailing NUL */
2424fee23f9Smrg
2434fee23f9Smrg dtaSize = strlen( pz_s ) + 3;
2444fee23f9Smrg
2454fee23f9Smrg {
2464fee23f9Smrg const char* pz = pz_s - 1;
2474fee23f9Smrg
2484fee23f9Smrg for (;;) {
2494fee23f9Smrg pz = strchr( pz+1, '\'' );
2504fee23f9Smrg if (pz == (char*)NULL)
2514fee23f9Smrg break;
2524fee23f9Smrg dtaSize += sizeof( zQ )-1;
2534fee23f9Smrg }
2544fee23f9Smrg }
2554fee23f9Smrg if (dtaSize > smax)
2564fee23f9Smrg return (char*)NULL;
2574fee23f9Smrg
2584fee23f9Smrg *(pz_d++) = '\'';
2594fee23f9Smrg
2604fee23f9Smrg for (;;) {
2614fee23f9Smrg if ((size_t) (pz_d - pz_d_start) >= smax)
2624fee23f9Smrg return (char*)NULL;
2634fee23f9Smrg switch (*(pz_d++) = *(pz_s++)) {
2644fee23f9Smrg case NUL:
2654fee23f9Smrg goto loopDone;
2664fee23f9Smrg
2674fee23f9Smrg case '\'':
2684fee23f9Smrg if ((size_t) (pz_d - pz_d_start) >= smax - sizeof( zQ )-1)
2694fee23f9Smrg return (char*)NULL;
2704fee23f9Smrg strcpy( pz_d-1, zQ );
2714fee23f9Smrg pz_d += sizeof( zQ )-2;
2724fee23f9Smrg }
2734fee23f9Smrg } loopDone:;
2744fee23f9Smrg pz_d[-1] = '\'';
2754fee23f9Smrg *pz_d = NUL;
2764fee23f9Smrg
2774fee23f9Smrg return pz_d;
2784fee23f9Smrg }
2794fee23f9Smrg
2804fee23f9Smrg #endif
281*b17d1066Smrg
282*b17d1066Smrg #if defined(__MINGW32__)
283*b17d1066Smrg void
fix_path_separators(char * p)284*b17d1066Smrg fix_path_separators (char* p)
285*b17d1066Smrg {
286*b17d1066Smrg while (p != NULL)
287*b17d1066Smrg {
288*b17d1066Smrg p = strchr (p, '\\');
289*b17d1066Smrg if (p != NULL)
290*b17d1066Smrg {
291*b17d1066Smrg *p = '/';
292*b17d1066Smrg ++p;
293*b17d1066Smrg }
294*b17d1066Smrg }
295*b17d1066Smrg }
296*b17d1066Smrg
297*b17d1066Smrg /* Count number of needle character ocurrences in str */
298*b17d1066Smrg static int
count_occurrences_of_char(char * str,char needle)299*b17d1066Smrg count_occurrences_of_char (char* str, char needle)
300*b17d1066Smrg {
301*b17d1066Smrg int cnt = 0;
302*b17d1066Smrg
303*b17d1066Smrg while (str)
304*b17d1066Smrg {
305*b17d1066Smrg str = strchr (str, needle);
306*b17d1066Smrg if (str)
307*b17d1066Smrg {
308*b17d1066Smrg ++str;
309*b17d1066Smrg ++cnt;
310*b17d1066Smrg }
311*b17d1066Smrg }
312*b17d1066Smrg
313*b17d1066Smrg return cnt;
314*b17d1066Smrg }
315*b17d1066Smrg
316*b17d1066Smrg /* On Mingw32, system function will just start cmd by default.
317*b17d1066Smrg Call system function, but prepend ${CONFIG_SHELL} or ${SHELL} -c to the command,
318*b17d1066Smrg replace newlines with '$'\n'', enclose command with double quotes
319*b17d1066Smrg and escape special characters which were originally enclosed in single quotes.
320*b17d1066Smrg */
321*b17d1066Smrg int
system_with_shell(char * s)322*b17d1066Smrg system_with_shell (char* s)
323*b17d1066Smrg {
324*b17d1066Smrg static const char z_shell_start_args[] = " -c \"";
325*b17d1066Smrg static const char z_shell_end_args[] = "\"";
326*b17d1066Smrg static const char z_shell_newline[] = "'$'\\n''";
327*b17d1066Smrg
328*b17d1066Smrg /* Use configured shell if present */
329*b17d1066Smrg char *env_shell = getenv ("CONFIG_SHELL");
330*b17d1066Smrg int newline_cnt = count_occurrences_of_char (s, '\n');
331*b17d1066Smrg int escapes_cnt = count_occurrences_of_char( s, '\\')
332*b17d1066Smrg + count_occurrences_of_char (s, '"')
333*b17d1066Smrg + count_occurrences_of_char (s, '`');
334*b17d1066Smrg char *long_cmd;
335*b17d1066Smrg char *cmd_endp;
336*b17d1066Smrg int sys_result;
337*b17d1066Smrg char *s_scan;
338*b17d1066Smrg int in_quotes;
339*b17d1066Smrg
340*b17d1066Smrg if (env_shell == NULL)
341*b17d1066Smrg env_shell = getenv ("SHELL");
342*b17d1066Smrg
343*b17d1066Smrg /* If neither CONFIGURED_SHELL nor SHELL is set, just call standard system function */
344*b17d1066Smrg if (env_shell == NULL)
345*b17d1066Smrg return system (s);
346*b17d1066Smrg
347*b17d1066Smrg /* Allocate enough memory to fit newly created command string */
348*b17d1066Smrg long_cmd = XNEWVEC (char, strlen (env_shell)
349*b17d1066Smrg + strlen (z_shell_start_args)
350*b17d1066Smrg + strlen (s)
351*b17d1066Smrg + newline_cnt * (strlen (z_shell_newline) - 1)
352*b17d1066Smrg + escapes_cnt
353*b17d1066Smrg + strlen (z_shell_end_args)
354*b17d1066Smrg + 1);
355*b17d1066Smrg
356*b17d1066Smrg /* Start with ${SHELL} */
357*b17d1066Smrg strcpy (long_cmd, env_shell);
358*b17d1066Smrg cmd_endp = long_cmd + strlen (long_cmd);
359*b17d1066Smrg
360*b17d1066Smrg /* Opening quote */
361*b17d1066Smrg strcpy (cmd_endp, z_shell_start_args);
362*b17d1066Smrg cmd_endp += strlen (z_shell_start_args);
363*b17d1066Smrg
364*b17d1066Smrg /* Replace newlines and escape special chars */
365*b17d1066Smrg in_quotes = 0;
366*b17d1066Smrg for (s_scan = s; *s_scan; ++s_scan)
367*b17d1066Smrg {
368*b17d1066Smrg switch (*s_scan)
369*b17d1066Smrg {
370*b17d1066Smrg case '\n':
371*b17d1066Smrg if (in_quotes)
372*b17d1066Smrg {
373*b17d1066Smrg /* Replace newline inside quotes with '$'\n'' */
374*b17d1066Smrg strcpy (cmd_endp, z_shell_newline);
375*b17d1066Smrg cmd_endp += strlen (z_shell_newline);
376*b17d1066Smrg }
377*b17d1066Smrg else
378*b17d1066Smrg {
379*b17d1066Smrg /* Replace newlines outside quotes with ; and merge subsequent newlines */
380*b17d1066Smrg *(cmd_endp++) = ';';
381*b17d1066Smrg *(cmd_endp++) = ' ';
382*b17d1066Smrg while (*(s_scan + 1) == '\n' || *(s_scan + 1) == ' ' || *(s_scan + 1) == '\t')
383*b17d1066Smrg ++s_scan;
384*b17d1066Smrg }
385*b17d1066Smrg break;
386*b17d1066Smrg case '\'':
387*b17d1066Smrg /* Escape single quote and toggle in_quotes flag */
388*b17d1066Smrg in_quotes = !in_quotes;
389*b17d1066Smrg *(cmd_endp++) = *s_scan;
390*b17d1066Smrg break;
391*b17d1066Smrg case '\\':
392*b17d1066Smrg case '`':
393*b17d1066Smrg /* Escape backslash and backtick inside quotes */
394*b17d1066Smrg if (in_quotes)
395*b17d1066Smrg *(cmd_endp++) = '\\';
396*b17d1066Smrg *(cmd_endp++) = *s_scan;
397*b17d1066Smrg break;
398*b17d1066Smrg case '"':
399*b17d1066Smrg /* Escape double quotes always */
400*b17d1066Smrg *(cmd_endp++) = '\\';
401*b17d1066Smrg *(cmd_endp++) = *s_scan;
402*b17d1066Smrg break;
403*b17d1066Smrg default:
404*b17d1066Smrg *(cmd_endp++) = *s_scan;
405*b17d1066Smrg }
406*b17d1066Smrg }
407*b17d1066Smrg
408*b17d1066Smrg /* Closing quote */
409*b17d1066Smrg strcpy (cmd_endp, z_shell_end_args);
410*b17d1066Smrg
411*b17d1066Smrg sys_result = system (long_cmd);
412*b17d1066Smrg
413*b17d1066Smrg free (long_cmd);
414*b17d1066Smrg
415*b17d1066Smrg return sys_result;
416*b17d1066Smrg }
417*b17d1066Smrg
418*b17d1066Smrg #endif /* defined(__MINGW32__) */
419