xref: /freebsd-12.1/contrib/gcc/cppspec.c (revision a2faa65a)
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 #ifndef SWITCH_TAKES_ARG
33 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
34 #endif
35 
36 #ifndef WORD_SWITCH_TAKES_ARG
37 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
38 #endif
39 
40 /* Suffixes for known sorts of input files.  Note that we do not list
41    files which are normally considered to have been preprocessed already,
42    since the user's expectation is that `cpp' always preprocesses.  */
43 static const char *const known_suffixes[] =
44 {
45   ".c",  ".C",   ".S",   ".m",
46   ".cc", ".cxx", ".cpp", ".cp",  ".c++",
47   NULL
48 };
49 
50 /* Filter argc and argv before processing by the gcc driver proper.  */
51 void
52 lang_specific_driver (in_argc, in_argv, in_added_libraries)
53      int *in_argc;
54      const char *const **in_argv;
55      int *in_added_libraries ATTRIBUTE_UNUSED;
56 {
57   int argc = *in_argc;
58   const char *const *argv = *in_argv;
59 
60   /* Do we need to read stdin? */
61   int read_stdin = 1;
62 
63   /* Do we need to insert -E? */
64   int need_E = 1;
65 
66   /* Do we need to insert -no-gcc? */
67   int need_no_gcc = 1;
68 
69   /* Have we seen an input file? */
70   int seen_input = 0;
71 
72   /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
73      0 means unnecessary.  */
74   int lang_c_here = 0;
75   int lang_S_here = 0;
76   int o_here = 0;
77 
78   /* Do we need to fix up an input file with an unrecognized suffix? */
79   int need_fixups = 1;
80 
81   int i, j, quote = 0;
82   const char **new_argv;
83   int new_argc;
84   extern int is_cpp_driver;
85 
86   is_cpp_driver = 1;
87 
88   /* First pass.  If we see an -S or -c, barf.  If we see an input file,
89      turn off read_stdin.  If we see a second input file, it is actually
90      the output file.  If we see a third input file, barf.  */
91   for (i = 1; i < argc; i++)
92     {
93       if (quote == 1)
94 	{
95 	  quote = 0;
96 	  continue;
97 	}
98 
99       if (argv[i][0] == '-')
100 	{
101 	  if (argv[i][1] == '\0')
102 	    read_stdin = 0;
103 	  else if (argv[i][2] == '\0')
104 	    {
105 	      if (argv[i][1] == 'E')
106 		need_E = 0;
107 	      else if (argv[i][1] == 'S' || argv[i][1] == 'c')
108 		{
109 		  fatal ("\"%s\" is not a valid option to the preprocessor",
110 			 argv[i]);
111 		  return;
112 		}
113 	      else if (argv[i][1] == 'x')
114 		{
115 		  need_fixups = 0;
116 		  quote = 1;
117 		}
118 	      else if (SWITCH_TAKES_ARG (argv[i][1]))
119 		quote = 1;
120 	    }
121 	  else if (argv[i][1] == 'x')
122 	    need_fixups = 0;
123 	  else if (argv[i][1] == 'g' && !strcmp(&argv[i][2], "cc"))
124 	    need_no_gcc = 0;
125 	  else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
126 	    quote = 1;
127 	}
128       else /* not an option */
129 	{
130 	  seen_input++;
131 	  if (seen_input == 3)
132 	    {
133 	      fatal ("too many input files");
134 	      return;
135 	    }
136 	  else if (seen_input == 2)
137 	    {
138 	      o_here = i;
139 	    }
140 	  else
141 	    {
142 	      read_stdin = 0;
143 	      if (need_fixups)
144 		{
145 		  int l = strlen (argv[i]);
146 		  int known = 0;
147 		  const char *const *suff;
148 
149 		  for (suff = known_suffixes; *suff; suff++)
150 		    if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
151 		      {
152 			known = 1;
153 			break;
154 		      }
155 
156 		  if (! known)
157 		    {
158 		      /* .s files are a special case; we have to treat
159 			 them like .S files so -D__ASSEMBLER__ will be
160 			 in effect.  */
161 		      if (!strcmp (".s", &argv[i][l - 2]))
162 			lang_S_here = i;
163 		      else
164 			lang_c_here = i;
165 		    }
166 		}
167 	    }
168 	}
169     }
170 
171   /* If we don't need to edit the command line, we can bail early.  */
172 
173   new_argc = argc + need_E + need_no_gcc + read_stdin
174     + !!o_here + !!lang_c_here + !!lang_S_here;
175 
176   if (new_argc == argc)
177     return;
178 
179   /* One more slot for a terminating null.  */
180   new_argv = (const char **) xmalloc ((new_argc + 1) * sizeof(char *));
181 
182   new_argv[0] = argv[0];
183   j = 1;
184 
185   if (need_E)
186     new_argv[j++] = "-E";
187 
188   if (need_no_gcc)
189     new_argv[j++] = "-no-gcc";
190 
191   for (i = 1; i < argc; i++, j++)
192     {
193       if (i == lang_c_here)
194 	new_argv[j++] = "-xc";
195       else if (i == lang_S_here)
196 	new_argv[j++] = "-xassembler-with-cpp";
197       else if (i == o_here)
198 	new_argv[j++] = "-o";
199 
200       new_argv[j] = argv[i];
201     }
202 
203   if (read_stdin)
204     new_argv[j++] = "-";
205 
206   new_argv[j] = NULL;
207   *in_argc = new_argc;
208   *in_argv = new_argv;
209 }
210 
211 /* Called before linking.  Returns 0 on success and -1 on failure.  */
212 int lang_specific_pre_link ()
213 {
214   return 0;  /* Not used for cpp.  */
215 }
216 
217 /* Number of extra output files that lang_specific_pre_link may generate.  */
218 int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
219 
220 /* Table of language-specific spec functions.  */
221 const struct spec_function lang_specific_spec_functions[] =
222 {
223   { 0, 0 }
224 };
225