OSDN Git Service

Daily bump.
[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 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, "-Xlinker")
198                || ! strcmp (text, "-specs"))
199         skip = 1;
200       else
201         skip = 0;
202     }
203
204   if (xopt != NULL)
205     *xopt = opt;
206   if (xskip != NULL)
207     *xskip = skip;
208   if (xarg != NULL)
209     {
210       if ((arg != NULL)
211           && (arg[0] == '\0'))
212         *xarg = NULL;
213       else
214         *xarg = arg;
215     }
216 }
217
218 /* Append another argument to the list being built.  As long as it is
219    identical to the corresponding arg in the original list, just increment
220    the new arg count.  Otherwise allocate a new list, etc.  */
221
222 static void
223 append_arg (arg)
224      const char *arg;
225 {
226   static int newargsize;
227
228 #if 0
229   fprintf (stderr, "`%s'\n", arg);
230 #endif
231
232   if (g77_newargv == g77_xargv
233       && g77_newargc < g77_xargc
234       && (arg == g77_xargv[g77_newargc]
235           || ! strcmp (arg, g77_xargv[g77_newargc])))
236     {
237       ++g77_newargc;
238       return;                   /* Nothing new here. */
239     }
240
241   if (g77_newargv == g77_xargv)
242     {                           /* Make new arglist. */
243       int i;
244
245       newargsize = (g77_xargc << 2) + 20;       /* This should handle all. */
246       g77_newargv = (const char **) xmalloc (newargsize * sizeof (char *));
247
248       /* Copy what has been done so far.  */
249       for (i = 0; i < g77_newargc; ++i)
250         g77_newargv[i] = g77_xargv[i];
251     }
252
253   if (g77_newargc == newargsize)
254     fatal ("overflowed output arg list for `%s'", arg);
255
256   g77_newargv[g77_newargc++] = arg;
257 }
258
259 void
260 lang_specific_driver (in_argc, in_argv, in_added_libraries)
261      int *in_argc;
262      const char *const **in_argv;
263      int *in_added_libraries ATTRIBUTE_UNUSED;
264 {
265   int argc = *in_argc;
266   const char *const *argv = *in_argv;
267   int i;
268   int verbose = 0;
269   Option opt;
270   int skip;
271   const char *arg;
272
273   /* This will be NULL if we encounter a situation where we should not
274      link in libf2c.  */
275   const char *library = FORTRAN_LIBRARY;
276
277   /* 0 => -xnone in effect.
278      1 => -xfoo in effect.  */
279   int saw_speclang = 0;
280
281   /* 0 => initial/reset state
282      1 => last arg was -l<library>
283      2 => last two args were -l<library> -lm.  */
284   int saw_library = 0;
285
286   /* 0 => initial/reset state
287      1 => FORTRAN_INIT linked in */
288   int use_init = 0;
289   /* By default, we throw on the math library if we have one.  */
290   int need_math = (MATH_LIBRARY[0] != '\0');
291
292   /* The number of input and output files in the incoming arg list.  */
293   int n_infiles = 0;
294   int n_outfiles = 0;
295
296 #if 0
297   fprintf (stderr, "Incoming:");
298   for (i = 0; i < argc; i++)
299     fprintf (stderr, " %s", argv[i]);
300   fprintf (stderr, "\n");
301 #endif
302
303   g77_xargc = argc;
304   g77_xargv = argv;
305   g77_newargc = 0;
306   g77_newargv = (const char **) argv;
307
308   /* First pass through arglist.
309
310      If -nostdlib or a "turn-off-linking" option is anywhere in the
311      command line, don't do any library-option processing (except
312      relating to -x).  Also, if -v is specified, but no other options
313      that do anything special (allowing -V version, etc.), remember
314      to add special stuff to make gcc command actually invoke all
315      the different phases of the compilation process so all the version
316      numbers can be seen.
317
318      Also, here is where all problems with missing arguments to options
319      are caught.  If this loop is exited normally, it means all options
320      have the appropriate number of arguments as far as the rest of this
321      program is concerned.  */
322
323   for (i = 1; i < argc; ++i)
324     {
325       if ((argv[i][0] == '+') && (argv[i][1] == 'e'))
326         {
327           continue;
328         }
329
330       if ((argv[i][0] != '-') || (argv[i][1] == '\0'))
331         {
332           ++n_infiles;
333           continue;
334         }
335
336       lookup_option (&opt, &skip, NULL, argv[i]);
337
338       switch (opt)
339         {
340         case OPTION_nostdlib:
341         case OPTION_c:
342         case OPTION_S:
343         case OPTION_syntax_only:
344         case OPTION_E:
345         case OPTION_M:
346         case OPTION_MM:
347           /* These options disable linking entirely or linking of the
348              standard libraries.  */
349           library = 0;
350           break;
351
352         case OPTION_l:
353           ++n_infiles;
354           break;
355
356         case OPTION_o:
357           ++n_outfiles;
358           break;
359
360         case OPTION_v:
361           verbose = 1;
362           break;
363
364         case OPTION_b:
365         case OPTION_B:
366         case OPTION_L:
367         case OPTION_i:
368         case OPTION_V:
369           /* These options are useful in conjunction with -v to get
370              appropriate version info.  */
371           break;
372
373         case OPTION_version:
374           printf ("\
375 GNU Fortran %s (Fortran Frontend version %s)\n\
376 Copyright (C) 2001 Free Software Foundation, Inc.\n\
377 \n\
378 GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
379 You may redistribute copies of GNU Fortran\n\
380 under the terms of the GNU General Public License.\n\
381 For more information about these matters, see the file named COPYING\n\
382 or type the command `info -f g77 Copying'.\n\
383 ", version_string, ffe_version_string);
384           exit (0);
385           break;
386
387         case OPTION_help:
388           /* Let gcc.c handle this, as it has a really
389              cool facility for handling --help and --verbose --help.  */
390           return;
391
392         case OPTION_driver:
393           fatal ("--driver no longer supported");
394           break;
395
396         default:
397           break;
398         }
399
400       /* This is the one place we check for missing arguments in the
401          program.  */
402
403       if (i + skip < argc)
404         i += skip;
405       else
406         fatal ("argument to `%s' missing", argv[i]);
407     }
408
409   if ((n_outfiles != 0) && (n_infiles == 0))
410     fatal ("no input files; unwilling to write output files");
411
412   /* If there are no input files, no need for the library.  */
413   if (n_infiles == 0)
414     library = 0;
415
416   /* Second pass through arglist, transforming arguments as appropriate.  */
417
418   append_arg (argv[0]); /* Start with command name, of course. */
419
420   for (i = 1; i < argc; ++i)
421     {
422       if (argv[i][0] == '\0')
423         {
424           append_arg (argv[i]); /* Interesting.  Just append as is. */
425           continue;
426         }
427
428       if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
429         {
430           /* Not a filename or library. */
431
432          if (saw_library == 1 && need_math)    /* -l<library>. */
433             append_arg (MATH_LIBRARY);
434
435           saw_library = 0;
436
437           lookup_option (&opt, &skip, &arg, argv[i]);
438
439           if (argv[i][1] == '\0')
440             {
441               append_arg (argv[i]);     /* "-" == Standard input. */
442               continue;
443             }
444
445           if (opt == OPTION_x)
446             {
447               /* Track input language. */
448               const char *lang;
449
450               if (arg == NULL)
451                 lang = argv[i+1];
452               else
453                 lang = arg;
454
455               saw_speclang = (strcmp (lang, "none") != 0);
456             }
457
458           append_arg (argv[i]);
459
460           for (; skip != 0; --skip)
461             append_arg (argv[++i]);
462
463           continue;
464         }
465
466       /* A filename/library, not an option. */
467
468       if (saw_speclang)
469         saw_library = 0;        /* -xfoo currently active. */
470       else
471         {                       /* -lfoo or filename. */
472           if (strcmp (argv[i], MATH_LIBRARY) == 0
473 #ifdef ALT_LIBM
474               || strcmp (argv[i], ALT_LIBM) == 0
475 #endif
476               )
477             {
478               if (saw_library == 1)
479                 saw_library = 2;        /* -l<library> -lm. */
480               else
481                 {
482                   if (0 == use_init)
483                     {
484                       append_arg (FORTRAN_INIT);
485                       use_init = 1;
486                     }
487                   append_arg (FORTRAN_LIBRARY);
488                 }
489             }
490           else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
491             saw_library = 1;    /* -l<library>. */
492           else
493             {           /* Other library, or filename. */
494              if (saw_library == 1 && need_math)
495                 append_arg (MATH_LIBRARY);
496               saw_library = 0;
497             }
498         }
499       append_arg (argv[i]);
500     }
501
502   /* Append `-lg2c -lm' as necessary.  */
503
504   if (library)
505     {                           /* Doing a link and no -nostdlib. */
506       if (saw_speclang)
507         append_arg ("-xnone");
508
509       switch (saw_library)
510         {
511         case 0:
512           if (0 == use_init)
513             {
514               append_arg (FORTRAN_INIT);
515               use_init = 1;
516             }
517           append_arg (library);
518         case 1:
519          if (need_math)
520            append_arg (MATH_LIBRARY);
521         default:
522           break;
523         }
524     }
525
526 #ifdef ENABLE_SHARED_LIBGCC
527   if (library)
528     {
529       int i;
530
531       for (i = 1; i < g77_newargc; i++)
532         if (g77_newargv[i][0] == '-')
533           if (strcmp (g77_newargv[i], "-static-libgcc") == 0
534               || strcmp (g77_newargv[i], "-static") == 0)
535             break;
536     
537       if (i == g77_newargc)
538         append_arg ("-shared-libgcc");
539     }
540   
541 #endif
542
543   if (verbose
544       && g77_newargv != g77_xargv)
545     {
546       fprintf (stderr, "Driving:");
547       for (i = 0; i < g77_newargc; i++)
548         fprintf (stderr, " %s", g77_newargv[i]);
549       fprintf (stderr, "\n");
550     }
551
552   *in_argc = g77_newargc;
553   *in_argv = g77_newargv;
554 }
555
556 /* Called before linking.  Returns 0 on success and -1 on failure. */
557 int lang_specific_pre_link ()  /* Not used for F77. */
558 {
559   return 0;
560 }
561
562 /* Number of extra output files that lang_specific_pre_link may generate. */
563 int lang_specific_extra_outfiles = 0;  /* Not used for F77. */