OSDN Git Service

2001-07-30 H.J. Lu (hjl@gnu.org)
[pf3gnuchains/gcc-fork.git] / gcc / cppspec.c
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 GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 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
107   /* First pass.  If we see an -S or -c, barf.  If we see an input file,
108      turn off read_stdin.  If we see a second input file, it is actually
109      the output file.  If we see a third input file, barf.  */
110   for (i = 1; i < argc; i++)
111     {
112       if (quote == 1)
113         {
114           quote = 0;
115           continue;
116         }
117       
118       if (argv[i][0] == '-')
119         {
120           if (argv[i][1] == '\0')
121             read_stdin = 0;
122           else if (argv[i][2] == '\0')
123             {
124               if (argv[i][1] == 'E')
125                 need_E = 0;
126               else if (argv[i][1] == 'S' || argv[i][1] == 'c')
127                 {
128                   fatal ("\"%s\" is not a valid option to the preprocessor",
129                          argv[i]);
130                   return;
131                 }
132               else if (argv[i][1] == 'x')
133                 {
134                   need_fixups = 0;
135                   quote = 1;
136                 }
137               else if (SWITCH_TAKES_ARG (argv[i][1]))
138                 quote = 1;
139             }
140           else if (argv[i][1] == 'x')
141             need_fixups = 0;
142           else if (argv[i][1] == 'g' && !strcmp(&argv[i][2], "cc"))
143             need_no_gcc = 0;
144           else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
145             quote = 1;
146         }
147       else /* not an option */
148         {
149           seen_input++;
150           if (seen_input == 3)
151             {
152               fatal ("too many input files");
153               return;
154             }
155           else if (seen_input == 2)
156             {
157               o_here = i;
158             }
159           else
160             {
161               read_stdin = 0;
162               if (need_fixups)
163                 {
164                   int l = strlen (argv[i]);
165                   int known = 0;
166                   const char *const *suff;
167
168                   for (suff = known_suffixes; *suff; suff++)
169                     if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
170                       {
171                         known = 1;
172                         break;
173                       }
174
175                   if (! known)
176                     {
177                       /* .s files are a special case; we have to treat
178                          them like .S files so -D__ASSEMBLER__ will be
179                          in effect.  */
180                       if (!strcmp (".s", &argv[i][l - 2]))
181                         lang_S_here = i;
182                       else
183                         lang_c_here = i;
184                     }
185                 }
186             }
187         }
188     }
189
190   /* If we don't need to edit the command line, we can bail early.  */
191
192   new_argc = argc + need_E + need_no_gcc + read_stdin
193     + !!o_here + !!lang_c_here + !!lang_S_here;
194
195   if (new_argc == argc)
196     return;
197
198   /* One more slot for a terminating null.  */
199   new_argv = (const char **) xmalloc ((new_argc + 1) * sizeof(char *));
200
201   new_argv[0] = argv[0];
202   j = 1;
203
204   if (need_E)
205     new_argv[j++] = "-E";
206
207   if (need_no_gcc)
208     new_argv[j++] = "-no-gcc";
209
210   for (i = 1; i < argc; i++, j++)
211     {
212       if (i == lang_c_here)
213         new_argv[j++] = "-xc";
214       else if (i == lang_S_here)
215         new_argv[j++] = "-xassembler-with-cpp";
216       else if (i == o_here)
217         new_argv[j++] = "-o";
218
219       new_argv[j] = argv[i];
220     }
221
222   if (read_stdin)
223     new_argv[j++] = "-";
224
225   new_argv[j] = NULL;
226   *in_argc = new_argc;
227   *in_argv = new_argv;
228
229
230 /* Called before linking.  Returns 0 on success and -1 on failure. */
231 int lang_specific_pre_link ()
232 {
233   return 0;  /* Not used for cpp. */
234 }
235
236 /* Number of extra output files that lang_specific_pre_link may generate. */
237 int lang_specific_extra_outfiles = 0;  /* Not used for cpp. */