OSDN Git Service

PR driver/35420
[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,
3    2007, 2008
4    Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
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 #ifdef HAVE_LD_STATIC_DYNAMIC
70 #define ADD_ARG_LIBGFORTRAN(arg) \
71   { \
72     if (static_lib && !static_linking) \
73       append_arg ("-Wl,-Bstatic"); \
74     append_arg (arg); \
75     if (static_lib && !static_linking) \
76       append_arg ("-Wl,-Bdynamic"); \
77   }
78 #else
79 #define ADD_ARG_LIBGFORTRAN(arg) append_arg (arg);
80 #endif
81
82
83 /* Options this driver needs to recognize, not just know how to
84    skip over.  */
85 typedef enum
86 {
87   OPTION_b,                     /* Aka --prefix.  */
88   OPTION_B,                     /* Aka --target.  */
89   OPTION_c,                     /* Aka --compile.  */
90   OPTION_E,                     /* Aka --preprocess.  */
91   OPTION_help,                  /* --help.  */
92   OPTION_i,                     /* -imacros, -include, -include-*.  */
93   OPTION_l,
94   OPTION_L,                     /* Aka --library-directory.  */
95   OPTION_nostdlib,              /* Aka --no-standard-libraries, or
96                                    -nodefaultlibs.  */
97   OPTION_o,                     /* Aka --output.  */
98   OPTION_S,                     /* Aka --assemble.  */
99   OPTION_static,                /* -static.  */
100   OPTION_static_libgfortran,    /* -static-libgfortran.  */
101   OPTION_syntax_only,           /* -fsyntax-only.  */
102   OPTION_v,                     /* Aka --verbose.  */
103   OPTION_version,               /* --version.  */
104   OPTION_V,                     /* Aka --use-version.  */
105   OPTION_x,                     /* Aka --language.  */
106   OPTION_                       /* Unrecognized or unimportant.  */
107 }
108 Option;
109
110 /* The original argument list and related info is copied here.  */
111 static int g77_xargc;
112 static const char *const *g77_xargv;
113 static void lookup_option (Option *, int *, const char **, const char *);
114 static void append_arg (const char *);
115
116 /* The new argument list will be built here.  */
117 static int g77_newargc;
118 static const char **g77_newargv;
119
120 /* --- This comes from gcc.c (2.8.1) verbatim: */
121
122 /* This defines which switch letters take arguments.  */
123
124 #ifndef SWITCH_TAKES_ARG
125 #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
126 #endif
127
128 /* This defines which multi-letter switches take arguments.  */
129
130 #ifndef WORD_SWITCH_TAKES_ARG
131 #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
132 #endif
133
134 /* --- End of verbatim.  */
135
136 /* Assumes text[0] == '-'.  Returns number of argv items that belong to
137    (and follow) this one, an option id for options important to the
138    caller, and a pointer to the first char of the arg, if embedded (else
139    returns NULL, meaning no arg or it's the next argv).
140
141    Note that this also assumes gcc.c's pass converting long options
142    to short ones, where available, has already been run.  */
143
144 static void
145 lookup_option (Option *xopt, int *xskip, const char **xarg, 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 (!strcmp (text, "-fhelp"))        /* Really --help!! */
183         opt = OPTION_help;
184       else if (!strcmp (text, "-nostdlib")
185                || !strcmp (text, "-nodefaultlibs"))
186         opt = OPTION_nostdlib;
187       else if (!strcmp (text, "-fsyntax-only"))
188         opt = OPTION_syntax_only;
189       else if (!strcmp (text, "-static-libgfortran"))
190         opt = OPTION_static_libgfortran;
191       else if (!strcmp (text, "-dumpversion"))
192         opt = OPTION_version;
193       else if (!strcmp (text, "-fversion"))     /* Really --version!! */
194         opt = OPTION_version;
195       else if (!strcmp (text, "-Xlinker") || !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) && (arg[0] == '\0'))
208         *xarg = NULL;
209       else
210         *xarg = arg;
211     }
212 }
213
214 /* Append another argument to the list being built.  As long as it is
215    identical to the corresponding arg in the original list, just increment
216    the new arg count.  Otherwise allocate a new list, etc.  */
217
218 static void
219 append_arg (const char *arg)
220 {
221   static int newargsize;
222
223 #if 0
224   fprintf (stderr, "`%s'\n", arg);
225 #endif
226
227   if (g77_newargv == g77_xargv
228       && g77_newargc < g77_xargc
229       && (arg == g77_xargv[g77_newargc]
230           || !strcmp (arg, g77_xargv[g77_newargc])))
231     {
232       ++g77_newargc;
233       return;                   /* Nothing new here.  */
234     }
235
236   if (g77_newargv == g77_xargv)
237     {                           /* Make new arglist.  */
238       int i;
239
240       newargsize = (g77_xargc << 2) + 20;       /* This should handle all.  */
241       g77_newargv = (const char **) xmalloc (newargsize * sizeof (char *));
242
243       /* Copy what has been done so far.  */
244       for (i = 0; i < g77_newargc; ++i)
245         g77_newargv[i] = g77_xargv[i];
246     }
247
248   if (g77_newargc == newargsize)
249     fatal ("overflowed output arg list for '%s'", arg);
250
251   g77_newargv[g77_newargc++] = arg;
252 }
253
254 void
255 lang_specific_driver (int *in_argc, const char *const **in_argv,
256                       int *in_added_libraries ATTRIBUTE_UNUSED)
257 {
258   int argc = *in_argc;
259   const char *const *argv = *in_argv;
260   int i;
261   int verbose = 0;
262   Option opt;
263   int skip;
264   const char *arg;
265
266   /* This will be NULL if we encounter a situation where we should not
267      link in libf2c.  */
268   const char *library = FORTRAN_LIBRARY;
269
270   /* 0 => -xnone in effect.
271      1 => -xfoo in effect.  */
272   int saw_speclang = 0;
273
274   /* 0 => initial/reset state
275      1 => last arg was -l<library>
276      2 => last two args were -l<library> -lm.  */
277   int saw_library = 0;
278
279   /* 0 => initial/reset state
280      1 => FORTRAN_INIT linked in */
281   int use_init = 0;
282
283   /* By default, we throw on the math library if we have one.  */
284   int need_math = (MATH_LIBRARY[0] != '\0');
285
286   /* Whether we should link a static libgfortran.  */
287   int static_lib = 0;
288
289   /* Whether we need to link statically.  */
290   int static_linking = 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_CAST2 (const char **, const char *const *, 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           /* These options disable linking entirely or linking of the
346              standard libraries.  */
347           library = 0;
348           break;
349
350         case OPTION_static_libgfortran:
351           static_lib = 1;
352           break;
353
354         case OPTION_static:
355           static_linking = 1;
356
357         case OPTION_l:
358           ++n_infiles;
359           break;
360
361         case OPTION_o:
362           ++n_outfiles;
363           break;
364
365         case OPTION_v:
366           verbose = 1;
367           break;
368
369         case OPTION_b:
370         case OPTION_B:
371         case OPTION_L:
372         case OPTION_i:
373         case OPTION_V:
374           /* These options are useful in conjunction with -v to get
375              appropriate version info.  */
376           break;
377
378         case OPTION_version:
379           printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
380           printf ("Copyright %s 2008 Free Software Foundation, Inc.\n\n",
381                   _("(C)"));
382           printf (_("GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
383 You may redistribute copies of GNU Fortran\n\
384 under the terms of the GNU General Public License.\n\
385 For more information about these matters, see the file named COPYING\n\n"));
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         default:
395           break;
396         }
397
398       /* This is the one place we check for missing arguments in the
399          program.  */
400
401       if (i + skip < argc)
402         i += skip;
403       else
404         fatal ("argument to '%s' missing", argv[i]);
405     }
406
407   if ((n_outfiles != 0) && (n_infiles == 0))
408     fatal ("no input files; unwilling to write output files");
409
410   /* If there are no input files, no need for the library.  */
411   if (n_infiles == 0)
412     library = 0;
413
414   /* Second pass through arglist, transforming arguments as appropriate.  */
415
416   append_arg (argv[0]);         /* Start with command name, of course.  */
417
418   for (i = 1; i < argc; ++i)
419     {
420       if (argv[i][0] == '\0')
421         {
422           append_arg (argv[i]); /* Interesting.  Just append as is.  */
423           continue;
424         }
425
426       if ((argv[i][0] == '-') && (argv[i][1] == 'M'))
427         {
428           char *p;
429
430           if (argv[i][2] == '\0')
431             {
432               p = XNEWVEC (char, strlen (argv[i + 1]) + 2);
433               p[0] = '-';
434               p[1] = 'J';
435               strcpy (&p[2], argv[i + 1]);
436               i++;
437             }
438           else
439             {
440               p = XNEWVEC (char, strlen (argv[i]) + 1);
441               strcpy (p, argv[i]);
442             }
443           append_arg (p);
444           continue;
445         }
446
447       if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
448         {
449           /* Not a filename or library.  */
450
451           if (saw_library == 1 && need_math)    /* -l<library>.  */
452             append_arg (MATH_LIBRARY);
453
454           saw_library = 0;
455
456           lookup_option (&opt, &skip, &arg, argv[i]);
457
458           if (argv[i][1] == '\0')
459             {
460               append_arg (argv[i]);     /* "-" == Standard input.  */
461               continue;
462             }
463
464           if (opt == OPTION_x)
465             {
466               /* Track input language.  */
467               const char *lang;
468
469               if (arg == NULL)
470                 lang = argv[i + 1];
471               else
472                 lang = arg;
473
474               saw_speclang = (strcmp (lang, "none") != 0);
475             }
476
477           append_arg (argv[i]);
478
479           for (; skip != 0; --skip)
480             append_arg (argv[++i]);
481
482           continue;
483         }
484
485       /* A filename/library, not an option.  */
486
487       if (saw_speclang)
488         saw_library = 0;        /* -xfoo currently active.  */
489       else
490         {                       /* -lfoo or filename.  */
491           if (strcmp (argv[i], MATH_LIBRARY) == 0)
492             {
493               if (saw_library == 1)
494                 saw_library = 2;        /* -l<library> -lm.  */
495               else
496                 {
497                   if (0 == use_init)
498                     {
499                       append_arg (FORTRAN_INIT);
500                       use_init = 1;
501                     }
502
503                   ADD_ARG_LIBGFORTRAN (FORTRAN_LIBRARY);
504                 }
505             }
506           else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
507             {
508               saw_library = 1;  /* -l<library>.  */
509               ADD_ARG_LIBGFORTRAN (argv[i]);
510               continue;
511             }
512           else
513             {                   /* Other library, or filename.  */
514               if (saw_library == 1 && need_math)
515                 append_arg (MATH_LIBRARY);
516               saw_library = 0;
517             }
518         }
519       append_arg (argv[i]);
520     }
521
522   /* Append `-lg2c -lm' as necessary.  */
523
524   if (library)
525     {                           /* Doing a link and no -nostdlib.  */
526       if (saw_speclang)
527         append_arg ("-xnone");
528
529       switch (saw_library)
530         {
531         case 0:
532           if (0 == use_init)
533             {
534               append_arg (FORTRAN_INIT);
535               use_init = 1;
536             }
537           ADD_ARG_LIBGFORTRAN (library);
538           /* Fall through.  */
539
540         case 1:
541           if (need_math)
542             append_arg (MATH_LIBRARY);
543         default:
544           break;
545         }
546     }
547
548 #ifdef ENABLE_SHARED_LIBGCC
549   if (library)
550     {
551       int i;
552
553       for (i = 1; i < g77_newargc; i++)
554         if (g77_newargv[i][0] == '-')
555           if (strcmp (g77_newargv[i], "-static-libgcc") == 0
556               || strcmp (g77_newargv[i], "-static") == 0)
557             break;
558
559       if (i == g77_newargc)
560         append_arg ("-shared-libgcc");
561     }
562
563 #endif
564
565   if (verbose && g77_newargv != g77_xargv)
566     {
567       fprintf (stderr, _("Driving:"));
568       for (i = 0; i < g77_newargc; i++)
569         fprintf (stderr, " %s", g77_newargv[i]);
570       fprintf (stderr, "\n");
571     }
572
573   *in_argc = g77_newargc;
574   *in_argv = g77_newargv;
575 }
576
577
578 /* Called before linking.  Returns 0 on success and -1 on failure.  */
579 int
580 lang_specific_pre_link (void)   /* Not used for F77.  */
581 {
582   return 0;
583 }
584
585 /* Number of extra output files that lang_specific_pre_link may generate.  */
586 int lang_specific_extra_outfiles = 0;   /* Not used for F77.  */