9a3efeacd5f366b4d7e84bd4b9a995d35dfe628c
[platform/upstream/gcc.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 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. 
21
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25
26 #include "config.h"
27 #include "system.h"
28 #include "gcc.h"
29
30 /* Name of spec file.  */
31 #define SPEC_FILE "libgcj.spec"
32
33 /* This bit is set if we saw a `-xfoo' language specification.  */
34 #define LANGSPEC        (1<<1)
35 /* True if this arg is a parameter to the previous option-taking arg. */
36 #define PARAM_ARG       (1<<2)
37 /* True if this arg is a .java input file name. */
38 #define JAVA_FILE_ARG   (1<<3)
39 /* True if this arg is a .class input file name. */
40 #define CLASS_FILE_ARG  (1<<4)
41 /* True if this arg is a .zip or .jar input file name. */
42 #define ZIP_FILE_ARG    (1<<5)
43 /* True if this arg is @FILE - where FILE contains a list of filenames. */
44 #define INDIRECT_FILE_ARG (1<<6)
45
46 static char *find_spec_file     PARAMS ((const char *));
47
48 static const char *main_class_name = NULL;
49 int lang_specific_extra_outfiles = 0;
50
51 /* True if we should add -shared-libgcc to the command-line.  */
52 int shared_libgcc = 1;
53
54 const char jvgenmain_spec[] =
55   "jvgenmain %{D*} %i %{!pipe:%umain.i} |\n\
56    cc1 %{!pipe:%Umain.i} %1 \
57                    %{!Q:-quiet} -dumpbase %b.c %{d*} %{m*} %{a*}\
58                    %{g*} %{O*} \
59                    %{v:-version} %{pg:-p} %{p}\
60                    %{<fbounds-check} %{<fno-bounds-check}\
61                    %{<fassume-compiled} %{<fno-assume-compiled}\
62                    %{<femit-class-file} %{<femit-class-files} %{<fencoding*}\
63                    %{<fuse-boehm-gc} %{<fhash-synchronization} %{<fjni}\
64                    %{<fclasspath*} %{<fCLASSPATH*} %{<foutput-class-dir}\
65                    %{<fuse-divide-subroutine} %{<fno-use-divide-subroutine}\
66                    %{f*} -fdollars-in-identifiers\
67                    %{aux-info*}\
68                    %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
69                    %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%Umain.s}} |\n\
70               %{!S:as %a %Y -o %d%w%umain%O %{!pipe:%Umain.s} %A\n }";
71
72 /* Return full path name of spec file if it is in DIR, or NULL if
73    not.  */
74 static char *
75 find_spec_file (dir)
76      const char *dir;
77 {
78   char *spec;
79   int x;
80   struct stat sb;
81
82   spec = (char *) xmalloc (strlen (dir) + sizeof (SPEC_FILE)
83                            + sizeof ("-specs=") + 4);
84   strcpy (spec, "-specs=");
85   x = strlen (spec);
86   strcat (spec, dir);
87   strcat (spec, "/");
88   strcat (spec, SPEC_FILE);
89   if (! stat (spec + x, &sb))
90     return spec;
91   free (spec);
92   return NULL;
93 }
94
95 void
96 lang_specific_driver (in_argc, in_argv, in_added_libraries)
97      int *in_argc;
98      const char *const **in_argv;
99      int *in_added_libraries;
100 {
101   int i, j;
102
103   /* If non-zero, the user gave us the `-v' flag.  */ 
104   int saw_verbose_flag = 0;
105
106   int saw_save_temps = 0;
107
108   /* This will be 0 if we encounter a situation where we should not
109      link in libgcj.  */
110   int library = 1;
111
112   /* This will be 1 if multiple input files (.class and/or .java)
113      should be passed to a single jc1 invocation. */
114   int combine_inputs = 0;
115
116   /* Index of last .java or .class argument. */
117   int last_input_index;
118
119   /* Number of .java and .class source file arguments seen. */
120   int java_files_count = 0;
121   int class_files_count = 0;
122   /* Number of .zip or .jar file arguments seen. */
123   int zip_files_count = 0;
124   /* Number of '@FILES' arguments seen. */
125   int indirect_files_count = 0;
126
127   /* Name of file containing list of files to compile. */
128   char *filelist_filename;
129
130   FILE *filelist_file;
131
132   /* The number of arguments being added to what's in argv, other than
133      libraries.  */
134   int added = 2;
135
136   /* Used to track options that take arguments, so we don't go wrapping
137      those with -xc++/-xnone.  */
138   const char *quote = NULL;
139
140   /* The new argument list will be contained in this.  */
141   const char **arglist;
142
143   /* Non-zero if we saw a `-xfoo' language specification on the
144      command line.  Used to avoid adding our own -xc++ if the user
145      already gave a language for the file.  */
146   int saw_speclang = 0;
147
148 #if 0
149   /* "-lm" or "-lmath" if it appears on the command line.  */
150   const char *saw_math ATTRIBUTE_UNUSED = 0;
151
152   /* "-lc" if it appears on the command line.  */
153   const char *saw_libc ATTRIBUTE_UNUSED = 0;
154
155   /* "-lgcjgc" if it appears on the command line.  */
156   const char *saw_gc ATTRIBUTE_UNUSED = 0;
157
158   /* Saw `-l' option for the thread library.  */
159   const char *saw_threadlib ATTRIBUTE_UNUSED = 0;
160
161   /* Saw `-lgcj' on command line.  */
162   int saw_libgcj ATTRIBUTE_UNUSED = 0;
163 #endif
164
165   /* Saw -C or -o option, respectively. */
166   int saw_C = 0;
167   int saw_o = 0;
168
169   /* Saw some -O* or -g* option, respectively. */
170   int saw_O = 0;
171   int saw_g = 0;
172
173   /* Saw a `-D' option.  */
174   int saw_D = 0;
175
176   /* An array used to flag each argument that needs a bit set for
177      LANGSPEC, MATHLIB, WITHLIBC, or GCLIB.  */
178   int *args;
179
180   /* The total number of arguments with the new stuff.  */
181   int argc;
182
183   /* The argument list.  */
184   const char *const *argv;
185
186   /* The number of libraries added in.  */
187   int added_libraries;
188
189   /* The total number of arguments with the new stuff.  */
190   int num_args = 1;
191
192   /* Non-zero if linking is supposed to happen.  */
193   int will_link = 1;
194
195   /* Non-zero if we want to find the spec file.  */
196   int want_spec_file = 1;
197
198   /* The argument we use to specify the spec file.  */
199   char *spec_file = NULL;
200
201   argc = *in_argc;
202   argv = *in_argv;
203   added_libraries = *in_added_libraries;
204
205   args = (int *) xcalloc (argc, sizeof (int));
206
207   for (i = 1; i < argc; i++)
208     {
209       /* If the previous option took an argument, we swallow it here.  */
210       if (quote)
211         {
212           quote = NULL;
213           args[i] |= PARAM_ARG;
214           continue;
215         }
216
217       /* We don't do this anymore, since we don't get them with minus
218          signs on them.  */
219       if (argv[i][0] == '\0' || argv[i][1] == '\0')
220         continue;
221
222       if (argv[i][0] == '-')
223         {
224           if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
225                                || strcmp (argv[i], "-nodefaultlibs") == 0))
226             {
227               library = 0;
228             }
229           else if (strncmp (argv[i], "-fmain=", 7) == 0)
230             {
231               main_class_name = argv[i] + 7;
232               added--;
233             }
234           else if (strcmp (argv[i], "-fhelp") == 0)
235             want_spec_file = 0;
236           else if (strcmp (argv[i], "-v") == 0)
237             {
238               saw_verbose_flag = 1;
239               if (argc == 2)
240                 {
241                   /* If they only gave us `-v', don't try to link
242                      in libgcj.  */ 
243                   library = 0;
244                 }
245             }
246           else if (strncmp (argv[i], "-x", 2) == 0)
247             saw_speclang = 1;
248           else if (strcmp (argv[i], "-C") == 0)
249             {
250               saw_C = 1;
251               want_spec_file = 0;
252               if (library != 0)
253                 added -= 2;
254               library = 0;
255               will_link = 0;
256             }
257           else if (argv[i][1] == 'D')
258             saw_D = 1;
259           else if (argv[i][1] == 'g')
260             saw_g = 1;
261           else if (argv[i][1] == 'O')
262             saw_O = 1;
263           else if ((argv[i][2] == '\0'
264                     && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
265                    || strcmp (argv[i], "-Tdata") == 0
266                    || strcmp (argv[i], "-MT") == 0
267                    || strcmp (argv[i], "-MF") == 0)
268             {
269               if (strcmp (argv[i], "-o") == 0)
270                 saw_o = 1;
271               quote = argv[i];
272             }
273           else if (strcmp(argv[i], "-classpath") == 0
274                    || strcmp(argv[i], "-CLASSPATH") == 0)
275             {
276               quote = argv[i];
277               added -= 1;
278             }
279           else if (library != 0 
280                    && ((argv[i][2] == '\0'
281                         && (char *) strchr ("cSEM", argv[i][1]) != NULL)
282                        || strcmp (argv[i], "-MM") == 0))
283             {
284               /* Don't specify libraries if we won't link, since that would
285                  cause a warning.  */
286               library = 0;
287               added -= 2;
288
289               /* Remember this so we can confirm -fmain option.  */
290               will_link = 0;
291             }
292           else if (strcmp (argv[i], "-d") == 0)
293             {
294               /* `-d' option is for javac compatibility.  */
295               quote = argv[i];
296               added -= 1;
297             }
298           else if (strcmp (argv[i], "-fsyntax-only") == 0
299                    || strcmp (argv[i], "--syntax-only") == 0)
300             {
301               want_spec_file = 0;
302               library = 0;
303               will_link = 0;
304               continue;
305             }
306           else if (strcmp (argv[i], "-save-temps") == 0)
307             saw_save_temps = 1;
308           else if (strcmp (argv[i], "-static-libgcc") == 0
309                    || strcmp (argv[i], "-static") == 0)
310             shared_libgcc = 0;
311           else
312             /* Pass other options through.  */
313             continue;
314         }
315       else
316         {
317           int len; 
318
319           if (saw_speclang)
320             {
321               saw_speclang = 0;
322               continue;
323             }
324
325           if (argv[i][0] == '@')
326             {
327               args[i] |= INDIRECT_FILE_ARG;
328               indirect_files_count++;
329               added += 2;  /* for -xjava and -xnone */
330             }
331
332           len = strlen (argv[i]);
333           if (len > 5 && strcmp (argv[i] + len - 5, ".java") == 0)
334             {
335               args[i] |= JAVA_FILE_ARG;
336               java_files_count++;
337               last_input_index = i;
338             }
339           if (len > 6 && strcmp (argv[i] + len - 6, ".class") == 0)
340             {
341               args[i] |= CLASS_FILE_ARG;
342               class_files_count++;
343               last_input_index = i;
344             }
345           if (len > 4
346               && (strcmp (argv[i] + len - 4, ".zip") == 0
347                   || strcmp (argv[i] + len - 4, ".jar") == 0))
348             {
349               args[i] |= ZIP_FILE_ARG;
350               zip_files_count++;
351               last_input_index = i;
352             }
353         }
354     }
355
356   if (quote)
357     fatal ("argument to `%s' missing\n", quote);
358
359   if (saw_D && ! main_class_name)
360     fatal ("can't specify `-D' without `--main'\n");
361
362   num_args = argc + added;
363   if (saw_C)
364     {
365       num_args += 3;
366       if (class_files_count + zip_files_count > 0)
367         {
368           error ("Warning: already-compiled .class files ignored with -C"); 
369           num_args -= class_files_count + zip_files_count;
370           class_files_count = 0;
371           zip_files_count = 0;
372         }
373       num_args += 2;  /* For -o NONE. */
374       if (saw_o)
375         fatal ("cannot specify both -C and -o");
376     }
377   if ((saw_o && java_files_count + class_files_count + zip_files_count > 1)
378       || (saw_C && java_files_count > 1)
379       || (indirect_files_count > 0
380           && java_files_count + class_files_count + zip_files_count > 0))
381     combine_inputs = 1;
382
383   if (combine_inputs)
384     {
385       filelist_filename = make_temp_file ("jx");
386       if (filelist_filename == NULL)
387         fatal ("cannot create temporary file");
388       record_temp_file (filelist_filename, ! saw_save_temps, 0);
389       filelist_file = fopen (filelist_filename, "w");
390       if (filelist_file == NULL)
391         pfatal_with_name (filelist_filename);
392       num_args -= java_files_count + class_files_count + zip_files_count;
393       num_args += 2;  /* for the combined arg and "-xjava" */
394     }
395   /* If we know we don't have to do anything, bail now.  */
396 #if 0
397   if (! added && ! library && main_class_name == NULL && ! saw_C)
398     {
399       free (args);
400       return;
401     }
402 #endif
403
404   if (main_class_name)
405     {
406       lang_specific_extra_outfiles++;
407     }
408   if (saw_g + saw_O == 0)
409     num_args++;
410   num_args++;
411
412   if (combine_inputs || indirect_files_count > 0)
413     num_args += 1; /* for "-ffilelist-file" */
414   if (combine_inputs && indirect_files_count > 0)
415     fatal("using both @FILE with multiple files not implemented");
416
417   /* There's no point adding -shared-libgcc if we don't have a shared
418      libgcc.  */
419 #ifndef ENABLE_SHARED_LIBGCC
420   shared_libgcc = 0;
421 #endif  
422   
423   num_args += shared_libgcc;
424
425   arglist = (const char **) xmalloc ((num_args + 1) * sizeof (char *));
426   j = 0;
427
428   for (i = 0; i < argc; i++, j++)
429     {
430       arglist[j] = argv[i];
431
432       if ((args[i] & PARAM_ARG) || i == 0)
433         continue;
434
435       if (strcmp (argv[i], "-classpath") == 0
436           || strcmp (argv[i], "-CLASSPATH") == 0)
437         {
438           char* patharg
439             = (char*) xmalloc (strlen (argv[i]) + strlen (argv[i+1]) + 3);
440           sprintf (patharg, "-f%s=%s", argv[i]+1, argv[i+1]);
441           arglist[j] = patharg;
442           i++;
443           continue;
444         }
445
446       if (strcmp (argv[i], "-d") == 0)
447         {
448           char *patharg = (char *) xmalloc (sizeof ("-foutput-class-dir=")
449                                             + strlen (argv[i + 1]) + 1);
450           sprintf (patharg, "-foutput-class-dir=%s", argv[i + 1]);
451           arglist[j] = patharg;
452           ++i;
453           continue;
454         }
455
456       if (spec_file == NULL && strncmp (argv[i], "-L", 2) == 0)
457         spec_file = find_spec_file (argv[i] + 2);
458
459       if (strncmp (argv[i], "-fmain=", 7) == 0)
460         {
461           if (! will_link)
462             fatal ("cannot specify `main' class when not linking");
463           --j;
464           continue;
465         }
466
467       if ((args[i] & INDIRECT_FILE_ARG) != 0)
468         {
469           arglist[j++] = "-xjava";
470           arglist[j++] = argv[i]+1;  /* Drop '@'. */
471           arglist[j] = "-xnone";
472         }
473
474       if ((args[i] & (CLASS_FILE_ARG|ZIP_FILE_ARG)) && saw_C)
475         {
476           --j;
477           continue;
478         }
479
480       if (combine_inputs
481           && (args[i] & (CLASS_FILE_ARG|JAVA_FILE_ARG|ZIP_FILE_ARG)) != 0)
482         {
483           fputs (argv[i], filelist_file);
484           fputc ('\n', filelist_file);
485           --j;
486           continue;
487         }
488   }
489
490   if (combine_inputs || indirect_files_count > 0)
491     arglist[j++] = "-ffilelist-file";
492
493   if (combine_inputs)
494     {
495       if (fclose (filelist_file))
496         pfatal_with_name (filelist_filename);
497       arglist[j++] = "-xjava";
498       arglist[j++] = filelist_filename;
499     }
500
501   /* If we saw no -O or -g option, default to -g1, for javac compatibility. */
502   if (saw_g + saw_O == 0)
503     arglist[j++] = "-g1";
504
505   /* Read the specs file corresponding to libgcj.
506      If we didn't find the spec file on the -L path, then we hope it
507      is somewhere in the standard install areas.  */
508   if (want_spec_file)
509     arglist[j++] = spec_file == NULL ? "-specs=libgcj.spec" : spec_file;
510
511   if (saw_C)
512     {
513       arglist[j++] = "-fsyntax-only";
514       arglist[j++] = "-femit-class-files";
515       arglist[j++] = "-S";
516       arglist[j++] = "-o";
517       arglist[j++] = "NONE";
518     }
519   
520   if (shared_libgcc)
521     arglist[j++] = "-shared-libgcc";
522
523   arglist[j] = NULL;
524
525   *in_argc = j;
526   *in_argv = arglist;
527   *in_added_libraries = added_libraries;
528 }
529
530 int
531 lang_specific_pre_link ()
532 {
533   if (main_class_name == NULL)
534     return 0;
535   input_filename = main_class_name;
536   input_filename_length = strlen (main_class_name);
537   return do_spec (jvgenmain_spec);
538 }