#include "config.h"
#include "system.h"
#include "gcc.h"
#ifndef MATH_LIBRARY
#define MATH_LIBRARY "-lm"
#endif
#ifndef FORTRAN_INIT
#define FORTRAN_INIT "-lfrtbegin"
#endif
#ifndef FORTRAN_LIBRARY
#define FORTRAN_LIBRARY "-lg2c"
#endif
typedef enum
{
OPTION_b,
OPTION_B,
OPTION_c,
OPTION_driver,
OPTION_E,
OPTION_help,
OPTION_i,
OPTION_l,
OPTION_L,
OPTION_M,
OPTION_MM,
OPTION_nostdlib,
OPTION_o,
OPTION_S,
OPTION_syntax_only,
OPTION_v,
OPTION_version,
OPTION_V,
OPTION_x,
OPTION_
} Option;
static int g77_xargc;
static const char *const *g77_xargv;
static void lookup_option PARAMS ((Option *, int *, const char **,
const char *));
static void append_arg PARAMS ((const char *));
static int g77_newargc;
static const char **g77_newargv;
#define DEFAULT_SWITCH_TAKES_ARG(CHAR) \
((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
|| (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
|| (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
|| (CHAR) == 'L' || (CHAR) == 'A')
#ifndef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
#endif
#define DEFAULT_WORD_SWITCH_TAKES_ARG(STR) \
(!strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \
|| !strcmp (STR, "Tbss") || !strcmp (STR, "include") \
|| !strcmp (STR, "imacros") || !strcmp (STR, "aux-info") \
|| !strcmp (STR, "idirafter") || !strcmp (STR, "iprefix") \
|| !strcmp (STR, "iwithprefix") || !strcmp (STR, "iwithprefixbefore") \
|| !strcmp (STR, "isystem") || !strcmp (STR, "specs"))
#ifndef WORD_SWITCH_TAKES_ARG
#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
#endif
static void
lookup_option (xopt, xskip, xarg, text)
Option *xopt;
int *xskip;
const char **xarg;
const char *text;
{
Option opt = OPTION_;
int skip;
const char *arg = NULL;
if ((skip = SWITCH_TAKES_ARG (text[1])))
skip -= (text[2] != '\0');
if (text[1] == 'B')
opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2;
else if (text[1] == 'b')
opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2;
else if ((text[1] == 'c') && (text[2] == '\0'))
opt = OPTION_c, skip = 0;
else if ((text[1] == 'E') && (text[2] == '\0'))
opt = OPTION_E, skip = 0;
else if (text[1] == 'i')
opt = OPTION_i, skip = 0;
else if (text[1] == 'l')
opt = OPTION_l;
else if (text[1] == 'L')
opt = OPTION_L, arg = text + 2;
else if (text[1] == 'o')
opt = OPTION_o;
else if ((text[1] == 'S') && (text[2] == '\0'))
opt = OPTION_S, skip = 0;
else if (text[1] == 'V')
opt = OPTION_V, skip = (text[2] == '\0');
else if ((text[1] == 'v') && (text[2] == '\0'))
opt = OPTION_v, skip = 0;
else if (text[1] == 'x')
opt = OPTION_x, arg = text + 2;
else
{
if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0)
;
else if (! strncmp (text, "-fdriver", 8))
opt = OPTION_driver;
else if (! strcmp (text, "-fhelp"))
opt = OPTION_help;
else if (! strcmp (text, "-M"))
opt = OPTION_M;
else if (! strcmp (text, "-MM"))
opt = OPTION_MM;
else if (! strcmp (text, "-nostdlib")
|| ! strcmp (text, "-nodefaultlibs"))
opt = OPTION_nostdlib;
else if (! strcmp (text, "-fsyntax-only"))
opt = OPTION_syntax_only;
else if (! strcmp (text, "-dumpversion"))
opt = OPTION_version;
else if (! strcmp (text, "-fversion"))
opt = OPTION_version;
else if (! strcmp (text, "-Xlinker")
|| ! strcmp (text, "-specs"))
skip = 1;
else
skip = 0;
}
if (xopt != NULL)
*xopt = opt;
if (xskip != NULL)
*xskip = skip;
if (xarg != NULL)
{
if ((arg != NULL)
&& (arg[0] == '\0'))
*xarg = NULL;
else
*xarg = arg;
}
}
static void
append_arg (arg)
const char *arg;
{
static int newargsize;
#if 0
fprintf (stderr, "`%s'\n", arg);
#endif
if (g77_newargv == g77_xargv
&& g77_newargc < g77_xargc
&& (arg == g77_xargv[g77_newargc]
|| ! strcmp (arg, g77_xargv[g77_newargc])))
{
++g77_newargc;
return;
}
if (g77_newargv == g77_xargv)
{
int i;
newargsize = (g77_xargc << 2) + 20;
g77_newargv = (const char **) xmalloc (newargsize * sizeof (char *));
for (i = 0; i < g77_newargc; ++i)
g77_newargv[i] = g77_xargv[i];
}
if (g77_newargc == newargsize)
fatal ("overflowed output arg list for `%s'", arg);
g77_newargv[g77_newargc++] = arg;
}
void
lang_specific_driver (in_argc, in_argv, in_added_libraries)
int *in_argc;
const char *const **in_argv;
int *in_added_libraries ATTRIBUTE_UNUSED;
{
int argc = *in_argc;
const char *const *argv = *in_argv;
int i;
int verbose = 0;
Option opt;
int skip;
const char *arg;
const char *library = FORTRAN_LIBRARY;
int saw_speclang = 0;
int saw_library = 0;
int use_init = 0;
int need_math = (MATH_LIBRARY[0] != '\0');
int n_infiles = 0;
int n_outfiles = 0;
#if 0
fprintf (stderr, "Incoming:");
for (i = 0; i < argc; i++)
fprintf (stderr, " %s", argv[i]);
fprintf (stderr, "\n");
#endif
g77_xargc = argc;
g77_xargv = argv;
g77_newargc = 0;
g77_newargv = (const char **) argv;
for (i = 1; i < argc; ++i)
{
if ((argv[i][0] == '+') && (argv[i][1] == 'e'))
{
continue;
}
if ((argv[i][0] != '-') || (argv[i][1] == '\0'))
{
++n_infiles;
continue;
}
lookup_option (&opt, &skip, NULL, argv[i]);
switch (opt)
{
case OPTION_nostdlib:
case OPTION_c:
case OPTION_S:
case OPTION_syntax_only:
case OPTION_E:
case OPTION_M:
case OPTION_MM:
library = 0;
break;
case OPTION_l:
++n_infiles;
break;
case OPTION_o:
++n_outfiles;
break;
case OPTION_v:
verbose = 1;
break;
case OPTION_b:
case OPTION_B:
case OPTION_L:
case OPTION_i:
case OPTION_V:
break;
case OPTION_version:
printf ("\
GNU Fortran (GCC) %s\n\
Copyright (C) 2002 Free Software Foundation, Inc.\n\
\n\
GNU Fortran comes with NO WARRANTY, to the extent permitted by law.\n\
You may redistribute copies of GNU Fortran\n\
under the terms of the GNU General Public License.\n\
For more information about these matters, see the file named COPYING\n\
or type the command `info -f g77 Copying'.\n\
", version_string);
exit (0);
break;
case OPTION_help:
return;
case OPTION_driver:
fatal ("--driver no longer supported");
break;
default:
break;
}
if (i + skip < argc)
i += skip;
else
fatal ("argument to `%s' missing", argv[i]);
}
if ((n_outfiles != 0) && (n_infiles == 0))
fatal ("no input files; unwilling to write output files");
if (n_infiles == 0)
library = 0;
append_arg (argv[0]);
for (i = 1; i < argc; ++i)
{
if (argv[i][0] == '\0')
{
append_arg (argv[i]);
continue;
}
if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
{
if (saw_library == 1 && need_math)
append_arg (MATH_LIBRARY);
saw_library = 0;
lookup_option (&opt, &skip, &arg, argv[i]);
if (argv[i][1] == '\0')
{
append_arg (argv[i]);
continue;
}
if (opt == OPTION_x)
{
const char *lang;
if (arg == NULL)
lang = argv[i+1];
else
lang = arg;
saw_speclang = (strcmp (lang, "none") != 0);
}
append_arg (argv[i]);
for (; skip != 0; --skip)
append_arg (argv[++i]);
continue;
}
if (saw_speclang)
saw_library = 0;
else
{
if (strcmp (argv[i], MATH_LIBRARY) == 0
#ifdef ALT_LIBM
|| strcmp (argv[i], ALT_LIBM) == 0
#endif
)
{
if (saw_library == 1)
saw_library = 2;
else
{
if (0 == use_init)
{
append_arg (FORTRAN_INIT);
use_init = 1;
}
append_arg (FORTRAN_LIBRARY);
}
}
else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
saw_library = 1;
else
{
if (saw_library == 1 && need_math)
append_arg (MATH_LIBRARY);
saw_library = 0;
}
}
append_arg (argv[i]);
}
if (library)
{
if (saw_speclang)
append_arg ("-xnone");
switch (saw_library)
{
case 0:
if (0 == use_init)
{
append_arg (FORTRAN_INIT);
use_init = 1;
}
append_arg (library);
case 1:
if (need_math)
append_arg (MATH_LIBRARY);
default:
break;
}
}
#ifdef ENABLE_SHARED_LIBGCC
if (library)
{
int i;
for (i = 1; i < g77_newargc; i++)
if (g77_newargv[i][0] == '-')
if (strcmp (g77_newargv[i], "-static-libgcc") == 0
|| strcmp (g77_newargv[i], "-static") == 0)
break;
if (i == g77_newargc)
append_arg ("-shared-libgcc");
}
#endif
if (verbose
&& g77_newargv != g77_xargv)
{
fprintf (stderr, "Driving:");
for (i = 0; i < g77_newargc; i++)
fprintf (stderr, " %s", g77_newargv[i]);
fprintf (stderr, "\n");
}
*in_argc = g77_newargc;
*in_argv = g77_newargv;
}
int lang_specific_pre_link ()
{
return 0;
}
int lang_specific_extra_outfiles = 0;
const struct spec_function lang_specific_spec_functions[] =
{
{ 0, 0 }
};