#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "gcc.h"
#define SPEC_FILE "libgcj.spec"
#define LANGSPEC (1<<1)
#define PARAM_ARG (1<<2)
#define JAVA_FILE_ARG (1<<3)
#define CLASS_FILE_ARG (1<<4)
#define ZIP_FILE_ARG (1<<5)
#define INDIRECT_FILE_ARG (1<<6)
#define RESOURCE_FILE_ARG (1<<7)
static char *find_spec_file (const char *);
static int verify_class_name (const char *);
static const char *main_class_name = NULL;
int lang_specific_extra_outfiles = 0;
int shared_libgcc = 1;
static const char jvgenmain_spec[] =
"jvgenmain %{D*} %b %m.i |\n\
cc1 %m.i %1 \
%{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
%{g*} %{O*} \
%{v:-version} %{pg:-p} %{p}\
%<fbounds-check %<fno-bounds-check\
%<fassume-compiled* %<fno-assume-compiled*\
%<fcompile-resource* %<fassert %<fno-assert \
%<femit-class-file %<femit-class-files %<fencoding*\
%<fuse-boehm-gc %<fhash-synchronization %<fjni\
%<findirect-dispatch %<fnew-verifier\
%<fno-store-check %<foutput-class-dir\
%<fclasspath* %<fCLASSPATH* %<fbootclasspath*\
%<fextdirs*\
%<fuse-divide-subroutine %<fno-use-divide-subroutine\
%<fcheck-references %<fno-check-references\
%<ffilelist-file\
%{f*} -fdollars-in-identifiers\
%{aux-info*}\
%{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
%{S:%W{o*}%{!o*:-o %b.s}}\
%(invoke_as)";
static char *
find_spec_file (const char *dir)
{
char *spec;
int x;
struct stat sb;
spec = xmalloc (strlen (dir) + sizeof (SPEC_FILE)
+ sizeof ("-specs=") + 4);
strcpy (spec, "-specs=");
x = strlen (spec);
strcat (spec, dir);
strcat (spec, "/");
strcat (spec, SPEC_FILE);
if (! stat (spec + x, &sb))
return spec;
free (spec);
return NULL;
}
#define JAVA_START_CHAR_P(c) (c < 128 && (ISIDST (c) || c == '$'))
#define JAVA_PART_CHAR_P(c) (c < 128 \
&& (ISIDNUM (c) \
|| c == '$' \
|| (c >= 0x00 && c <= 0x08) \
|| (c >= 0x0e && c <= 0x1b) \
|| c == 0x7f))
static int
verify_class_name (const char *name)
{
while (*name)
{
int ch = *name++;
if (ch < 0 || ! JAVA_START_CHAR_P (ch))
return 0;
while (*name)
{
ch = *name++;
if (ch < 0)
return 0;
if (ch == '.')
break;
if (! JAVA_PART_CHAR_P (ch))
return 0;
}
}
return 1;
}
void
lang_specific_driver (int *in_argc, const char *const **in_argv,
int *in_added_libraries)
{
int i, j;
int saw_verbose_flag = 0;
int saw_save_temps = 0;
int library = 1;
int combine_inputs = 0;
int java_files_count = 0;
int class_files_count = 0;
int zip_files_count = 0;
int indirect_files_count = 0;
char *filelist_filename = 0;
FILE *filelist_file = 0;
int added = 2;
const char *quote = NULL;
const char **arglist;
int saw_speclang = 0;
#if 0
const char *saw_math ATTRIBUTE_UNUSED = 0;
const char *saw_libc ATTRIBUTE_UNUSED = 0;
const char *saw_gc ATTRIBUTE_UNUSED = 0;
const char *saw_threadlib ATTRIBUTE_UNUSED = 0;
int saw_libgcj ATTRIBUTE_UNUSED = 0;
#endif
int saw_resource = 0;
int saw_C = 0;
int saw_o = 0;
int saw_O = 0;
int saw_g = 0;
int saw_D = 0;
int *args;
int argc;
const char *const *argv;
int added_libraries;
int num_args = 1;
int will_link = 1;
int want_spec_file = 1;
char *spec_file = NULL;
argc = *in_argc;
argv = *in_argv;
added_libraries = *in_added_libraries;
args = xcalloc (argc, sizeof (int));
for (i = 1; i < argc; i++)
{
if (quote)
{
quote = NULL;
args[i] |= PARAM_ARG;
continue;
}
if (argv[i][0] == '\0' || argv[i][1] == '\0')
continue;
if (argv[i][0] == '-')
{
if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
|| strcmp (argv[i], "-nodefaultlibs") == 0))
{
library = 0;
}
else if (strncmp (argv[i], "-fmain=", 7) == 0)
{
main_class_name = argv[i] + 7;
added--;
}
else if (strcmp (argv[i], "-fhelp") == 0)
want_spec_file = 0;
else if (strcmp (argv[i], "-v") == 0)
{
saw_verbose_flag = 1;
if (argc == 2)
{
library = 0;
}
}
else if (strncmp (argv[i], "-x", 2) == 0)
saw_speclang = 1;
else if (strcmp (argv[i], "-C") == 0)
{
saw_C = 1;
want_spec_file = 0;
if (library != 0)
added -= 2;
library = 0;
will_link = 0;
}
else if (strncmp (argv[i], "-fcompile-resource=", 19) == 0)
{
saw_resource = 1;
want_spec_file = 0;
if (library != 0)
--added;
library = 0;
will_link = 0;
}
else if (argv[i][1] == 'D')
saw_D = 1;
else if (argv[i][1] == 'g')
saw_g = 1;
else if (argv[i][1] == 'O')
saw_O = 1;
else if ((argv[i][2] == '\0'
&& strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
|| strcmp (argv[i], "-Tdata") == 0
|| strcmp (argv[i], "-MT") == 0
|| strcmp (argv[i], "-MF") == 0)
{
if (strcmp (argv[i], "-o") == 0)
saw_o = 1;
quote = argv[i];
}
else if (strcmp (argv[i], "-classpath") == 0
|| strcmp (argv[i], "-bootclasspath") == 0
|| strcmp (argv[i], "-CLASSPATH") == 0
|| strcmp (argv[i], "-encoding") == 0
|| strcmp (argv[i], "-extdirs") == 0)
{
quote = argv[i];
added -= 1;
}
else if (library != 0
&& ((argv[i][2] == '\0'
&& strchr ("cSEM", argv[i][1]) != NULL)
|| strcmp (argv[i], "-MM") == 0))
{
library = 0;
added -= 2;
will_link = 0;
}
else if (strcmp (argv[i], "-d") == 0)
{
quote = argv[i];
added -= 1;
}
else if (strcmp (argv[i], "-fsyntax-only") == 0
|| strcmp (argv[i], "--syntax-only") == 0)
{
want_spec_file = 0;
library = 0;
will_link = 0;
continue;
}
else if (strcmp (argv[i], "-save-temps") == 0)
saw_save_temps = 1;
else if (strcmp (argv[i], "-static-libgcc") == 0
|| strcmp (argv[i], "-static") == 0)
shared_libgcc = 0;
else
continue;
}
else
{
int len;
if (saw_speclang)
{
saw_speclang = 0;
continue;
}
if (saw_resource)
{
args[i] |= RESOURCE_FILE_ARG;
added += 2;
}
if (argv[i][0] == '@')
{
args[i] |= INDIRECT_FILE_ARG;
indirect_files_count++;
added += 2;
}
len = strlen (argv[i]);
if (len > 5 && strcmp (argv[i] + len - 5, ".java") == 0)
{
args[i] |= JAVA_FILE_ARG;
java_files_count++;
}
if (len > 6 && strcmp (argv[i] + len - 6, ".class") == 0)
{
args[i] |= CLASS_FILE_ARG;
class_files_count++;
}
if (len > 4
&& (strcmp (argv[i] + len - 4, ".zip") == 0
|| strcmp (argv[i] + len - 4, ".jar") == 0))
{
args[i] |= ZIP_FILE_ARG;
zip_files_count++;
}
}
}
if (quote)
fatal ("argument to '%s' missing\n", quote);
if (saw_D && ! main_class_name)
fatal ("can't specify '-D' without '--main'\n");
if (main_class_name && ! verify_class_name (main_class_name))
fatal ("'%s' is not a valid class name", main_class_name);
num_args = argc + added;
if (saw_resource)
{
if (! saw_o)
fatal ("--resource requires -o");
}
if (saw_C)
{
num_args += 3;
if (class_files_count + zip_files_count > 0)
{
error ("warning: already-compiled .class files ignored with -C");
num_args -= class_files_count + zip_files_count;
class_files_count = 0;
zip_files_count = 0;
}
num_args += 2;
if (saw_o)
fatal ("cannot specify both -C and -o");
}
if ((saw_o && java_files_count + class_files_count + zip_files_count > 1)
|| (saw_C && java_files_count > 1)
|| (indirect_files_count > 0
&& java_files_count + class_files_count + zip_files_count > 0))
combine_inputs = 1;
if (combine_inputs)
{
filelist_filename = make_temp_file ("jx");
if (filelist_filename == NULL)
fatal ("cannot create temporary file");
record_temp_file (filelist_filename, ! saw_save_temps, 0);
filelist_file = fopen (filelist_filename, "w");
if (filelist_file == NULL)
pfatal_with_name (filelist_filename);
num_args -= java_files_count + class_files_count + zip_files_count;
num_args += 2;
}
#if 0
if (! added && ! library && main_class_name == NULL && ! saw_C)
{
free (args);
return;
}
#endif
if (main_class_name)
{
lang_specific_extra_outfiles++;
}
if (saw_g + saw_O == 0)
num_args++;
num_args++;
if (combine_inputs || indirect_files_count > 0)
num_args += 1;
if (combine_inputs && indirect_files_count > 0)
fatal("using both @FILE with multiple files not implemented");
#ifndef ENABLE_SHARED_LIBGCC
shared_libgcc = 0;
#endif
num_args += shared_libgcc;
arglist = xmalloc ((num_args + 1) * sizeof (char *));
j = 0;
for (i = 0; i < argc; i++, j++)
{
arglist[j] = argv[i];
if ((args[i] & PARAM_ARG) || i == 0)
continue;
if ((args[i] & RESOURCE_FILE_ARG) != 0)
{
arglist[j++] = "-xjava";
arglist[j++] = argv[i];
arglist[j] = "-xnone";
}
if (strcmp (argv[i], "-classpath") == 0
|| strcmp (argv[i], "-bootclasspath") == 0
|| strcmp (argv[i], "-CLASSPATH") == 0
|| strcmp (argv[i], "-encoding") == 0
|| strcmp (argv[i], "-extdirs") == 0)
{
arglist[j] = concat ("-f", argv[i]+1, "=", argv[i+1], NULL);
i++;
continue;
}
if (strcmp (argv[i], "-d") == 0)
{
arglist[j] = concat ("-foutput-class-dir=", argv[i + 1], NULL);
++i;
continue;
}
if (spec_file == NULL && strncmp (argv[i], "-L", 2) == 0)
spec_file = find_spec_file (argv[i] + 2);
if (strncmp (argv[i], "-fmain=", 7) == 0)
{
if (! will_link)
fatal ("cannot specify 'main' class when not linking");
--j;
continue;
}
if ((args[i] & INDIRECT_FILE_ARG) != 0)
{
arglist[j++] = "-xjava";
arglist[j++] = argv[i]+1;
arglist[j] = "-xnone";
}
if ((args[i] & (CLASS_FILE_ARG|ZIP_FILE_ARG)) && saw_C)
{
--j;
continue;
}
if (combine_inputs
&& (args[i] & (CLASS_FILE_ARG|JAVA_FILE_ARG|ZIP_FILE_ARG)) != 0)
{
fputs (argv[i], filelist_file);
fputc ('\n', filelist_file);
--j;
continue;
}
}
if (combine_inputs || indirect_files_count > 0)
arglist[j++] = "-ffilelist-file";
if (combine_inputs)
{
if (fclose (filelist_file))
pfatal_with_name (filelist_filename);
arglist[j++] = "-xjava";
arglist[j++] = filelist_filename;
}
if (saw_g + saw_O == 0)
arglist[j++] = "-g1";
if (want_spec_file)
arglist[j++] = spec_file == NULL ? "-specs=libgcj.spec" : spec_file;
if (saw_C)
{
arglist[j++] = "-fsyntax-only";
arglist[j++] = "-femit-class-files";
arglist[j++] = "-S";
arglist[j++] = "-o";
arglist[j++] = "NONE";
}
if (shared_libgcc)
arglist[j++] = "-shared-libgcc";
arglist[j] = NULL;
*in_argc = j;
*in_argv = arglist;
*in_added_libraries = added_libraries;
}
int
lang_specific_pre_link (void)
{
int err;
if (main_class_name == NULL)
return 0;
set_input (concat (main_class_name, "main.c", NULL));
err = do_spec (jvgenmain_spec);
if (err == 0)
{
int i = n_infiles;
const char *generated = outfiles[i];
while (--i >= 0)
outfiles[i + 1] = outfiles[i];
outfiles[0] = generated;
}
return err;
}
const struct spec_function lang_specific_spec_functions[] =
{
{ 0, 0 }
};