OSDN Git Service

Merged gcj-eclipse branch to trunk.
[pf3gnuchains/gcc-fork.git] / gcc / java / jvspec.c
1 /* Specific flags and argument handling of the front-end of the 
2    GNU compiler for the Java(TM) language.
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
4    2005, 2006, 2007 Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC 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 2, or (at your option)
11 any later version.
12
13 GCC 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 COPYING.  If not, write to
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. 
22
23 Java and all Java-based marks are trademarks or registered trademarks
24 of Sun Microsystems, Inc. in the United States and other countries.
25 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
31 #include "gcc.h"
32 #include "jcf.h"
33
34 /* Name of spec file.  */
35 #define SPEC_FILE "libgcj.spec"
36
37 /* This bit is set if we saw a `-xfoo' language specification.  */
38 #define LANGSPEC        (1<<1)
39 /* True if this arg is a parameter to the previous option-taking arg. */
40 #define PARAM_ARG       (1<<2)
41 /* True if this arg is a .java input file name. */
42 #define JAVA_FILE_ARG   (1<<3)
43 /* True if this arg is a .class input file name. */
44 #define CLASS_FILE_ARG  (1<<4)
45 /* True if this arg is a .zip or .jar input file name. */
46 #define ZIP_FILE_ARG    (1<<5)
47 /* True if this arg is @FILE - where FILE contains a list of filenames. */
48 #define INDIRECT_FILE_ARG (1<<6)
49 /* True if this arg is a resource file.  */
50 #define RESOURCE_FILE_ARG (1<<7)
51
52 static char *find_spec_file (const char *);
53 static int verify_class_name (const char *);
54
55 static const char *main_class_name = NULL;
56 int lang_specific_extra_outfiles = 0;
57
58 /* True if we should add -shared-libgcc to the command-line.  */
59 int shared_libgcc = 1;
60
61 static const char jvgenmain_spec[] =
62   "jvgenmain %{findirect-dispatch} %{D*} %b %m.i |\n\
63    cc1 %m.i %1 \
64                    %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
65                    %{g*} %{O*} \
66                    %{v:-version} %{pg:-p} %{p}\
67                    %<fbounds-check %<fno-bounds-check\
68                    %<fassume-compiled* %<fno-assume-compiled*\
69                    %<fcompile-resource* %<fassert %<fno-assert \
70                    %<femit-class-file %<femit-class-files %<fencoding*\
71                    %<fuse-boehm-gc %<fhash-synchronization %<fjni\
72                    %<findirect-dispatch %<fnew-verifier\
73                    %<fno-store-check %<foutput-class-dir\
74                    %<fclasspath* %<fCLASSPATH* %<fbootclasspath*\
75                    %<fextdirs*\
76                    %<fuse-divide-subroutine %<fno-use-divide-subroutine\
77                    %<fcheck-references %<fno-check-references\
78                    %<ffilelist-file %<fsaw-java-file %<fsource* %<ftarget*\
79                    %{f*} -fdollars-in-identifiers\
80                    %{aux-info*}\
81                    %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
82                    %{S:%W{o*}%{!o*:-o %b.s}}\
83    %(invoke_as)";
84
85 /* Return full path name of spec file if it is in DIR, or NULL if
86    not.  */
87 static char *
88 find_spec_file (const char *dir)
89 {
90   char *spec;
91   int x;
92   struct stat sb;
93
94   spec = XNEWVEC (char, strlen (dir) + sizeof (SPEC_FILE)
95                   + sizeof ("-specs=") + 4);
96   strcpy (spec, "-specs=");
97   x = strlen (spec);
98   strcat (spec, dir);
99   strcat (spec, "/");
100   strcat (spec, SPEC_FILE);
101   if (! stat (spec + x, &sb))
102     return spec;
103   free (spec);
104   return NULL;
105 }
106
107 #define JAVA_START_CHAR_P(c) (c < 128 && (ISIDST (c) || c == '$'))
108 #define JAVA_PART_CHAR_P(c) (c < 128                                          \
109                              && (ISIDNUM (c)                                  \
110                                  || c == '$'                                  \
111                                  || (c >= 0x00 && c <= 0x08)                  \
112                                  || (c >= 0x0e && c <= 0x1b)                  \
113                                  || c == 0x7f))
114
115 /* Verify that NAME is a valid Java class name that might contain
116    `main'.  Return 0 on failure.  */
117 static int
118 verify_class_name (const char *name)
119 {
120   /* FIXME: what encoding do we use for command-line arguments?  For
121      now we assume plain ASCII, which of course is wrong.  */
122   while (*name)
123     {
124       int ch = *name++;
125       if (ch < 0 || ! JAVA_START_CHAR_P (ch))
126         return 0;
127       while (*name)
128         {
129           ch = *name++;
130           if (ch < 0)
131             return 0;
132           /* We found a break between class names.  Next character
133              must be an identifier start again.  */
134           if (ch == '.')
135             break;
136           if (! JAVA_PART_CHAR_P (ch))
137             return 0;
138         }
139     }
140
141   return 1;
142 }
143
144 void
145 lang_specific_driver (int *in_argc, const char *const **in_argv,
146                       int *in_added_libraries)
147 {
148   int i, j;
149
150   /* If nonzero, the user gave us the `-v' flag.  */
151   int saw_verbose_flag = 0;
152
153   int saw_save_temps = 0;
154
155   /* This will be 0 if we encounter a situation where we should not
156      link in libgcj.  */
157   int library = 1;
158
159   /* This will be 1 if multiple input files (.class and/or .java)
160      should be passed to a single jc1 invocation. */
161   int combine_inputs = 0;
162
163   /* Number of .java and .class source file arguments seen. */
164   int java_files_count = 0;
165   int class_files_count = 0;
166   /* Number of .zip or .jar file arguments seen. */
167   int zip_files_count = 0;
168   /* Number of '@FILES' arguments seen. */
169   int indirect_files_count = 0;
170
171   /* Name of file containing list of files to compile. */
172   char *filelist_filename = 0;
173
174   FILE *filelist_file = 0;
175
176   /* The number of arguments being added to what's in argv, other than
177      libraries.  */
178   int added = 2;
179
180   /* Used to track options that take arguments, so we don't go wrapping
181      those with -xc++/-xnone.  */
182   const char *quote = NULL;
183
184   /* The new argument list will be contained in this.  */
185   const char **arglist;
186
187   /* Nonzero if we saw a `-xfoo' language specification on the
188      command line.  Used to avoid adding our own -xc++ if the user
189      already gave a language for the file.  */
190   int saw_speclang = 0;
191
192   /* Saw --resource, -C or -o options, respectively. */
193   int saw_resource = 0;
194   int saw_C = 0;
195   int saw_o = 0;
196
197   /* Saw some -O* or -g* option, respectively. */
198   int saw_O = 0;
199   int saw_g = 0;
200
201   /* Saw a `-D' option.  */
202   int saw_D = 0;
203
204   /* An array used to flag each argument that needs a bit set for
205      LANGSPEC, MATHLIB, WITHLIBC, or GCLIB.  */
206   int *args;
207
208   /* The total number of arguments with the new stuff.  */
209   int argc;
210
211   /* The argument list.  */
212   const char *const *argv;
213
214   /* The number of libraries added in.  */
215   int added_libraries;
216
217   /* The total number of arguments having to do with classpath
218      setting.  */
219   int classpath_args = 0;
220
221   /* The total number of arguments with the new stuff.  */
222   int num_args = 1;
223
224   /* Nonzero if linking is supposed to happen.  */
225   int will_link = 1;
226
227   /* Nonzero if we want to find the spec file.  */
228   int want_spec_file = 1;
229
230   /* The argument we use to specify the spec file.  */
231   char *spec_file = NULL;
232
233   /* If linking, nonzero if the BC-ABI is in use.  */
234   int link_for_bc_abi = 0;
235
236   argc = *in_argc;
237   argv = *in_argv;
238   added_libraries = *in_added_libraries;
239
240   args = XCNEWVEC (int, argc);
241
242   for (i = 1; i < argc; i++)
243     {
244       /* If the previous option took an argument, we swallow it here.  */
245       if (quote)
246         {
247           quote = NULL;
248           args[i] |= PARAM_ARG;
249           continue;
250         }
251
252       /* We don't do this anymore, since we don't get them with minus
253          signs on them.  */
254       if (argv[i][0] == '\0' || argv[i][1] == '\0')
255         continue;
256
257       if (argv[i][0] == '-')
258         {
259           if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
260                                || strcmp (argv[i], "-nodefaultlibs") == 0))
261             {
262               library = 0;
263             }
264           else if (strncmp (argv[i], "-fmain=", 7) == 0)
265             {
266               main_class_name = argv[i] + 7;
267               added--;
268             }
269           else if (strcmp (argv[i], "-fhelp") == 0)
270             want_spec_file = 0;
271           else if (strcmp (argv[i], "-v") == 0)
272             {
273               saw_verbose_flag = 1;
274               if (argc == 2)
275                 {
276                   /* If they only gave us `-v', don't try to link
277                      in libgcj.  */ 
278                   library = 0;
279                 }
280             }
281           else if (strncmp (argv[i], "-x", 2) == 0)
282             saw_speclang = 1;
283           else if (strcmp (argv[i], "-C") == 0)
284             {
285               saw_C = 1;
286               want_spec_file = 0;
287               if (library != 0)
288                 added -= 2;
289               library = 0;
290               will_link = 0;
291             }
292           else if (strncmp (argv[i], "-fcompile-resource=", 19) == 0)
293             {
294               saw_resource = 1;
295               want_spec_file = 0;
296               if (library != 0)
297                 --added;
298               library = 0;
299               will_link = 0;
300             }
301           else if (argv[i][1] == 'D')
302             saw_D = 1;
303           else if (argv[i][1] == 'g')
304             saw_g = 1;
305           else if (argv[i][1] == 'O')
306             saw_O = 1;
307           else if ((argv[i][2] == '\0'
308                     && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
309                    || strcmp (argv[i], "-Tdata") == 0
310                    || strcmp (argv[i], "-MT") == 0
311                    || strcmp (argv[i], "-MF") == 0)
312             {
313               if (strcmp (argv[i], "-o") == 0)
314                 saw_o = 1;
315               quote = argv[i];
316             }
317           else if (strcmp (argv[i], "-classpath") == 0
318                    || strcmp (argv[i], "-bootclasspath") == 0
319                    || strcmp (argv[i], "-CLASSPATH") == 0
320                    || strcmp (argv[i], "-encoding") == 0
321                    || strcmp (argv[i], "-extdirs") == 0)
322             {
323               quote = argv[i];
324               added -= 1;
325             }
326           else if (library != 0 
327                    && ((argv[i][2] == '\0'
328                         && strchr ("cSEM", argv[i][1]) != NULL)
329                        || strcmp (argv[i], "-MM") == 0))
330             {
331               /* Don't specify libraries if we won't link, since that would
332                  cause a warning.  */
333               library = 0;
334               added -= 2;
335
336               /* Remember this so we can confirm -fmain option.  */
337               will_link = 0;
338             }
339           else if (strcmp (argv[i], "-d") == 0)
340             {
341               /* `-d' option is for javac compatibility.  */
342               quote = argv[i];
343               added -= 1;
344             }
345           else if (strcmp (argv[i], "-fsyntax-only") == 0
346                    || strcmp (argv[i], "--syntax-only") == 0)
347             {
348               library = 0;
349               will_link = 0;
350               continue;
351             }
352           else if (strcmp (argv[i], "-save-temps") == 0)
353             saw_save_temps = 1;
354           else if (strcmp (argv[i], "-static-libgcc") == 0
355                    || strcmp (argv[i], "-static") == 0)
356             shared_libgcc = 0;
357           else if (strcmp (argv[i], "-findirect-dispatch") == 0
358                    || strcmp (argv[i], "--indirect-dispatch") == 0)
359             {
360               link_for_bc_abi = 1;
361             }
362           else
363             /* Pass other options through.  */
364             continue;
365         }
366       else
367         {
368           int len; 
369
370           if (saw_speclang)
371             {
372               saw_speclang = 0;
373               continue;
374             }
375
376           if (saw_resource)
377             {
378               args[i] |= RESOURCE_FILE_ARG;
379               added += 2;  /* for -xjava and -xnone */
380             }
381
382           if (argv[i][0] == '@')
383             {
384               args[i] |= INDIRECT_FILE_ARG;
385               indirect_files_count++;
386               added += 2;  /* for -xjava and -xnone */
387             }
388
389           len = strlen (argv[i]);
390           if (len > 5 && strcmp (argv[i] + len - 5, ".java") == 0)
391             {
392               args[i] |= JAVA_FILE_ARG;
393               java_files_count++;
394             }
395           if (len > 6 && strcmp (argv[i] + len - 6, ".class") == 0)
396             {
397               args[i] |= CLASS_FILE_ARG;
398               class_files_count++;
399             }
400           if (len > 4
401               && (strcmp (argv[i] + len - 4, ".zip") == 0
402                   || strcmp (argv[i] + len - 4, ".jar") == 0))
403             {
404               args[i] |= ZIP_FILE_ARG;
405               zip_files_count++;
406             }
407         }
408     }
409
410   if (quote)
411     fatal ("argument to '%s' missing\n", quote);
412
413   if (saw_D && ! main_class_name)
414     fatal ("can't specify '-D' without '--main'\n");
415
416   if (main_class_name && ! verify_class_name (main_class_name))
417     fatal ("'%s' is not a valid class name", main_class_name);
418
419   num_args = argc + added;
420   if (saw_resource)
421     {
422       if (! saw_o)
423         fatal ("--resource requires -o");
424     }
425   if (saw_C)
426     {
427       num_args += 3;
428       if (class_files_count + zip_files_count > 0)
429         {
430           error ("warning: already-compiled .class files ignored with -C"); 
431           num_args -= class_files_count + zip_files_count;
432           class_files_count = 0;
433           zip_files_count = 0;
434         }
435       num_args += 2;  /* For -o NONE. */
436       if (saw_o)
437         fatal ("cannot specify both -C and -o");
438     }
439   if ((saw_o && java_files_count + class_files_count + zip_files_count > 1)
440       || (saw_C && java_files_count > 1)
441       || (indirect_files_count > 0
442           && java_files_count + class_files_count + zip_files_count > 0))
443     combine_inputs = 1;
444
445   if (combine_inputs)
446     {
447       filelist_filename = make_temp_file ("jx");
448       if (filelist_filename == NULL)
449         fatal ("cannot create temporary file");
450       record_temp_file (filelist_filename, ! saw_save_temps, 0);
451       filelist_file = fopen (filelist_filename, "w");
452       if (filelist_file == NULL)
453         pfatal_with_name (filelist_filename);
454       num_args -= java_files_count + class_files_count + zip_files_count;
455       num_args += 3;  /* for the combined arg "-xjava", and "-xnone" */
456     }
457
458   if (main_class_name)
459     {
460       lang_specific_extra_outfiles++;
461     }
462   if (saw_g + saw_O == 0)
463     num_args++;
464   num_args++;
465   /* An additional entry for the classpath.  */
466   num_args++;
467
468   if (combine_inputs || indirect_files_count > 0)
469     num_args += 1; /* for "-ffilelist-file" */
470   if (combine_inputs && indirect_files_count > 0)
471     fatal("using both @FILE with multiple files not implemented");
472
473   /* There's no point adding -shared-libgcc if we don't have a shared
474      libgcc.  */
475 #ifndef ENABLE_SHARED_LIBGCC
476   shared_libgcc = 0;
477 #endif  
478   
479   if (java_files_count > 0)
480     ++num_args;
481
482   num_args += shared_libgcc;
483
484   num_args += link_for_bc_abi;
485
486   arglist = XNEWVEC (const char *, num_args + 1);
487   j = 0;
488
489   arglist[j++] = argv[0];
490
491   if (combine_inputs || indirect_files_count > 0)
492     arglist[j++] = "-ffilelist-file";
493
494   if (combine_inputs)
495     {
496       arglist[j++] = "-xjava";
497       arglist[j++] = filelist_filename;
498       arglist[j++] = "-xnone";
499     }
500
501   if (java_files_count > 0)
502     arglist[j++] = "-fsaw-java-file";
503
504   jcf_path_init ();
505   for (i = 1; i < argc; i++, j++)
506     {
507       arglist[j] = argv[i];
508
509       if ((args[i] & PARAM_ARG))
510         continue;
511
512       if ((args[i] & RESOURCE_FILE_ARG) != 0)
513         {
514           arglist[j++] = "-xjava";
515           arglist[j++] = argv[i];
516           arglist[j] = "-xnone";
517         }
518
519       if (argv[i][1] == 'I')
520         {
521           jcf_path_include_arg (&argv[i][2]);
522           --j;
523           continue;
524         }
525       if (! strcmp (argv[i], "-classpath")
526           || ! strcmp (argv[i], "-CLASSPATH"))
527         {
528           jcf_path_classpath_arg (argv[i + 1]);
529           ++i;
530           --j;
531           continue;
532         }
533       if (! strcmp (argv[i], "-bootclasspath"))
534         {
535           jcf_path_bootclasspath_arg (argv[i + 1]);
536           ++i;
537           --j;
538           continue;
539         }
540       if (! strncmp (argv[i], "-fCLASSPATH=", 12)
541           || ! strncmp (argv[i], "-fclasspath=", 12))
542         {
543           char *p = strchr (argv[i], '=');
544           jcf_path_classpath_arg (p + 1);
545           --j;
546           continue;
547         }
548       if (! strncmp (argv[i], "-fbootclasspath=", 16))
549         {
550           char *p = strchr (argv[i], '=');
551           jcf_path_bootclasspath_arg (p + 1);
552           --j;
553           continue;
554         }
555       if (! strcmp (argv[i], "-extdirs"))
556         {
557           jcf_path_extdirs_arg (argv[i + 1]);
558           ++i;
559           --j;
560           continue;
561         }
562
563       if (strcmp (argv[i], "-encoding") == 0)
564         {
565           arglist[j] = concat ("-f", argv[i]+1, "=", argv[i+1], NULL);
566           i++;
567           continue;
568         }
569
570       if (strcmp (argv[i], "-d") == 0)
571         {
572           arglist[j] = concat ("-foutput-class-dir=", argv[i + 1], NULL);
573           ++i;
574           continue;
575         }
576
577       if (spec_file == NULL && strncmp (argv[i], "-L", 2) == 0)
578         spec_file = find_spec_file (argv[i] + 2);
579
580       if (strncmp (argv[i], "-fmain=", 7) == 0)
581         {
582           if (! will_link)
583             fatal ("cannot specify 'main' class when not linking");
584           --j;
585           continue;
586         }
587
588       if ((args[i] & INDIRECT_FILE_ARG) != 0)
589         {
590           arglist[j++] = "-xjava";
591           arglist[j++] = argv[i]+1;  /* Drop '@'. */
592           arglist[j] = "-xnone";
593         }
594
595       if ((args[i] & (CLASS_FILE_ARG|ZIP_FILE_ARG)) && saw_C)
596         {
597           --j;
598           continue;
599         }
600
601       if (combine_inputs
602           && (args[i] & (CLASS_FILE_ARG|JAVA_FILE_ARG|ZIP_FILE_ARG)) != 0)
603         {
604           fputs (argv[i], filelist_file);
605           fputc ('\n', filelist_file);
606           --j;
607           continue;
608         }
609   }
610
611   /* Handle classpath setting.  We specify the bootclasspath since
612      that requires the fewest changes to our existing code...  */
613   jcf_path_seal (0);
614   arglist[j++] = jcf_path_compute ("-fbootclasspath=");
615
616   if (combine_inputs)
617     {
618       if (fclose (filelist_file))
619         pfatal_with_name (filelist_filename);
620     }
621
622   /* If we saw no -O or -g option, default to -g1, for javac compatibility. */
623   if (saw_g + saw_O == 0)
624     arglist[j++] = "-g1";
625
626   /* Read the specs file corresponding to libgcj.
627      If we didn't find the spec file on the -L path, then we hope it
628      is somewhere in the standard install areas.  */
629   if (want_spec_file)
630     arglist[j++] = spec_file == NULL ? "-specs=libgcj.spec" : spec_file;
631
632   if (saw_C)
633     {
634       arglist[j++] = "-fsyntax-only";
635       arglist[j++] = "-femit-class-files";
636       arglist[j++] = "-S";
637       arglist[j++] = "-o";
638       arglist[j++] = "NONE";
639     }
640   
641   if (shared_libgcc)
642     arglist[j++] = "-shared-libgcc";
643
644   if (link_for_bc_abi)
645     arglist[j++] = "-s-bc-abi";
646
647   arglist[j] = NULL;
648
649   *in_argc = j;
650   *in_argv = arglist;
651   *in_added_libraries = added_libraries;
652 }
653
654 int
655 lang_specific_pre_link (void)
656 {
657   int err;
658   if (main_class_name == NULL)
659     return 0;
660   /* Append `main' to make the filename unique and allow
661
662         gcj --main=hello -save-temps hello.java
663
664      to work.  jvgenmain needs to strip this `main' to arrive at the correct
665      class name.  Append dummy `.c' that can be stripped by set_input so %b
666      is correct.  */ 
667   set_input (concat (main_class_name, "main.c", NULL));
668   err = do_spec (jvgenmain_spec);
669   if (err == 0)
670     {
671       /* Shift the outfiles array so the generated main comes first.
672          This is important when linking against (non-shared) libraries,
673          since otherwise we risk (a) nothing getting linked or
674          (b) 'main' getting picked up from a library. */
675       int i = n_infiles;
676       const char *generated = outfiles[i];
677       while (--i >= 0)
678         outfiles[i + 1] = outfiles[i];
679       outfiles[0] = generated;
680     }
681   return err;
682 }