]>
Commit | Line | Data |
---|---|---|
6de9cd9a | 1 | /* Specific flags and argument handling of the Fortran front-end. |
9fc4d79b TS |
2 | Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004 Free Software |
3 | Foundation, Inc. | |
6de9cd9a DN |
4 | |
5 | This file is part of GNU CC. | |
6 | ||
7 | GNU CC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GNU CC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GNU CC; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
21 | /* This file is copied more or less verbatim from g77. */ | |
22 | /* This file contains a filter for the main `gcc' driver, which is | |
23 | replicated for the `gfortran' driver by adding this filter. The purpose | |
24 | of this filter is to be basically identical to gcc (in that | |
25 | it faithfully passes all of the original arguments to gcc) but, | |
26 | unless explicitly overridden by the user in certain ways, ensure | |
27 | that the needs of the language supported by this wrapper are met. | |
28 | ||
29 | For GNU Fortran 95(gfortran), we do the following to the argument list | |
30 | before passing it to `gcc': | |
31 | ||
32 | 1. Make sure `-lgfortran -lm' is at the end of the list. | |
33 | ||
34 | 2. Make sure each time `-lgfortran' or `-lm' is seen, it forms | |
35 | part of the series `-lgfortran -lm'. | |
36 | ||
37 | #1 and #2 are not done if `-nostdlib' or any option that disables | |
38 | the linking phase is present, or if `-xfoo' is in effect. Note that | |
39 | a lack of source files or -l options disables linking. | |
40 | ||
41 | This program was originally made out of gcc/cp/g++spec.c, but the | |
42 | way it builds the new argument list was rewritten so it is much | |
43 | easier to maintain, improve the way it decides to add or not add | |
44 | extra arguments, etc. And several improvements were made in the | |
45 | handling of arguments, primarily to make it more consistent with | |
46 | `gcc' itself. */ | |
47 | ||
48 | #include "config.h" | |
49 | #include "system.h" | |
50 | #include "gcc.h" | |
51 | ||
52 | #include "coretypes.h" | |
53 | #include "tm.h" | |
54 | ||
55 | #ifndef MATH_LIBRARY | |
56 | #define MATH_LIBRARY "-lm" | |
57 | #endif | |
58 | ||
59 | #ifndef FORTRAN_INIT | |
60 | #define FORTRAN_INIT "-lgfortranbegin" | |
61 | #endif | |
62 | ||
63 | #ifndef FORTRAN_LIBRARY | |
64 | #define FORTRAN_LIBRARY "-lgfortran" | |
65 | #endif | |
66 | ||
67 | /* Options this driver needs to recognize, not just know how to | |
68 | skip over. */ | |
69 | typedef enum | |
70 | { | |
71 | OPTION_b, /* Aka --prefix. */ | |
72 | OPTION_B, /* Aka --target. */ | |
73 | OPTION_c, /* Aka --compile. */ | |
74 | OPTION_E, /* Aka --preprocess. */ | |
75 | OPTION_help, /* --help. */ | |
76 | OPTION_i, /* -imacros, -include, -include-*. */ | |
77 | OPTION_l, | |
78 | OPTION_L, /* Aka --library-directory. */ | |
79 | OPTION_nostdlib, /* Aka --no-standard-libraries, or | |
80 | -nodefaultlibs. */ | |
81 | OPTION_o, /* Aka --output. */ | |
82 | OPTION_S, /* Aka --assemble. */ | |
83 | OPTION_syntax_only, /* -fsyntax-only. */ | |
84 | OPTION_v, /* Aka --verbose. */ | |
85 | OPTION_version, /* --version. */ | |
86 | OPTION_V, /* Aka --use-version. */ | |
87 | OPTION_x, /* Aka --language. */ | |
88 | OPTION_ /* Unrecognized or unimportant. */ | |
89 | } | |
90 | Option; | |
91 | ||
92 | /* The original argument list and related info is copied here. */ | |
93 | static int g77_xargc; | |
94 | static const char *const *g77_xargv; | |
95 | static void lookup_option (Option *, int *, const char **, const char *); | |
96 | static void append_arg (const char *); | |
97 | ||
98 | /* The new argument list will be built here. */ | |
99 | static int g77_newargc; | |
100 | static const char **g77_newargv; | |
101 | ||
102 | const struct spec_function lang_specific_spec_functions[] = {{0,0}}; | |
103 | ||
104 | /* --- This comes from gcc.c (2.8.1) verbatim: */ | |
105 | ||
106 | /* This defines which switch letters take arguments. */ | |
107 | ||
108 | #ifndef SWITCH_TAKES_ARG | |
109 | #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) | |
110 | #endif | |
111 | ||
112 | /* This defines which multi-letter switches take arguments. */ | |
113 | ||
114 | #ifndef WORD_SWITCH_TAKES_ARG | |
115 | #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) | |
116 | #endif | |
117 | ||
118 | /* --- End of verbatim. */ | |
119 | ||
120 | /* Assumes text[0] == '-'. Returns number of argv items that belong to | |
121 | (and follow) this one, an option id for options important to the | |
122 | caller, and a pointer to the first char of the arg, if embedded (else | |
123 | returns NULL, meaning no arg or it's the next argv). | |
124 | ||
125 | Note that this also assumes gcc.c's pass converting long options | |
126 | to short ones, where available, has already been run. */ | |
127 | ||
128 | static void | |
129 | lookup_option (Option *xopt, int *xskip, const char **xarg, const char *text) | |
130 | { | |
131 | Option opt = OPTION_; | |
132 | int skip; | |
133 | const char *arg = NULL; | |
134 | ||
135 | if ((skip = SWITCH_TAKES_ARG (text[1]))) | |
136 | skip -= (text[2] != '\0'); /* See gcc.c. */ | |
137 | ||
138 | if (text[1] == 'B') | |
139 | opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2; | |
140 | else if (text[1] == 'b') | |
141 | opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2; | |
142 | else if ((text[1] == 'c') && (text[2] == '\0')) | |
143 | opt = OPTION_c, skip = 0; | |
144 | else if ((text[1] == 'E') && (text[2] == '\0')) | |
145 | opt = OPTION_E, skip = 0; | |
146 | else if (text[1] == 'i') | |
147 | opt = OPTION_i, skip = 0; | |
148 | else if (text[1] == 'l') | |
149 | opt = OPTION_l; | |
150 | else if (text[1] == 'L') | |
151 | opt = OPTION_L, arg = text + 2; | |
152 | else if (text[1] == 'o') | |
153 | opt = OPTION_o; | |
154 | else if ((text[1] == 'S') && (text[2] == '\0')) | |
155 | opt = OPTION_S, skip = 0; | |
156 | else if (text[1] == 'V') | |
157 | opt = OPTION_V, skip = (text[2] == '\0'); | |
158 | else if ((text[1] == 'v') && (text[2] == '\0')) | |
159 | opt = OPTION_v, skip = 0; | |
160 | else if (text[1] == 'x') | |
161 | opt = OPTION_x, arg = text + 2; | |
162 | else | |
163 | { | |
164 | if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0) /* See gcc.c. */ | |
165 | ; | |
166 | else if (!strcmp (text, "-fhelp")) /* Really --help!! */ | |
167 | opt = OPTION_help; | |
168 | else if (!strcmp (text, "-nostdlib") | |
169 | || !strcmp (text, "-nodefaultlibs")) | |
170 | opt = OPTION_nostdlib; | |
171 | else if (!strcmp (text, "-fsyntax-only")) | |
172 | opt = OPTION_syntax_only; | |
173 | else if (!strcmp (text, "-dumpversion")) | |
174 | opt = OPTION_version; | |
175 | else if (!strcmp (text, "-fversion")) /* Really --version!! */ | |
176 | opt = OPTION_version; | |
177 | else if (!strcmp (text, "-Xlinker") || !strcmp (text, "-specs")) | |
178 | skip = 1; | |
179 | else | |
180 | skip = 0; | |
181 | } | |
182 | ||
183 | if (xopt != NULL) | |
184 | *xopt = opt; | |
185 | if (xskip != NULL) | |
186 | *xskip = skip; | |
187 | if (xarg != NULL) | |
188 | { | |
189 | if ((arg != NULL) && (arg[0] == '\0')) | |
190 | *xarg = NULL; | |
191 | else | |
192 | *xarg = arg; | |
193 | } | |
194 | } | |
195 | ||
196 | /* Append another argument to the list being built. As long as it is | |
197 | identical to the corresponding arg in the original list, just increment | |
198 | the new arg count. Otherwise allocate a new list, etc. */ | |
199 | ||
200 | static void | |
201 | append_arg (const char *arg) | |
202 | { | |
203 | static int newargsize; | |
204 | ||
205 | #if 0 | |
206 | fprintf (stderr, "`%s'\n", arg); | |
207 | #endif | |
208 | ||
209 | if (g77_newargv == g77_xargv | |
210 | && g77_newargc < g77_xargc | |
211 | && (arg == g77_xargv[g77_newargc] | |
212 | || !strcmp (arg, g77_xargv[g77_newargc]))) | |
213 | { | |
214 | ++g77_newargc; | |
215 | return; /* Nothing new here. */ | |
216 | } | |
217 | ||
218 | if (g77_newargv == g77_xargv) | |
219 | { /* Make new arglist. */ | |
220 | int i; | |
221 | ||
222 | newargsize = (g77_xargc << 2) + 20; /* This should handle all. */ | |
223 | g77_newargv = (const char **) xmalloc (newargsize * sizeof (char *)); | |
224 | ||
225 | /* Copy what has been done so far. */ | |
226 | for (i = 0; i < g77_newargc; ++i) | |
227 | g77_newargv[i] = g77_xargv[i]; | |
228 | } | |
229 | ||
230 | if (g77_newargc == newargsize) | |
231 | fatal ("overflowed output arg list for `%s'", arg); | |
232 | ||
233 | g77_newargv[g77_newargc++] = arg; | |
234 | } | |
235 | ||
236 | void | |
237 | lang_specific_driver (int *in_argc, const char *const **in_argv, | |
238 | int *in_added_libraries ATTRIBUTE_UNUSED) | |
239 | { | |
240 | int argc = *in_argc; | |
241 | const char *const *argv = *in_argv; | |
242 | int i; | |
243 | int verbose = 0; | |
244 | Option opt; | |
245 | int skip; | |
246 | const char *arg; | |
247 | ||
248 | /* This will be NULL if we encounter a situation where we should not | |
249 | link in libf2c. */ | |
250 | const char *library = FORTRAN_LIBRARY; | |
251 | ||
252 | /* 0 => -xnone in effect. | |
253 | 1 => -xfoo in effect. */ | |
254 | int saw_speclang = 0; | |
255 | ||
256 | /* 0 => initial/reset state | |
257 | 1 => last arg was -l<library> | |
258 | 2 => last two args were -l<library> -lm. */ | |
259 | int saw_library = 0; | |
260 | ||
261 | /* 0 => initial/reset state | |
262 | 1 => FORTRAN_INIT linked in */ | |
263 | int use_init = 0; | |
264 | ||
265 | /* By default, we throw on the math library if we have one. */ | |
266 | int need_math = (MATH_LIBRARY[0] != '\0'); | |
267 | ||
268 | /* The number of input and output files in the incoming arg list. */ | |
269 | int n_infiles = 0; | |
270 | int n_outfiles = 0; | |
271 | ||
272 | #if 0 | |
273 | fprintf (stderr, "Incoming:"); | |
274 | for (i = 0; i < argc; i++) | |
275 | fprintf (stderr, " %s", argv[i]); | |
276 | fprintf (stderr, "\n"); | |
277 | #endif | |
278 | ||
279 | g77_xargc = argc; | |
280 | g77_xargv = argv; | |
281 | g77_newargc = 0; | |
282 | g77_newargv = (const char **) argv; | |
283 | ||
284 | /* First pass through arglist. | |
285 | ||
286 | If -nostdlib or a "turn-off-linking" option is anywhere in the | |
287 | command line, don't do any library-option processing (except | |
288 | relating to -x). Also, if -v is specified, but no other options | |
289 | that do anything special (allowing -V version, etc.), remember | |
290 | to add special stuff to make gcc command actually invoke all | |
291 | the different phases of the compilation process so all the version | |
292 | numbers can be seen. | |
293 | ||
294 | Also, here is where all problems with missing arguments to options | |
295 | are caught. If this loop is exited normally, it means all options | |
296 | have the appropriate number of arguments as far as the rest of this | |
297 | program is concerned. */ | |
298 | ||
299 | for (i = 1; i < argc; ++i) | |
300 | { | |
301 | if ((argv[i][0] == '+') && (argv[i][1] == 'e')) | |
302 | { | |
303 | continue; | |
304 | } | |
305 | ||
306 | if ((argv[i][0] != '-') || (argv[i][1] == '\0')) | |
307 | { | |
308 | ++n_infiles; | |
309 | continue; | |
310 | } | |
311 | ||
312 | lookup_option (&opt, &skip, NULL, argv[i]); | |
313 | ||
314 | switch (opt) | |
315 | { | |
316 | case OPTION_nostdlib: | |
317 | case OPTION_c: | |
318 | case OPTION_S: | |
319 | case OPTION_syntax_only: | |
320 | case OPTION_E: | |
321 | /* These options disable linking entirely or linking of the | |
322 | standard libraries. */ | |
323 | library = 0; | |
324 | break; | |
325 | ||
326 | case OPTION_l: | |
327 | ++n_infiles; | |
328 | break; | |
329 | ||
330 | case OPTION_o: | |
331 | ++n_outfiles; | |
332 | break; | |
333 | ||
334 | case OPTION_v: | |
335 | verbose = 1; | |
336 | break; | |
337 | ||
338 | case OPTION_b: | |
339 | case OPTION_B: | |
340 | case OPTION_L: | |
341 | case OPTION_i: | |
342 | case OPTION_V: | |
343 | /* These options are useful in conjunction with -v to get | |
344 | appropriate version info. */ | |
345 | break; | |
346 | ||
347 | case OPTION_version: | |
348 | printf ("\ | |
349 | GNU Fortran 95 (GCC %s)\n\ | |
350 | Copyright (C) 2003 Free Software Foundation, Inc.\n\ | |
351 | \n\ | |
352 | GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\ | |
353 | You may redistribute copies of GNU Fortran\n\ | |
354 | under the terms of the GNU General Public License.\n\ | |
355 | For more information about these matters, see the file named COPYING\n\ | |
356 | ", version_string); | |
357 | exit (0); | |
358 | break; | |
359 | ||
360 | case OPTION_help: | |
361 | /* Let gcc.c handle this, as it has a really | |
362 | cool facility for handling --help and --verbose --help. */ | |
363 | return; | |
364 | ||
365 | default: | |
366 | break; | |
367 | } | |
368 | ||
369 | /* This is the one place we check for missing arguments in the | |
370 | program. */ | |
371 | ||
372 | if (i + skip < argc) | |
373 | i += skip; | |
374 | else | |
375 | fatal ("argument to `%s' missing", argv[i]); | |
376 | } | |
377 | ||
378 | if ((n_outfiles != 0) && (n_infiles == 0)) | |
379 | fatal ("no input files; unwilling to write output files"); | |
380 | ||
381 | /* If there are no input files, no need for the library. */ | |
382 | if (n_infiles == 0) | |
383 | library = 0; | |
384 | ||
385 | /* Second pass through arglist, transforming arguments as appropriate. */ | |
386 | ||
387 | append_arg (argv[0]); /* Start with command name, of course. */ | |
388 | ||
389 | for (i = 1; i < argc; ++i) | |
390 | { | |
391 | if (argv[i][0] == '\0') | |
392 | { | |
393 | append_arg (argv[i]); /* Interesting. Just append as is. */ | |
394 | continue; | |
395 | } | |
396 | ||
397 | if ((argv[i][0] == '-') && (argv[i][1] == 'M')) | |
398 | { | |
399 | char *p; | |
400 | ||
401 | if (argv[i][2] == '\0') | |
402 | { | |
403 | p = xmalloc (strlen (argv[i + 1]) + 2); | |
404 | p[0] = '-'; | |
405 | p[1] = 'J'; | |
406 | strcpy (&p[2], argv[i + 1]); | |
407 | i++; | |
408 | } | |
409 | else | |
410 | { | |
411 | p = xmalloc (strlen (argv[i]) + 1); | |
412 | strcpy (p, argv[i]); | |
413 | } | |
414 | append_arg (p); | |
415 | continue; | |
416 | } | |
417 | ||
418 | if ((argv[i][0] == '-') && (argv[i][1] != 'l')) | |
419 | { | |
420 | /* Not a filename or library. */ | |
421 | ||
422 | if (saw_library == 1 && need_math) /* -l<library>. */ | |
423 | append_arg (MATH_LIBRARY); | |
424 | ||
425 | saw_library = 0; | |
426 | ||
427 | lookup_option (&opt, &skip, &arg, argv[i]); | |
428 | ||
429 | if (argv[i][1] == '\0') | |
430 | { | |
431 | append_arg (argv[i]); /* "-" == Standard input. */ | |
432 | continue; | |
433 | } | |
434 | ||
435 | if (opt == OPTION_x) | |
436 | { | |
437 | /* Track input language. */ | |
438 | const char *lang; | |
439 | ||
440 | if (arg == NULL) | |
441 | lang = argv[i + 1]; | |
442 | else | |
443 | lang = arg; | |
444 | ||
445 | saw_speclang = (strcmp (lang, "none") != 0); | |
446 | } | |
447 | ||
448 | append_arg (argv[i]); | |
449 | ||
450 | for (; skip != 0; --skip) | |
451 | append_arg (argv[++i]); | |
452 | ||
453 | continue; | |
454 | } | |
455 | ||
456 | /* A filename/library, not an option. */ | |
457 | ||
458 | if (saw_speclang) | |
459 | saw_library = 0; /* -xfoo currently active. */ | |
460 | else | |
461 | { /* -lfoo or filename. */ | |
462 | if (strcmp (argv[i], MATH_LIBRARY) == 0) | |
463 | { | |
464 | if (saw_library == 1) | |
465 | saw_library = 2; /* -l<library> -lm. */ | |
466 | else | |
467 | { | |
468 | if (0 == use_init) | |
469 | { | |
470 | append_arg (FORTRAN_INIT); | |
471 | use_init = 1; | |
472 | } | |
473 | append_arg (FORTRAN_LIBRARY); | |
474 | } | |
475 | } | |
476 | else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0) | |
477 | saw_library = 1; /* -l<library>. */ | |
478 | else | |
479 | { /* Other library, or filename. */ | |
480 | if (saw_library == 1 && need_math) | |
481 | append_arg (MATH_LIBRARY); | |
482 | saw_library = 0; | |
483 | } | |
484 | } | |
485 | append_arg (argv[i]); | |
486 | } | |
487 | ||
488 | /* Append `-lg2c -lm' as necessary. */ | |
489 | ||
490 | if (library) | |
491 | { /* Doing a link and no -nostdlib. */ | |
492 | if (saw_speclang) | |
493 | append_arg ("-xnone"); | |
494 | ||
495 | switch (saw_library) | |
496 | { | |
497 | case 0: | |
498 | if (0 == use_init) | |
499 | { | |
500 | append_arg (FORTRAN_INIT); | |
501 | use_init = 1; | |
502 | } | |
503 | append_arg (library); | |
504 | case 1: | |
505 | if (need_math) | |
506 | append_arg (MATH_LIBRARY); | |
507 | default: | |
508 | break; | |
509 | } | |
510 | } | |
511 | ||
512 | #ifdef ENABLE_SHARED_LIBGCC | |
513 | if (library) | |
514 | { | |
515 | int i; | |
516 | ||
517 | for (i = 1; i < g77_newargc; i++) | |
518 | if (g77_newargv[i][0] == '-') | |
519 | if (strcmp (g77_newargv[i], "-static-libgcc") == 0 | |
520 | || strcmp (g77_newargv[i], "-static") == 0) | |
521 | break; | |
522 | ||
523 | if (i == g77_newargc) | |
524 | append_arg ("-shared-libgcc"); | |
525 | } | |
526 | ||
527 | #endif | |
528 | ||
529 | if (verbose && g77_newargv != g77_xargv) | |
530 | { | |
531 | fprintf (stderr, "Driving:"); | |
532 | for (i = 0; i < g77_newargc; i++) | |
533 | fprintf (stderr, " %s", g77_newargv[i]); | |
534 | fprintf (stderr, "\n"); | |
535 | } | |
536 | ||
537 | *in_argc = g77_newargc; | |
538 | *in_argv = g77_newargv; | |
539 | } | |
540 | ||
541 | /* Called before linking. Returns 0 on success and -1 on failure. */ | |
542 | int | |
543 | lang_specific_pre_link (void) /* Not used for F77. */ | |
544 | { | |
545 | return 0; | |
546 | } | |
547 | ||
548 | /* Number of extra output files that lang_specific_pre_link may generate. */ | |
549 | int lang_specific_extra_outfiles = 0; /* Not used for F77. */ |