OSDN Git Service

* gcc.c (process_command): Change year in 'gcc --version' to 2005.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / gfortranspec.c
1 /* Specific flags and argument handling of the Fortran front-end.
2    Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free
3    Software Foundation, Inc.
4
5 This file is part of GCC.
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) 2005 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.  */