OSDN Git Service

PR 31050
[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, 2006, 2007
3    Free 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, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.  */
21
22 /* This file is copied more or less verbatim from g77.  */
23 /* This file contains a filter for the main `gcc' driver, which is
24    replicated for the `gfortran' driver by adding this filter.  The purpose
25    of this filter is to be basically identical to gcc (in that
26    it faithfully passes all of the original arguments to gcc) but,
27    unless explicitly overridden by the user in certain ways, ensure
28    that the needs of the language supported by this wrapper are met.
29
30    For GNU Fortran 95(gfortran), we do the following to the argument list
31    before passing it to `gcc':
32
33    1.  Make sure `-lgfortran -lm' is at the end of the list.
34
35    2.  Make sure each time `-lgfortran' or `-lm' is seen, it forms
36        part of the series `-lgfortran -lm'.
37
38    #1 and #2 are not done if `-nostdlib' or any option that disables
39    the linking phase is present, or if `-xfoo' is in effect.  Note that
40    a lack of source files or -l options disables linking.
41
42    This program was originally made out of gcc/cp/g++spec.c, but the
43    way it builds the new argument list was rewritten so it is much
44    easier to maintain, improve the way it decides to add or not add
45    extra arguments, etc.  And several improvements were made in the
46    handling of arguments, primarily to make it more consistent with
47    `gcc' itself.  */
48
49 #include "config.h"
50 #include "system.h"
51 #include "gcc.h"
52
53 #include "coretypes.h"
54 #include "tm.h"
55 #include "intl.h"
56
57 #ifndef MATH_LIBRARY
58 #define MATH_LIBRARY "-lm"
59 #endif
60
61 #ifndef FORTRAN_INIT
62 #define FORTRAN_INIT "-lgfortranbegin"
63 #endif
64
65 #ifndef FORTRAN_LIBRARY
66 #define FORTRAN_LIBRARY "-lgfortran"
67 #endif
68
69 /* Options this driver needs to recognize, not just know how to
70    skip over.  */
71 typedef enum
72 {
73   OPTION_b,                     /* Aka --prefix.  */
74   OPTION_B,                     /* Aka --target.  */
75   OPTION_c,                     /* Aka --compile.  */
76   OPTION_E,                     /* Aka --preprocess.  */
77   OPTION_help,                  /* --help.  */
78   OPTION_i,                     /* -imacros, -include, -include-*.  */
79   OPTION_l,
80   OPTION_L,                     /* Aka --library-directory.  */
81   OPTION_nostdlib,              /* Aka --no-standard-libraries, or
82                                    -nodefaultlibs.  */
83   OPTION_o,                     /* Aka --output.  */
84   OPTION_S,                     /* Aka --assemble.  */
85   OPTION_syntax_only,           /* -fsyntax-only.  */
86   OPTION_v,                     /* Aka --verbose.  */
87   OPTION_version,               /* --version.  */
88   OPTION_V,                     /* Aka --use-version.  */
89   OPTION_x,                     /* Aka --language.  */
90   OPTION_                       /* Unrecognized or unimportant.  */
91 }
92 Option;
93
94 /* The original argument list and related info is copied here.  */
95 static int g77_xargc;
96 static const char *const *g77_xargv;
97 static void lookup_option (Option *, int *, const char **, const char *);
98 static void append_arg (const char *);
99
100 /* The new argument list will be built here.  */
101 static int g77_newargc;
102 static const char **g77_newargv;
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 ("GNU Fortran (GCC) %s\n", version_string);
349           printf ("Copyright %s 2007 Free Software Foundation, Inc.\n\n",
350                   _("(C)"));
351           printf (_("GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
352 You may redistribute copies of GNU Fortran\n\
353 under the terms of the GNU General Public License.\n\
354 For more information about these matters, see the file named COPYING\n\n"));
355           exit (0);
356           break;
357
358         case OPTION_help:
359           /* Let gcc.c handle this, as it has a really
360              cool facility for handling --help and --verbose --help.  */
361           return;
362
363         default:
364           break;
365         }
366
367       /* This is the one place we check for missing arguments in the
368          program.  */
369
370       if (i + skip < argc)
371         i += skip;
372       else
373         fatal ("argument to '%s' missing", argv[i]);
374     }
375
376   if ((n_outfiles != 0) && (n_infiles == 0))
377     fatal ("no input files; unwilling to write output files");
378
379   /* If there are no input files, no need for the library.  */
380   if (n_infiles == 0)
381     library = 0;
382
383   /* Second pass through arglist, transforming arguments as appropriate.  */
384
385   append_arg (argv[0]);         /* Start with command name, of course.  */
386
387   for (i = 1; i < argc; ++i)
388     {
389       if (argv[i][0] == '\0')
390         {
391           append_arg (argv[i]); /* Interesting.  Just append as is.  */
392           continue;
393         }
394
395       if ((argv[i][0] == '-') && (argv[i][1] == 'M'))
396         {
397           char *p;
398
399           if (argv[i][2] == '\0')
400             {
401               p = XNEWVEC (char, strlen (argv[i + 1]) + 2);
402               p[0] = '-';
403               p[1] = 'J';
404               strcpy (&p[2], argv[i + 1]);
405               i++;
406             }
407           else
408             {
409               p = XNEWVEC (char, strlen (argv[i]) + 1);
410               strcpy (p, argv[i]);
411             }
412           append_arg (p);
413           continue;
414         }
415
416       if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
417         {
418           /* Not a filename or library.  */
419
420           if (saw_library == 1 && need_math)    /* -l<library>.  */
421             append_arg (MATH_LIBRARY);
422
423           saw_library = 0;
424
425           lookup_option (&opt, &skip, &arg, argv[i]);
426
427           if (argv[i][1] == '\0')
428             {
429               append_arg (argv[i]);     /* "-" == Standard input.  */
430               continue;
431             }
432
433           if (opt == OPTION_x)
434             {
435               /* Track input language.  */
436               const char *lang;
437
438               if (arg == NULL)
439                 lang = argv[i + 1];
440               else
441                 lang = arg;
442
443               saw_speclang = (strcmp (lang, "none") != 0);
444             }
445
446           append_arg (argv[i]);
447
448           for (; skip != 0; --skip)
449             append_arg (argv[++i]);
450
451           continue;
452         }
453
454       /* A filename/library, not an option.  */
455
456       if (saw_speclang)
457         saw_library = 0;        /* -xfoo currently active.  */
458       else
459         {                       /* -lfoo or filename.  */
460           if (strcmp (argv[i], MATH_LIBRARY) == 0)
461             {
462               if (saw_library == 1)
463                 saw_library = 2;        /* -l<library> -lm.  */
464               else
465                 {
466                   if (0 == use_init)
467                     {
468                       append_arg (FORTRAN_INIT);
469                       use_init = 1;
470                     }
471                   append_arg (FORTRAN_LIBRARY);
472                 }
473             }
474           else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
475             saw_library = 1;    /* -l<library>.  */
476           else
477             {                   /* Other library, or filename.  */
478               if (saw_library == 1 && need_math)
479                 append_arg (MATH_LIBRARY);
480               saw_library = 0;
481             }
482         }
483       append_arg (argv[i]);
484     }
485
486   /* Append `-lg2c -lm' as necessary.  */
487
488   if (library)
489     {                           /* Doing a link and no -nostdlib.  */
490       if (saw_speclang)
491         append_arg ("-xnone");
492
493       switch (saw_library)
494         {
495         case 0:
496           if (0 == use_init)
497             {
498               append_arg (FORTRAN_INIT);
499               use_init = 1;
500             }
501           append_arg (library);
502         case 1:
503           if (need_math)
504             append_arg (MATH_LIBRARY);
505         default:
506           break;
507         }
508     }
509
510 #ifdef ENABLE_SHARED_LIBGCC
511   if (library)
512     {
513       int i;
514
515       for (i = 1; i < g77_newargc; i++)
516         if (g77_newargv[i][0] == '-')
517           if (strcmp (g77_newargv[i], "-static-libgcc") == 0
518               || strcmp (g77_newargv[i], "-static") == 0)
519             break;
520
521       if (i == g77_newargc)
522         append_arg ("-shared-libgcc");
523     }
524
525 #endif
526
527   if (verbose && g77_newargv != g77_xargv)
528     {
529       fprintf (stderr, _("Driving:"));
530       for (i = 0; i < g77_newargc; i++)
531         fprintf (stderr, " %s", g77_newargv[i]);
532       fprintf (stderr, "\n");
533     }
534
535   *in_argc = g77_newargc;
536   *in_argv = g77_newargv;
537 }
538
539
540 /* Called before linking.  Returns 0 on success and -1 on failure.  */
541 int
542 lang_specific_pre_link (void)   /* Not used for F77.  */
543 {
544   return 0;
545 }
546
547 /* Number of extra output files that lang_specific_pre_link may generate.  */
548 int lang_specific_extra_outfiles = 0;   /* Not used for F77.  */