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, 51 Franklin Street, Fifth Floor, Boston, MA
1902110-1301, USA.  */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "gcc.h"
26
27/* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
28   is a customized version of the gcc driver.  It forces -E; -S and -c
29   are errors.  It defaults to -x c for files with unrecognized
30   extensions, unless -x options appear in argv, in which case we
31   assume the user knows what they're doing.  If no explicit input is
32   mentioned, it will read stdin.  */
33
34#ifndef SWITCH_TAKES_ARG
35#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
36#endif
37
38#ifndef WORD_SWITCH_TAKES_ARG
39#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
40#endif
41
42/* Suffixes for known sorts of input files.  Note that we do not list
43   files which are normally considered to have been preprocessed already,
44   since the user's expectation is that `cpp' always preprocesses.  */
45static const char *const known_suffixes[] =
46{
47  ".c",  ".C",   ".S",   ".m",
48  ".cc", ".cxx", ".cpp", ".cp",  ".c++",
49  NULL
50};
51
52/* Filter argc and argv before processing by the gcc driver proper.  */
53void
54lang_specific_driver (int *in_argc, 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  /* Have we seen an input file? */
67  int seen_input = 0;
68
69  /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
70     0 means unnecessary.  */
71  int lang_c_here = 0;
72  int lang_S_here = 0;
73  int o_here = 0;
74
75  /* Do we need to fix up an input file with an unrecognized suffix? */
76  int need_fixups = 1;
77
78  int i, j, quote = 0;
79  const char **new_argv;
80  int new_argc;
81  extern int is_cpp_driver;
82
83  is_cpp_driver = 1;
84
85  /* First pass.  If we see an -S or -c, barf.  If we see an input file,
86     turn off read_stdin.  If we see a second input file, it is actually
87     the output file.  If we see a third input file, barf.  */
88  for (i = 1; i < argc; i++)
89    {
90      if (quote == 1)
91	{
92	  quote = 0;
93	  continue;
94	}
95
96      if (argv[i][0] == '-')
97	{
98	  if (argv[i][1] == '\0')
99	    read_stdin = 0;
100	  else if (argv[i][2] == '\0')
101	    {
102	      if (argv[i][1] == 'E')
103		need_E = 0;
104	      else if (argv[i][1] == 'S' || argv[i][1] == 'c')
105		{
106		  fatal ("\"%s\" is not a valid option to the preprocessor",
107			 argv[i]);
108		  return;
109		}
110	      else if (argv[i][1] == 'x')
111		{
112		  need_fixups = 0;
113		  quote = 1;
114		}
115	      else if (SWITCH_TAKES_ARG (argv[i][1]))
116		quote = 1;
117	    }
118	  else if (argv[i][1] == 'x')
119	    need_fixups = 0;
120	  else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
121	    quote = 1;
122	}
123      else /* not an option */
124	{
125	  seen_input++;
126	  if (seen_input == 3)
127	    {
128	      fatal ("too many input files");
129	      return;
130	    }
131	  else if (seen_input == 2)
132	    {
133	      o_here = i;
134	    }
135	  else
136	    {
137	      read_stdin = 0;
138	      if (need_fixups)
139		{
140		  int l = strlen (argv[i]);
141		  int known = 0;
142		  const char *const *suff;
143
144		  for (suff = known_suffixes; *suff; suff++)
145		    if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
146		      {
147			known = 1;
148			break;
149		      }
150
151		  if (! known)
152		    {
153		      /* .s files are a special case; we have to treat
154			 them like .S files so -D__ASSEMBLER__ will be
155			 in effect.  */
156		      if (!strcmp (".s", &argv[i][l - 2]))
157			lang_S_here = i;
158		      else
159			lang_c_here = i;
160		    }
161		}
162	    }
163	}
164    }
165
166  /* If we don't need to edit the command line, we can bail early.  */
167
168  new_argc = argc + need_E + read_stdin
169    + !!o_here + !!lang_c_here + !!lang_S_here;
170
171  if (new_argc == argc)
172    return;
173
174  /* One more slot for a terminating null.  */
175  new_argv = XNEWVEC (const char *, new_argc + 1);
176
177  new_argv[0] = argv[0];
178  j = 1;
179
180  if (need_E)
181    new_argv[j++] = "-E";
182
183  for (i = 1; i < argc; i++, j++)
184    {
185      if (i == lang_c_here)
186	new_argv[j++] = "-xc";
187      else if (i == lang_S_here)
188	new_argv[j++] = "-xassembler-with-cpp";
189      else if (i == o_here)
190	new_argv[j++] = "-o";
191
192      new_argv[j] = argv[i];
193    }
194
195  if (read_stdin)
196    new_argv[j++] = "-";
197
198  new_argv[j] = NULL;
199  *in_argc = new_argc;
200  *in_argv = new_argv;
201}
202
203/* Called before linking.  Returns 0 on success and -1 on failure.  */
204int lang_specific_pre_link (void)
205{
206  return 0;  /* Not used for cpp.  */
207}
208
209/* Number of extra output files that lang_specific_pre_link may generate.  */
210int lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
211