OSDN Git Service

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