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