1/* Specific flags and argument handling of the C preprocessor.
2   Copyright (C) 1999 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 2, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING.  If not, write to the Free
18Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1902111-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.  */
43static 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.  */
51void
52lang_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.  */
212int 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.  */
218int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
219
220/* Table of language-specific spec functions.  */
221const struct spec_function lang_specific_spec_functions[] =
222{
223  { 0, 0 }
224};
225