xref: /netbsd-src/external/gpl3/gcc/dist/fixincludes/fixlib.c (revision b17d1066a7e7247cfc01a45f6ada19302e1cc150)
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