OSDN Git Service

2908b739368e386ff0d62a01a83242beea1cbe30
[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
24 /* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
25    is a customized version of the gcc driver.  It forces -E; -S and -c
26    are errors.  It defaults to -x c for files with unrecognized
27    extensions, unless -x options appear in argv, in which case we
28    assume the user knows what they're doing.  If no explicit input is
29    mentioned, it will read stdin. */
30
31 /* Snarfed from gcc.c: */
32
33 /* This defines which switch letters take arguments.  */
34
35 #define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
36   ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
37    || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
38    || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
39    || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
40    || (CHAR) == 'B' || (CHAR) == 'b')
41
42 #ifndef SWITCH_TAKES_ARG
43 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
44 #endif
45
46 /* This defines which multi-letter switches take arguments.  */
47
48 #define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)              \
49  (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")      \
50   || !strcmp (STR, "Tbss") || !strcmp (STR, "include")  \
51   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
52   || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
53   || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
54   || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
55
56 #ifndef WORD_SWITCH_TAKES_ARG
57 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
58 #endif
59
60 /* Suffixes for known sorts of input files.  Note that we do not list
61    files which are normally considered to have been preprocessed already,
62    since the user's expectation is that `cpp' always preprocesses.  */
63 static const char *const known_suffixes[] =
64 {
65   ".c",  ".C",   ".S",   ".m",
66   ".cc", ".cxx", ".cpp", ".cp",  ".c++",
67   NULL
68 };
69
70 /* Filter argc and argv before processing by the gcc driver proper. */
71 void
72 lang_specific_driver (errfn, in_argc, in_argv, in_added_libraries)
73      void (*errfn) PVPROTO((const char *, ...));
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   /* Have we seen an input file? */
88   int seen_input = 0;
89   
90   /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
91      0 means unnecessary. */
92   int lang_c_here = 0;
93   int lang_S_here = 0;
94   int o_here = 0;
95
96   /* Do we need to fix up an input file with an unrecognized suffix? */
97   int need_fixups = 1;
98   
99   int i, j, quote;
100   char **new_argv;
101   int new_argc;
102
103   /* First pass.  If we see an -S or -c, barf.  If we see an input file,
104      turn off read_stdin.  If we see a second input file, it is actually
105      the output file.  If we see a third input file, barf.  */
106   for (i = 1; i < argc; i++)
107     {
108       if (quote == 1)
109         {
110           quote = 0;
111           continue;
112         }
113       
114       if (argv[i][0] == '-')
115         {
116           if (argv[i][1] == '\0')
117             read_stdin = 0;
118           else if (argv[i][2] == '\0')
119             {
120               if (argv[i][1] == 'E')
121                 need_E = 0;
122               else if (argv[i][1] == 'S' || argv[i][1] == 'c')
123                 {
124                   (*errfn) ("`%s' is not a legal option to the preprocessor",
125                             argv[i]);
126                   return;
127                 }
128               else if (argv[i][1] == 'x')
129                 {
130                   need_fixups = 0;
131                   quote = 1;
132                 }
133               else if (SWITCH_TAKES_ARG (argv[i][1]))
134                 quote = 1;
135             }
136           else if (argv[i][1] == 'x')
137             need_fixups = 0;
138           else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
139             quote = 1;
140         }
141       else /* not an option */
142         {
143           seen_input++;
144           if (seen_input == 3)
145             {
146               (*errfn) ("too many input files");
147               return;
148             }
149           else if (seen_input == 2)
150             {
151               o_here = i;
152             }
153           else
154             {
155               read_stdin = 0;
156               if (need_fixups)
157                 {
158                   int l = strlen (argv[i]);
159                   int known = 0;
160                   const char *const *suff;
161
162                   for (suff = known_suffixes; *suff; suff++)
163                     if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
164                       {
165                         known = 1;
166                         break;
167                       }
168
169                   if (! known)
170                     {
171                       /* .s files are a special case; we have to treat
172                          them like .S files so -D__ASSEMBLER__ will be
173                          in effect.  */
174                       if (!strcmp (".s", &argv[i][l - 2]))
175                         lang_S_here = i;
176                       else
177                         lang_c_here = i;
178                     }
179                 }
180             }
181         }
182     }
183
184   /* If we don't need to edit the command line, we can bail early.  */
185
186   new_argc = argc + need_E + read_stdin
187     + !!o_here + !!lang_c_here + !!lang_S_here;
188
189   if (new_argc == argc)
190     return;
191
192   new_argv = xmalloc (new_argc * sizeof(char *));
193
194   new_argv[0] = argv[0];
195   j = 1;
196
197   if (need_E)
198     new_argv[j++] = "-E";
199
200   for (i = 1; i < argc; i++, j++)
201     {
202       if (i == lang_c_here)
203         new_argv[j++] = "-xc";
204       else if (i == lang_S_here)
205         new_argv[j++] = "-xassembler-with-cpp";
206       else if (i == o_here)
207         new_argv[j++] = "-o";
208
209       new_argv[j] = argv[i];
210     }
211
212   if (read_stdin)
213     new_argv[j] = "-";
214
215   *in_argc = new_argc;
216   *in_argv = new_argv;
217
218
219 /* Called before linking.  Returns 0 on success and -1 on failure. */
220 int lang_specific_pre_link ()
221 {
222   return 0;  /* Not used for cpp. */
223 }
224
225 /* Number of extra output files that lang_specific_pre_link may generate. */
226 int lang_specific_extra_outfiles = 0;  /* Not used for cpp. */