xref: /freebsd-12.1/contrib/gcc/cppspec.c (revision ca6500fc)
1 /* Specific flags and argument handling of the C preprocessor.
2    Copyright (C) 1999 Free Software Foundation, Inc.
3 
4 This file is part of GCC.
5 
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10 
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20 
21 #include "config.h"
22 #include "system.h"
23 #include "gcc.h"
24 
25 /* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
26    is a customized version of the gcc driver.  It forces -E; -S and -c
27    are errors.  It defaults to -x c for files with unrecognized
28    extensions, unless -x options appear in argv, in which case we
29    assume the user knows what they're doing.  If no explicit input is
30    mentioned, it will read stdin.  */
31 
32 /* Snarfed from gcc.c: */
33 
34 /* This defines which switch letters take arguments.  */
35 
36 #define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
37   ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
38    || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
39    || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
40    || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
41    || (CHAR) == 'B' || (CHAR) == 'b')
42 
43 #ifndef SWITCH_TAKES_ARG
44 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
45 #endif
46 
47 /* This defines which multi-letter switches take arguments.  */
48 
49 #define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)		\
50  (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")	\
51   || !strcmp (STR, "Tbss") || !strcmp (STR, "include")	\
52   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
53   || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
54   || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
55   || !strcmp (STR, "isystem") || !strcmp (STR, "specs") \
56   || !strcmp (STR, "MF") || !strcmp (STR, "MT") || !strcmp (STR, "MQ"))
57 
58 #ifndef WORD_SWITCH_TAKES_ARG
59 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
60 #endif
61 
62 /* Suffixes for known sorts of input files.  Note that we do not list
63    files which are normally considered to have been preprocessed already,
64    since the user's expectation is that `cpp' always preprocesses.  */
65 static const char *const known_suffixes[] =
66 {
67   ".c",  ".C",   ".S",   ".m",
68   ".cc", ".cxx", ".cpp", ".cp",  ".c++",
69   NULL
70 };
71 
72 /* Filter argc and argv before processing by the gcc driver proper.  */
73 void
74 lang_specific_driver (in_argc, in_argv, in_added_libraries)
75      int *in_argc;
76      const char *const **in_argv;
77      int *in_added_libraries ATTRIBUTE_UNUSED;
78 {
79   int argc = *in_argc;
80   const char *const *argv = *in_argv;
81 
82   /* Do we need to read stdin? */
83   int read_stdin = 1;
84 
85   /* Do we need to insert -E? */
86   int need_E = 1;
87 
88   /* Do we need to insert -no-gcc? */
89   int need_no_gcc = 1;
90 
91   /* Have we seen an input file? */
92   int seen_input = 0;
93 
94   /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
95      0 means unnecessary.  */
96   int lang_c_here = 0;
97   int lang_S_here = 0;
98   int o_here = 0;
99 
100   /* Do we need to fix up an input file with an unrecognized suffix? */
101   int need_fixups = 1;
102 
103   int i, j, quote = 0;
104   const char **new_argv;
105   int new_argc;
106   extern int is_cpp_driver;
107 
108   is_cpp_driver = 1;
109 
110   /* First pass.  If we see an -S or -c, barf.  If we see an input file,
111      turn off read_stdin.  If we see a second input file, it is actually
112      the output file.  If we see a third input file, barf.  */
113   for (i = 1; i < argc; i++)
114     {
115       if (quote == 1)
116 	{
117 	  quote = 0;
118 	  continue;
119 	}
120 
121       if (argv[i][0] == '-')
122 	{
123 	  if (argv[i][1] == '\0')
124 	    read_stdin = 0;
125 	  else if (argv[i][2] == '\0')
126 	    {
127 	      if (argv[i][1] == 'E')
128 		need_E = 0;
129 	      else if (argv[i][1] == 'S' || argv[i][1] == 'c')
130 		{
131 		  fatal ("\"%s\" is not a valid option to the preprocessor",
132 			 argv[i]);
133 		  return;
134 		}
135 	      else if (argv[i][1] == 'x')
136 		{
137 		  need_fixups = 0;
138 		  quote = 1;
139 		}
140 	      else if (SWITCH_TAKES_ARG (argv[i][1]))
141 		quote = 1;
142 	    }
143 	  else if (argv[i][1] == 'x')
144 	    need_fixups = 0;
145 	  else if (argv[i][1] == 'g' && !strcmp(&argv[i][2], "cc"))
146 	    need_no_gcc = 0;
147 	  else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
148 	    quote = 1;
149 	}
150       else /* not an option */
151 	{
152 	  seen_input++;
153 	  if (seen_input == 3)
154 	    {
155 	      fatal ("too many input files");
156 	      return;
157 	    }
158 	  else if (seen_input == 2)
159 	    {
160 	      o_here = i;
161 	    }
162 	  else
163 	    {
164 	      read_stdin = 0;
165 	      if (need_fixups)
166 		{
167 		  int l = strlen (argv[i]);
168 		  int known = 0;
169 		  const char *const *suff;
170 
171 		  for (suff = known_suffixes; *suff; suff++)
172 		    if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
173 		      {
174 			known = 1;
175 			break;
176 		      }
177 
178 		  if (! known)
179 		    {
180 		      /* .s files are a special case; we have to treat
181 			 them like .S files so -D__ASSEMBLER__ will be
182 			 in effect.  */
183 		      if (!strcmp (".s", &argv[i][l - 2]))
184 			lang_S_here = i;
185 		      else
186 			lang_c_here = i;
187 		    }
188 		}
189 	    }
190 	}
191     }
192 
193   /* If we don't need to edit the command line, we can bail early.  */
194 
195   new_argc = argc + need_E + need_no_gcc + read_stdin
196     + !!o_here + !!lang_c_here + !!lang_S_here;
197 
198   if (new_argc == argc)
199     return;
200 
201   /* One more slot for a terminating null.  */
202   new_argv = (const char **) xmalloc ((new_argc + 1) * sizeof(char *));
203 
204   new_argv[0] = argv[0];
205   j = 1;
206 
207   if (need_E)
208     new_argv[j++] = "-E";
209 
210   if (need_no_gcc)
211     new_argv[j++] = "-no-gcc";
212 
213   for (i = 1; i < argc; i++, j++)
214     {
215       if (i == lang_c_here)
216 	new_argv[j++] = "-xc";
217       else if (i == lang_S_here)
218 	new_argv[j++] = "-xassembler-with-cpp";
219       else if (i == o_here)
220 	new_argv[j++] = "-o";
221 
222       new_argv[j] = argv[i];
223     }
224 
225   if (read_stdin)
226     new_argv[j++] = "-";
227 
228   new_argv[j] = NULL;
229   *in_argc = new_argc;
230   *in_argv = new_argv;
231 }
232 
233 /* Called before linking.  Returns 0 on success and -1 on failure.  */
234 int lang_specific_pre_link ()
235 {
236   return 0;  /* Not used for cpp.  */
237 }
238 
239 /* Number of extra output files that lang_specific_pre_link may generate.  */
240 int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
241