OSDN Git Service

Fix date on last entry.
[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
57 #ifndef WORD_SWITCH_TAKES_ARG
58 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
59 #endif
60
61 /* Suffixes for known sorts of input files.  Note that we do not list
62    files which are normally considered to have been preprocessed already,
63    since the user's expectation is that `cpp' always preprocesses.  */
64 static const char *const known_suffixes[] =
65 {
66   ".c",  ".C",   ".S",   ".m",
67   ".cc", ".cxx", ".cpp", ".cp",  ".c++",
68   NULL
69 };
70
71 /* Filter argc and argv before processing by the gcc driver proper. */
72 void
73 lang_specific_driver (in_argc, in_argv, in_added_libraries)
74      int *in_argc;
75      char ***in_argv;
76      int *in_added_libraries ATTRIBUTE_UNUSED;
77 {
78   int argc = *in_argc;
79   char **argv = *in_argv;
80   
81   /* Do we need to read stdin? */
82   int read_stdin = 1;
83
84   /* Do we need to insert -E? */
85   int need_E = 1;
86
87   /* Do we need to insert -no-gcc? */
88   int need_no_gcc = 1;
89
90   /* Have we seen an input file? */
91   int seen_input = 0;
92   
93   /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
94      0 means unnecessary. */
95   int lang_c_here = 0;
96   int lang_S_here = 0;
97   int o_here = 0;
98
99   /* Do we need to fix up an input file with an unrecognized suffix? */
100   int need_fixups = 1;
101   
102   int i, j, quote = 0;
103   char **real_new_argv;
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 legal 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   real_new_argv = (char **) xmalloc ((new_argc + 1) * sizeof(char *));
200   new_argv = (const char **) real_new_argv;
201
202   new_argv[0] = argv[0];
203   j = 1;
204
205   if (need_E)
206     new_argv[j++] = "-E";
207
208   if (need_no_gcc)
209     new_argv[j++] = "-no-gcc";
210
211   for (i = 1; i < argc; i++, j++)
212     {
213       if (i == lang_c_here)
214         new_argv[j++] = "-xc";
215       else if (i == lang_S_here)
216         new_argv[j++] = "-xassembler-with-cpp";
217       else if (i == o_here)
218         new_argv[j++] = "-o";
219
220       new_argv[j] = argv[i];
221     }
222
223   if (read_stdin)
224     new_argv[j++] = "-";
225
226   new_argv[j] = NULL;
227   *in_argc = new_argc;
228   *in_argv = real_new_argv;
229
230
231 /* Called before linking.  Returns 0 on success and -1 on failure. */
232 int lang_specific_pre_link ()
233 {
234   return 0;  /* Not used for cpp. */
235 }
236
237 /* Number of extra output files that lang_specific_pre_link may generate. */
238 int lang_specific_extra_outfiles = 0;  /* Not used for cpp. */