150397Sobrien/* Specific flags and argument handling of the C++ front-end.
2169689Skan   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
3132718Skan   Free Software Foundation, Inc.
450397Sobrien
5132718SkanThis file is part of GCC.
650397Sobrien
7132718SkanGCC is free software; you can redistribute it and/or modify
850397Sobrienit under the terms of the GNU General Public License as published by
950397Sobrienthe Free Software Foundation; either version 2, or (at your option)
1050397Sobrienany later version.
1150397Sobrien
12132718SkanGCC is distributed in the hope that it will be useful,
1350397Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1450397SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1550397SobrienGNU General Public License for more details.
1650397Sobrien
1750397SobrienYou should have received a copy of the GNU General Public License
18132718Skanalong with GCC; see the file COPYING.  If not, write to
19169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
20169689SkanBoston, MA 02110-1301, USA.  */
2150397Sobrien
2250397Sobrien#include "config.h"
2350397Sobrien#include "system.h"
24132718Skan#include "coretypes.h"
25132718Skan#include "tm.h"
2690075Sobrien#include "gcc.h"
2750397Sobrien
2850397Sobrien/* This bit is set if we saw a `-xfoo' language specification.  */
2950397Sobrien#define LANGSPEC	(1<<1)
3050397Sobrien/* This bit is set if they did `-lm' or `-lmath'.  */
3150397Sobrien#define MATHLIB		(1<<2)
3250397Sobrien/* This bit is set if they did `-lc'.  */
3350397Sobrien#define WITHLIBC	(1<<3)
3450397Sobrien
3550397Sobrien#ifndef MATH_LIBRARY
3650397Sobrien#define MATH_LIBRARY "-lm"
3750397Sobrien#endif
3896263Sobrien#ifndef MATH_LIBRARY_PROFILE
39169689Skan#define MATH_LIBRARY_PROFILE MATH_LIBRARY
4096263Sobrien#endif
4152284Sobrien
4252284Sobrien#ifndef LIBSTDCXX
4352284Sobrien#define LIBSTDCXX "-lstdc++"
4450397Sobrien#endif
4596263Sobrien#ifndef LIBSTDCXX_PROFILE
46169689Skan#define LIBSTDCXX_PROFILE LIBSTDCXX
4796263Sobrien#endif
4850397Sobrien
4950397Sobrienvoid
50132718Skanlang_specific_driver (int *in_argc, const char *const **in_argv,
51132718Skan		      int *in_added_libraries)
5250397Sobrien{
5350397Sobrien  int i, j;
5450397Sobrien
55117395Skan  /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
5696263Sobrien  int saw_profile_flag = 0;
5796263Sobrien
58117395Skan  /* If nonzero, the user gave us the `-v' flag.  */
5950397Sobrien  int saw_verbose_flag = 0;
6050397Sobrien
61132718Skan  /* This is a tristate:
62132718Skan     -1 means we should not link in libstdc++
63132718Skan     0  means we should link in libstdc++ if it is needed
64132718Skan     1  means libstdc++ is needed and should be linked in.  */
65132718Skan  int library = 0;
6650397Sobrien
6750397Sobrien  /* The number of arguments being added to what's in argv, other than
6850397Sobrien     libraries.  We use this to track the number of times we've inserted
6950397Sobrien     -xc++/-xnone.  */
70132718Skan  int added = 0;
7150397Sobrien
7250397Sobrien  /* Used to track options that take arguments, so we don't go wrapping
7350397Sobrien     those with -xc++/-xnone.  */
7490075Sobrien  const char *quote = NULL;
7550397Sobrien
7650397Sobrien  /* The new argument list will be contained in this.  */
7790075Sobrien  const char **arglist;
7850397Sobrien
79117395Skan  /* Nonzero if we saw a `-xfoo' language specification on the
8050397Sobrien     command line.  Used to avoid adding our own -xc++ if the user
8150397Sobrien     already gave a language for the file.  */
8250397Sobrien  int saw_speclang = 0;
8350397Sobrien
8450397Sobrien  /* "-lm" or "-lmath" if it appears on the command line.  */
8590075Sobrien  const char *saw_math = 0;
8650397Sobrien
8750397Sobrien  /* "-lc" if it appears on the command line.  */
8890075Sobrien  const char *saw_libc = 0;
8950397Sobrien
9050397Sobrien  /* An array used to flag each argument that needs a bit set for
9150397Sobrien     LANGSPEC, MATHLIB, or WITHLIBC.  */
9250397Sobrien  int *args;
9350397Sobrien
9452284Sobrien  /* By default, we throw on the math library if we have one.  */
9552284Sobrien  int need_math = (MATH_LIBRARY[0] != '\0');
9650397Sobrien
9790075Sobrien  /* True if we should add -shared-libgcc to the command-line.  */
9890075Sobrien  int shared_libgcc = 1;
9990075Sobrien
10050397Sobrien  /* The total number of arguments with the new stuff.  */
10150397Sobrien  int argc;
10250397Sobrien
10350397Sobrien  /* The argument list.  */
10490075Sobrien  const char *const *argv;
10550397Sobrien
10650397Sobrien  /* The number of libraries added in.  */
10750397Sobrien  int added_libraries;
10850397Sobrien
10950397Sobrien  /* The total number of arguments with the new stuff.  */
11050397Sobrien  int num_args = 1;
11150397Sobrien
11250397Sobrien  argc = *in_argc;
11350397Sobrien  argv = *in_argv;
11450397Sobrien  added_libraries = *in_added_libraries;
11550397Sobrien
116169689Skan  args = XCNEWVEC (int, argc);
11750397Sobrien
11850397Sobrien  for (i = 1; i < argc; i++)
11950397Sobrien    {
12050397Sobrien      /* If the previous option took an argument, we swallow it here.  */
12150397Sobrien      if (quote)
12250397Sobrien	{
12350397Sobrien	  quote = NULL;
12450397Sobrien	  continue;
12550397Sobrien	}
12650397Sobrien
12750397Sobrien      /* We don't do this anymore, since we don't get them with minus
12850397Sobrien	 signs on them.  */
12950397Sobrien      if (argv[i][0] == '\0' || argv[i][1] == '\0')
13050397Sobrien	continue;
13150397Sobrien
13250397Sobrien      if (argv[i][0] == '-')
13350397Sobrien	{
134132718Skan	  if (strcmp (argv[i], "-nostdlib") == 0
135132718Skan	      || strcmp (argv[i], "-nodefaultlibs") == 0)
13650397Sobrien	    {
137132718Skan	      library = -1;
13850397Sobrien	    }
139169689Skan	  else if (strcmp (argv[i], MATH_LIBRARY) == 0)
14050397Sobrien	    {
14150397Sobrien	      args[i] |= MATHLIB;
14250397Sobrien	      need_math = 0;
14350397Sobrien	    }
14450397Sobrien	  else if (strcmp (argv[i], "-lc") == 0)
14550397Sobrien	    args[i] |= WITHLIBC;
14696263Sobrien	  else if (strcmp (argv[i], "-pg") == 0 || strcmp (argv[i], "-p") == 0)
14796263Sobrien	    saw_profile_flag++;
14850397Sobrien	  else if (strcmp (argv[i], "-v") == 0)
149132718Skan	    saw_verbose_flag = 1;
150132718Skan	  else if (strncmp (argv[i], "-x", 2) == 0)
15150397Sobrien	    {
152169689Skan	      const char * arg;
153169689Skan	      if (argv[i][2] != '\0')
154169689Skan		arg = argv[i]+2;
155169689Skan	      else if ((argv[i+1]) != NULL)
156169689Skan		/* We need to swallow arg on next loop.  */
157169689Skan		quote = arg = argv[i+1];
158169689Skan  	      else  /* Error condition, message will be printed later.  */
159169689Skan		arg = "";
160169689Skan	      if (library == 0
161169689Skan		  && (strcmp (arg, "c++") == 0
162169689Skan		      || strcmp (arg, "c++-cpp-output") == 0))
163169689Skan		library = 1;
164169689Skan
165132718Skan	      saw_speclang = 1;
16650397Sobrien	    }
167169689Skan	  /* Arguments that go directly to the linker might be .o files,
168169689Skan	     or something, and so might cause libstdc++ to be needed.  */
169169689Skan	  else if (strcmp (argv[i], "-Xlinker") == 0)
170169689Skan	    {
171169689Skan	      quote = argv[i];
172169689Skan	      if (library == 0)
173169689Skan		library = 1;
174169689Skan	    }
175169689Skan	  else if (strncmp (argv[i], "-Wl,", 4) == 0)
176169689Skan	    library = (library == 0) ? 1 : library;
177146895Skan	  /* Unrecognized libraries (e.g. -lfoo) may require libstdc++.  */
178146895Skan	  else if (strncmp (argv[i], "-l", 2) == 0)
179146895Skan	    library = (library == 0) ? 1 : library;
18050397Sobrien	  else if (((argv[i][2] == '\0'
181132718Skan		     && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
18250397Sobrien		    || strcmp (argv[i], "-Tdata") == 0))
18350397Sobrien	    quote = argv[i];
184132718Skan	  else if ((argv[i][2] == '\0'
185132718Skan		    && strchr ("cSEM", argv[i][1]) != NULL)
186132718Skan		   || strcmp (argv[i], "-MM") == 0
187132718Skan		   || strcmp (argv[i], "-fsyntax-only") == 0)
18850397Sobrien	    {
18950397Sobrien	      /* Don't specify libraries if we won't link, since that would
19050397Sobrien		 cause a warning.  */
191132718Skan	      library = -1;
19250397Sobrien	    }
193169689Skan	  else if (strcmp (argv[i], "-static-libgcc") == 0
19490075Sobrien		   || strcmp (argv[i], "-static") == 0)
19590075Sobrien	    shared_libgcc = 0;
196117395Skan	  else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv[i][1]))
197117395Skan	    i++;
19850397Sobrien	  else
19950397Sobrien	    /* Pass other options through.  */
20050397Sobrien	    continue;
20150397Sobrien	}
20250397Sobrien      else
20350397Sobrien	{
204169689Skan	  int len;
20550397Sobrien
20650397Sobrien	  if (saw_speclang)
20750397Sobrien	    {
20850397Sobrien	      saw_speclang = 0;
20950397Sobrien	      continue;
21050397Sobrien	    }
21150397Sobrien
212132718Skan	  /* If the filename ends in .[chi], put options around it.
21350397Sobrien	     But not if a specified -x option is currently active.  */
21450397Sobrien	  len = strlen (argv[i]);
21550397Sobrien	  if (len > 2
216169689Skan	      && (argv[i][len - 1] == 'c'
217132718Skan		  || argv[i][len - 1] == 'i'
218132718Skan		  || argv[i][len - 1] == 'h')
21950397Sobrien	      && argv[i][len - 2] == '.')
22050397Sobrien	    {
22150397Sobrien	      args[i] |= LANGSPEC;
22250397Sobrien	      added += 2;
22350397Sobrien	    }
224169689Skan
225132718Skan	  /* If we don't know that this is a header file, we might
226132718Skan	     need to be linking in the libraries.  */
227132718Skan	  if (library == 0)
228132718Skan	    {
229132718Skan	      if ((len <= 2 || strcmp (argv[i] + (len - 2), ".H") != 0)
230132718Skan		  && (len <= 2 || strcmp (argv[i] + (len - 2), ".h") != 0)
231132718Skan		  && (len <= 3 || strcmp (argv[i] + (len - 3), ".hh") != 0))
232132718Skan		library = 1;
233132718Skan	    }
23450397Sobrien	}
23550397Sobrien    }
23650397Sobrien
23750397Sobrien  if (quote)
238169689Skan    fatal ("argument to '%s' missing\n", quote);
23950397Sobrien
24050397Sobrien  /* If we know we don't have to do anything, bail now.  */
241132718Skan  if (! added && library <= 0)
24250397Sobrien    {
24350397Sobrien      free (args);
24450397Sobrien      return;
24550397Sobrien    }
24650397Sobrien
24790075Sobrien  /* There's no point adding -shared-libgcc if we don't have a shared
24890075Sobrien     libgcc.  */
24990075Sobrien#ifndef ENABLE_SHARED_LIBGCC
25090075Sobrien  shared_libgcc = 0;
25190075Sobrien#endif
25250397Sobrien
25390075Sobrien  /* Make sure to have room for the trailing NULL argument.  */
254132718Skan  num_args = argc + added + need_math + shared_libgcc + (library > 0) + 1;
255169689Skan  arglist = XNEWVEC (const char *, num_args);
25690075Sobrien
25790075Sobrien  i = 0;
25890075Sobrien  j = 0;
259169689Skan
26090075Sobrien  /* Copy the 0th argument, i.e., the name of the program itself.  */
26190075Sobrien  arglist[i++] = argv[j++];
26290075Sobrien
26350397Sobrien  /* NOTE: We start at 1 now, not 0.  */
26490075Sobrien  while (i < argc)
26550397Sobrien    {
26650397Sobrien      arglist[j] = argv[i];
26750397Sobrien
26850397Sobrien      /* Make sure -lstdc++ is before the math library, since libstdc++
26950397Sobrien	 itself uses those math routines.  */
270132718Skan      if (!saw_math && (args[i] & MATHLIB) && library > 0)
27150397Sobrien	{
27250397Sobrien	  --j;
27350397Sobrien	  saw_math = argv[i];
27450397Sobrien	}
27550397Sobrien
276132718Skan      if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
27750397Sobrien	{
27850397Sobrien	  --j;
27950397Sobrien	  saw_libc = argv[i];
28050397Sobrien	}
28150397Sobrien
282132718Skan      /* Wrap foo.[chi] files in a language specification to
28350397Sobrien	 force the gcc compiler driver to run cc1plus on them.  */
28450397Sobrien      if (args[i] & LANGSPEC)
28550397Sobrien	{
28650397Sobrien	  int len = strlen (argv[i]);
287132718Skan	  switch (argv[i][len - 1])
288132718Skan	    {
289132718Skan	    case 'c':
290132718Skan	      arglist[j++] = "-xc++";
291132718Skan	      break;
292132718Skan	    case 'i':
293132718Skan	      arglist[j++] = "-xc++-cpp-output";
294132718Skan	      break;
295132718Skan	    case 'h':
296132718Skan	      arglist[j++] = "-xc++-header";
297132718Skan	      break;
298132718Skan	    default:
299169689Skan	      gcc_unreachable ();
300132718Skan	    }
30150397Sobrien	  arglist[j++] = argv[i];
30250397Sobrien	  arglist[j] = "-xnone";
30350397Sobrien	}
30450397Sobrien
30590075Sobrien      i++;
30690075Sobrien      j++;
30790075Sobrien    }
30890075Sobrien
30950397Sobrien  /* Add `-lstdc++' if we haven't already done so.  */
310132718Skan  if (library > 0)
31150397Sobrien    {
312169689Skan      arglist[j] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
313169689Skan      if (arglist[j][0] != '-' || arglist[j][1] == 'l')
314169689Skan	added_libraries++;
315169689Skan      j++;
31650397Sobrien    }
31750397Sobrien  if (saw_math)
31850397Sobrien    arglist[j++] = saw_math;
319132718Skan  else if (library > 0 && need_math)
32050397Sobrien    {
321169689Skan      arglist[j] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY;
322169689Skan      if (arglist[j][0] != '-' || arglist[j][1] == 'l')
323169689Skan	added_libraries++;
324169689Skan      j++;
32550397Sobrien    }
32650397Sobrien  if (saw_libc)
32750397Sobrien    arglist[j++] = saw_libc;
32890075Sobrien  if (shared_libgcc)
32990075Sobrien    arglist[j++] = "-shared-libgcc";
33050397Sobrien
33150397Sobrien  arglist[j] = NULL;
33250397Sobrien
33350397Sobrien  *in_argc = j;
33450397Sobrien  *in_argv = arglist;
33550397Sobrien  *in_added_libraries = added_libraries;
33650397Sobrien}
33750397Sobrien
338117395Skan/* Called before linking.  Returns 0 on success and -1 on failure.  */
339132718Skanint lang_specific_pre_link (void)  /* Not used for C++.  */
34050397Sobrien{
34150397Sobrien  return 0;
34250397Sobrien}
34350397Sobrien
344117395Skan/* Number of extra output files that lang_specific_pre_link may generate.  */
345117395Skanint lang_specific_extra_outfiles = 0;  /* Not used for C++.  */
346