OSDN Git Service

* g77spec.c: Don't include gansidecl.h.
[pf3gnuchains/gcc-fork.git] / gcc / f / g77spec.c
1 /* Specific flags and argument handling of the Fortran front-end.
2    Copyright (C) 1997 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 <f/version.h>
50
51 #ifndef MATH_LIBRARY
52 #define MATH_LIBRARY "-lm"
53 #endif
54
55 #ifndef FORTRAN_LIBRARY
56 #define FORTRAN_LIBRARY "-lg2c"
57 #endif
58
59 /* Options this driver needs to recognize, not just know how to
60    skip over.  */
61 typedef enum
62 {
63   OPTION_b,                     /* Aka --prefix. */
64   OPTION_B,                     /* Aka --target. */
65   OPTION_c,                     /* Aka --compile. */
66   OPTION_driver,                /* Wrapper-specific option. */
67   OPTION_E,                     /* Aka --preprocess. */
68   OPTION_help,                  /* --help. */
69   OPTION_i,                     /* -imacros, -include, -include-*. */
70   OPTION_l,
71   OPTION_L,                     /* Aka --library-directory. */
72   OPTION_M,                     /* Aka --dependencies. */
73   OPTION_MM,                    /* Aka --user-dependencies. */
74   OPTION_nostdlib,              /* Aka --no-standard-libraries, or
75                                    -nodefaultlibs. */
76   OPTION_o,                     /* Aka --output. */
77   OPTION_S,                     /* Aka --assemble. */
78   OPTION_syntax_only,           /* -fsyntax-only. */
79   OPTION_v,                     /* Aka --verbose. */
80   OPTION_version,               /* --version. */
81   OPTION_V,                     /* Aka --use-version. */
82   OPTION_x,                     /* Aka --language. */
83   OPTION_                       /* Unrecognized or unimportant. */
84 } Option;
85
86 /* The original argument list and related info is copied here.  */
87 static int g77_xargc;
88 static char **g77_xargv;
89 static void (*g77_fn)();
90
91 /* The new argument list will be built here.  */
92 static int g77_newargc;
93 static char **g77_newargv;
94
95 extern char *xmalloc PROTO((size_t));
96
97 extern char *version_string;
98
99 /* --- This comes from gcc.c (2.8.1) verbatim: */
100
101 /* This defines which switch letters take arguments.  */
102
103 #define DEFAULT_SWITCH_TAKES_ARG(CHAR)      \
104   ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
105    || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
106    || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
107    || (CHAR) == 'L' || (CHAR) == 'A')
108
109 #ifndef SWITCH_TAKES_ARG
110 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
111 #endif
112
113 /* This defines which multi-letter switches take arguments.  */
114
115 #define DEFAULT_WORD_SWITCH_TAKES_ARG(STR)              \
116  (!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext")      \
117   || !strcmp (STR, "Tbss") || !strcmp (STR, "include")  \
118   || !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
119   || !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
120   || !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
121   || !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
122
123 #ifndef WORD_SWITCH_TAKES_ARG
124 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
125 #endif
126
127 /* --- End of verbatim.  */
128
129 /* Assumes text[0] == '-'.  Returns number of argv items that belong to
130    (and follow) this one, an option id for options important to the
131    caller, and a pointer to the first char of the arg, if embedded (else
132    returns NULL, meaning no arg or it's the next argv).
133
134    Note that this also assumes gcc.c's pass converting long options
135    to short ones, where available, has already been run.  */
136
137 static void
138 lookup_option (xopt, xskip, xarg, text)
139      Option *xopt;
140      int *xskip;
141      char **xarg;
142      char *text;
143 {
144   Option opt = OPTION_;
145   int skip;
146   char *arg = NULL;
147
148   if ((skip = SWITCH_TAKES_ARG (text[1])))
149     skip -= (text[2] != '\0');  /* See gcc.c. */
150
151   if (text[1] == 'B')
152     opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2;
153   else if (text[1] == 'b')
154     opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2;
155   else if ((text[1] == 'c') && (text[2] == '\0'))
156     opt = OPTION_c, skip = 0;
157   else if ((text[1] == 'E') && (text[2] == '\0'))
158     opt = OPTION_E, skip = 0;
159   else if (text[1] == 'i')
160     opt = OPTION_i, skip = 0;
161   else if (text[1] == 'l')
162     opt = OPTION_l;
163   else if (text[1] == 'L')
164     opt = OPTION_L, arg = text + 2;
165   else if (text[1] == 'o')
166     opt = OPTION_o;
167   else if ((text[1] == 'S') && (text[2] == '\0'))
168     opt = OPTION_S, skip = 0;
169   else if (text[1] == 'V')
170     opt = OPTION_V, skip = (text[2] == '\0');
171   else if ((text[1] == 'v') && (text[2] == '\0'))
172     opt = OPTION_v, skip = 0;
173   else if (text[1] == 'x')
174     opt = OPTION_x, arg = text + 2;
175   else
176     {
177       if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0)  /* See gcc.c. */
178         ;
179       else if (! strncmp (text, "-fdriver", 8))  /* Really --driver!! */
180         opt = OPTION_driver;    /* Never mind arg, this is unsupported. */
181       else if (! strcmp (text, "-fhelp"))  /* Really --help!! */
182         opt = OPTION_help;
183       else if (! strcmp (text, "-M"))
184         opt = OPTION_M;
185       else if (! strcmp (text, "-MM"))
186         opt = OPTION_MM;
187       else if (! strcmp (text, "-nostdlib")
188                || ! strcmp (text, "-nodefaultlibs"))
189         opt = OPTION_nostdlib;
190       else if (! strcmp (text, "-fsyntax-only"))
191         opt = OPTION_syntax_only;
192       else if (! strcmp (text, "-dumpversion"))
193         opt = OPTION_version;
194       else if (! strcmp (text, "-Xlinker")
195                || ! strcmp (text, "-specs"))
196         skip = 1;
197       else
198         skip = 0;
199     }
200
201   if (xopt != NULL)
202     *xopt = opt;
203   if (xskip != NULL)
204     *xskip = skip;
205   if (xarg != NULL)
206     {
207       if ((arg != NULL)
208           && (arg[0] == '\0'))
209         *xarg = NULL;
210       else
211         *xarg = arg;
212     }
213 }
214
215 /* Append another argument to the list being built.  As long as it is
216    identical to the corresponding arg in the original list, just increment
217    the new arg count.  Otherwise allocate a new list, etc.  */
218
219 static void
220 append_arg (arg)
221      char *arg;
222 {
223   static int newargsize;
224
225 #if 0
226   fprintf (stderr, "`%s'\n", arg);
227 #endif
228
229   if (g77_newargv == g77_xargv
230       && g77_newargc < g77_xargc
231       && (arg == g77_xargv[g77_newargc]
232           || ! strcmp (arg, g77_xargv[g77_newargc])))
233     {
234       ++g77_newargc;
235       return;                   /* Nothing new here. */
236     }
237
238   if (g77_newargv == g77_xargv)
239     {                           /* Make new arglist. */
240       int i;
241
242       newargsize = (g77_xargc << 2) + 20;       /* This should handle all. */
243       g77_newargv = (char **) xmalloc (newargsize * sizeof (char *));
244
245       /* Copy what has been done so far.  */
246       for (i = 0; i < g77_newargc; ++i)
247         g77_newargv[i] = g77_xargv[i];
248     }
249
250   if (g77_newargc == newargsize)
251     (*g77_fn) ("overflowed output arg list for `%s'", arg);
252
253   g77_newargv[g77_newargc++] = arg;
254 }
255
256 void
257 lang_specific_driver (fn, in_argc, in_argv, in_added_libraries)
258      void (*fn)();
259      int *in_argc;
260      char ***in_argv;
261      int *in_added_libraries;
262 {
263   int argc = *in_argc;
264   char **argv = *in_argv;
265   int i;
266   int verbose = 0;
267   Option opt;
268   int skip;
269   char *arg;
270
271   /* This will be NULL if we encounter a situation where we should not
272      link in libf2c.  */
273   char *library = FORTRAN_LIBRARY;
274
275   /* This will become 0 if anything other than -v and kin (like -V)
276      is seen, meaning the user is trying to accomplish something.
277      If it remains nonzero, and the user wants version info, add stuff to
278      the command line to make gcc invoke all the appropriate phases
279      to get all the version info.  */
280   int add_version_magic = 1;
281
282   /* 0 => -xnone in effect.
283      1 => -xfoo in effect.  */
284   int saw_speclang = 0;
285
286   /* 0 => initial/reset state
287      1 => last arg was -l<library>
288      2 => last two args were -l<library> -lm.  */
289   int saw_library = 0;
290
291   /* The number of input and output files in the incoming arg list.  */
292   int n_infiles = 0;
293   int n_outfiles = 0;
294
295 #if 0
296   fprintf (stderr, "Incoming:");
297   for (i = 0; i < argc; i++)
298     fprintf (stderr, " %s", argv[i]);
299   fprintf (stderr, "\n");
300 #endif
301
302   g77_xargc = argc;
303   g77_xargv = argv;
304   g77_newargc = 0;
305   g77_newargv = argv;
306   g77_fn = fn;
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           add_version_magic = 0;
328           continue;
329         }
330
331       if ((argv[i][0] != '-') || (argv[i][1] == '\0'))
332         {
333           ++n_infiles;
334           add_version_magic = 0;
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           add_version_magic = 0;
353           break;
354
355         case OPTION_l:
356           ++n_infiles;
357           add_version_magic = 0;
358           break;
359
360         case OPTION_o:
361           ++n_outfiles;
362           add_version_magic = 0;
363           break;
364
365         case OPTION_v:
366           if (! verbose)
367             fprintf (stderr, "g77 version %s (from FSF-g77 version %s)\n",
368                      version_string, ffe_version_string);
369           verbose = 1;
370           break;
371
372         case OPTION_b:
373         case OPTION_B:
374         case OPTION_L:
375         case OPTION_i:
376         case OPTION_V:
377           /* These options are useful in conjunction with -v to get
378              appropriate version info.  */
379           break;
380
381         case OPTION_version:
382           printf ("\
383 GNU Fortran %s\n\
384 Copyright (C) 1997 Free Software Foundation, Inc.\n\
385 For more version information on components of the GNU Fortran\n\
386 compilation system, especially useful when reporting bugs,\n\
387 type the command `g77 --verbose'.\n\
388 \n\
389 GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
390 You may redistribute copies of GNU Fortran\n\
391 under the terms of the GNU General Public License.\n\
392 For more information about these matters, see the file named COPYING\n\
393 or type the command `info -f g77 Copying'.\n\
394 ", ffe_version_string);
395           exit (0);
396           break;
397
398         case OPTION_help:
399           /* Let gcc.c handle this, as the egcs version has a really
400              cool facility for handling --help and --verbose --help.  */
401           return;
402
403 #if 0
404           printf ("\
405 Usage: g77 [OPTION]... FORTRAN-SOURCE...\n\
406 \n\
407 Compile and link Fortran source code to produce an executable program,\n\
408 which by default is named `a.out', and can be invoked with the UNIX\n\
409 command `./a.out'.\n\
410 \n\
411 Options:\n\
412 --debug                include debugging information in executable.\n\
413 --help                 display this help and exit.\n\
414 --optimize[=LEVEL]     take extra time and memory to make generated\n\
415                          executable run faster.  LEVEL is 0 for no\n\
416                          optimization, 1 for normal optimization, and\n\
417                          increases through 3 for more optimization.\n\
418 --output=PROGRAM       name the executable PROGRAM instead of a.out;\n\
419                          invoke with the command `./PROGRAM'.\n\
420 --version              display version information and exit.\n\
421 \n\
422 Many other options exist to tailor the compilation process, specify\n\
423 the dialect of the Fortran source code, specify details of the\n\
424 code-generation methodology, and so on.\n\
425 \n\
426 For more information on g77 and gcc, type the commands `info -f g77'\n\
427 and `info -f gcc' to read the Info documentation.\n\
428 \n\
429 Report bugs to <egcs-bugs@cygnus.org>.\n");
430           exit (0);
431           break;
432 #endif
433
434         case OPTION_driver:
435           (*fn) ("--driver no longer supported", argv[i]);
436           break;
437
438         default:
439           add_version_magic = 0;
440           break;
441         }
442
443       /* This is the one place we check for missing arguments in the
444          program.  */
445
446       if (i + skip < argc)
447         i += skip;
448       else
449         (*fn) ("argument to `%s' missing", argv[i]);
450     }
451
452   if ((n_outfiles != 0) && (n_infiles == 0))
453     (*fn) ("No input files; unwilling to write output files");
454
455   /* Second pass through arglist, transforming arguments as appropriate.  */
456
457   append_arg (argv[0]); /* Start with command name, of course. */
458
459   for (i = 1; i < argc; ++i)
460     {
461       if (argv[i][0] == '\0')
462         {
463           append_arg (argv[i]); /* Interesting.  Just append as is. */
464           continue;
465         }
466
467       if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
468         {
469           /* Not a filename or library. */
470
471           if (saw_library == 1) /* -l<library>. */
472             append_arg (MATH_LIBRARY);
473
474           saw_library = 0;
475
476           lookup_option (&opt, &skip, &arg, argv[i]);
477
478           if (argv[i][1] == '\0')
479             {
480               append_arg (argv[i]);     /* "-" == Standard input. */
481               continue;
482             }
483
484           if (opt == OPTION_x)
485             {
486               /* Track input language. */
487               char *lang;
488
489               if (arg == NULL)
490                 lang = argv[i+1];
491               else
492                 lang = arg;
493
494               saw_speclang = (strcmp (lang, "none") != 0);
495             }
496
497           append_arg (argv[i]);
498
499           for (; skip != 0; --skip)
500             append_arg (argv[++i]);
501
502           continue;
503         }
504
505       /* A filename/library, not an option. */
506
507       if (saw_speclang)
508         saw_library = 0;        /* -xfoo currently active. */
509       else
510         {                       /* -lfoo or filename. */
511           if (strcmp (argv[i], MATH_LIBRARY) == 0
512 #ifdef ALT_LIBM
513               || strcmp (argv[i], ALT_LIBM) == 0
514 #endif
515               )
516             {
517               if (saw_library == 1)
518                 saw_library = 2;        /* -l<library> -lm. */
519               else
520                 append_arg (FORTRAN_LIBRARY);
521             }
522           else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
523             saw_library = 1;    /* -l<library>. */
524           else
525             {           /* Other library, or filename. */
526               if (saw_library == 1)
527                 append_arg (MATH_LIBRARY);
528               saw_library = 0;
529             }
530         }
531       append_arg (argv[i]);
532     }
533
534   /* Append `-lg2c -lm' as necessary.  */
535
536   if (! add_version_magic && library)
537     {                           /* Doing a link and no -nostdlib. */
538       if (saw_speclang)
539         append_arg ("-xnone");
540
541       switch (saw_library)
542         {
543         case 0:
544           append_arg (library);
545         case 1:
546           append_arg (MATH_LIBRARY);
547         default:
548           break;
549         }
550     }
551   else if (add_version_magic && verbose)
552     {
553       append_arg ("-c");
554       append_arg ("-xf77-version");
555       append_arg ("/dev/null");
556       append_arg ("-xnone");
557     }
558
559   if (verbose
560       && g77_newargv != g77_xargv)
561     {
562       fprintf (stderr, "Driving:");
563       for (i = 0; i < g77_newargc; i++)
564         fprintf (stderr, " %s", g77_newargv[i]);
565       fprintf (stderr, "\n");
566     }
567
568   *in_argc = g77_newargc;
569   *in_argv = g77_newargv;
570 }
571
572 /* Called before linking.  Returns 0 on success and -1 on failure. */
573 int lang_specific_pre_link ()  /* Not used for F77. */
574 {
575   return 0;
576 }
577
578 /* Number of extra output files that lang_specific_pre_link may generate. */
579 int lang_specific_extra_outfiles = 0;  /* Not used for F77. */