11556Srgrimes/* Specific flags and argument handling of the C preprocessor.
21556Srgrimes   Copyright (C) 1999 Free Software Foundation, Inc.
31556Srgrimes
41556SrgrimesThis file is part of GCC.
51556Srgrimes
61556SrgrimesGCC is free software; you can redistribute it and/or modify it under
71556Srgrimesthe terms of the GNU General Public License as published by the Free
81556SrgrimesSoftware Foundation; either version 2, or (at your option) any later
91556Srgrimesversion.
101556Srgrimes
111556SrgrimesGCC is distributed in the hope that it will be useful, but WITHOUT ANY
121556SrgrimesWARRANTY; without even the implied warranty of MERCHANTABILITY or
131556SrgrimesFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141556Srgrimesfor more details.
151556Srgrimes
161556SrgrimesYou should have received a copy of the GNU General Public License
171556Srgrimesalong with GCC; see the file COPYING.  If not, write to the Free
181556SrgrimesSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
191556Srgrimes02110-1301, USA.  */
201556Srgrimes
211556Srgrimes#include "config.h"
221556Srgrimes#include "system.h"
231556Srgrimes#include "coretypes.h"
241556Srgrimes#include "tm.h"
251556Srgrimes#include "gcc.h"
261556Srgrimes
271556Srgrimes/* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
281556Srgrimes   is a customized version of the gcc driver.  It forces -E; -S and -c
291556Srgrimes   are errors.  It defaults to -x c for files with unrecognized
301556Srgrimes   extensions, unless -x options appear in argv, in which case we
311556Srgrimes   assume the user knows what they're doing.  If no explicit input is
321556Srgrimes   mentioned, it will read stdin.  */
331556Srgrimes
341556Srgrimes#ifndef SWITCH_TAKES_ARG
351556Srgrimes#define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR)
361556Srgrimes#endif
371556Srgrimes
381556Srgrimes#ifndef WORD_SWITCH_TAKES_ARG
3936049Scharnier#define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR)
4036049Scharnier#endif
4136049Scharnier
4236049Scharnier/* Suffixes for known sorts of input files.  Note that we do not list
4350471Speter   files which are normally considered to have been preprocessed already,
441556Srgrimes   since the user's expectation is that `cpp' always preprocesses.  */
451556Srgrimesstatic const char *const known_suffixes[] =
461556Srgrimes{
471556Srgrimes  ".c",  ".C",   ".S",   ".m",
481556Srgrimes  ".cc", ".cxx", ".cpp", ".cp",  ".c++",
491556Srgrimes  NULL
501556Srgrimes};
511556Srgrimes
521556Srgrimes/* Filter argc and argv before processing by the gcc driver proper.  */
531556Srgrimesvoid
541556Srgrimeslang_specific_driver (int *in_argc, const char *const **in_argv,
551556Srgrimes		      int *in_added_libraries ATTRIBUTE_UNUSED)
561556Srgrimes{
571556Srgrimes  int argc = *in_argc;
581556Srgrimes  const char *const *argv = *in_argv;
591556Srgrimes
601556Srgrimes  /* Do we need to read stdin? */
611556Srgrimes  int read_stdin = 1;
621556Srgrimes
631556Srgrimes  /* Do we need to insert -E? */
641556Srgrimes  int need_E = 1;
651556Srgrimes
661556Srgrimes  /* Have we seen an input file? */
671556Srgrimes  int seen_input = 0;
681556Srgrimes
691556Srgrimes  /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
701556Srgrimes     0 means unnecessary.  */
711556Srgrimes  int lang_c_here = 0;
721556Srgrimes  int lang_S_here = 0;
731556Srgrimes  int o_here = 0;
741556Srgrimes
751556Srgrimes  /* Do we need to fix up an input file with an unrecognized suffix? */
761556Srgrimes  int need_fixups = 1;
771556Srgrimes
781556Srgrimes  int i, j, quote = 0;
7976017Skris  const char **new_argv;
801556Srgrimes  int new_argc;
811556Srgrimes  extern int is_cpp_driver;
821556Srgrimes
831556Srgrimes  is_cpp_driver = 1;
841556Srgrimes
851556Srgrimes  /* First pass.  If we see an -S or -c, barf.  If we see an input file,
861556Srgrimes     turn off read_stdin.  If we see a second input file, it is actually
871556Srgrimes     the output file.  If we see a third input file, barf.  */
881556Srgrimes  for (i = 1; i < argc; i++)
891556Srgrimes    {
901556Srgrimes      if (quote == 1)
911556Srgrimes	{
921556Srgrimes	  quote = 0;
931556Srgrimes	  continue;
941556Srgrimes	}
9576017Skris
961556Srgrimes      if (argv[i][0] == '-')
971556Srgrimes	{
981556Srgrimes	  if (argv[i][1] == '\0')
991556Srgrimes	    read_stdin = 0;
1001556Srgrimes	  else if (argv[i][2] == '\0')
1011556Srgrimes	    {
1021556Srgrimes	      if (argv[i][1] == 'E')
1031556Srgrimes		need_E = 0;
1041556Srgrimes	      else if (argv[i][1] == 'S' || argv[i][1] == 'c')
1051556Srgrimes		{
1061556Srgrimes		  fatal ("\"%s\" is not a valid option to the preprocessor",
1071556Srgrimes			 argv[i]);
10876017Skris		  return;
1091556Srgrimes		}
1101556Srgrimes	      else if (argv[i][1] == 'x')
1111556Srgrimes		{
1121556Srgrimes		  need_fixups = 0;
1131556Srgrimes		  quote = 1;
1141556Srgrimes		}
1151556Srgrimes	      else if (SWITCH_TAKES_ARG (argv[i][1]))
1161556Srgrimes		quote = 1;
1171556Srgrimes	    }
1181556Srgrimes	  else if (argv[i][1] == 'x')
1191556Srgrimes	    need_fixups = 0;
1201556Srgrimes	  else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
1211556Srgrimes	    quote = 1;
1221556Srgrimes	}
1231556Srgrimes      else /* not an option */
12476017Skris	{
1251556Srgrimes	  seen_input++;
1261556Srgrimes	  if (seen_input == 3)
1271556Srgrimes	    {
1281556Srgrimes	      fatal ("too many input files");
1291556Srgrimes	      return;
1301556Srgrimes	    }
1311556Srgrimes	  else if (seen_input == 2)
1321556Srgrimes	    {
1331556Srgrimes	      o_here = i;
1341556Srgrimes	    }
1351556Srgrimes	  else
1361556Srgrimes	    {
13776017Skris	      read_stdin = 0;
1381556Srgrimes	      if (need_fixups)
1391556Srgrimes		{
1401556Srgrimes		  int l = strlen (argv[i]);
1411556Srgrimes		  int known = 0;
1421556Srgrimes		  const char *const *suff;
1431556Srgrimes
1441556Srgrimes		  for (suff = known_suffixes; *suff; suff++)
1451556Srgrimes		    if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
1461556Srgrimes		      {
1471556Srgrimes			known = 1;
1481556Srgrimes			break;
1491556Srgrimes		      }
1501556Srgrimes
1511556Srgrimes		  if (! known)
1521556Srgrimes		    {
15376017Skris		      /* .s files are a special case; we have to treat
1541556Srgrimes			 them like .S files so -D__ASSEMBLER__ will be
1551556Srgrimes			 in effect.  */
1561556Srgrimes		      if (!strcmp (".s", &argv[i][l - 2]))
1571556Srgrimes			lang_S_here = i;
1581556Srgrimes		      else
1591556Srgrimes			lang_c_here = i;
1601556Srgrimes		    }
1611556Srgrimes		}
1621556Srgrimes	    }
1631556Srgrimes	}
1641556Srgrimes    }
1651556Srgrimes
16676017Skris  /* If we don't need to edit the command line, we can bail early.  */
1671556Srgrimes
1681556Srgrimes  new_argc = argc + need_E + read_stdin
1691556Srgrimes    + !!o_here + !!lang_c_here + !!lang_S_here;
1701556Srgrimes
1711556Srgrimes  if (new_argc == argc)
1721556Srgrimes    return;
1731556Srgrimes
1741556Srgrimes  /* One more slot for a terminating null.  */
1751556Srgrimes  new_argv = XNEWVEC (const char *, new_argc + 1);
1761556Srgrimes
1771556Srgrimes  new_argv[0] = argv[0];
1781556Srgrimes  j = 1;
1791556Srgrimes
1801556Srgrimes  if (need_E)
1811556Srgrimes    new_argv[j++] = "-E";
18276017Skris
1831556Srgrimes  for (i = 1; i < argc; i++, j++)
1841556Srgrimes    {
1851556Srgrimes      if (i == lang_c_here)
1861556Srgrimes	new_argv[j++] = "-xc";
1871556Srgrimes      else if (i == lang_S_here)
1881556Srgrimes	new_argv[j++] = "-xassembler-with-cpp";
1891556Srgrimes      else if (i == o_here)
1901556Srgrimes	new_argv[j++] = "-o";
1911556Srgrimes
1921556Srgrimes      new_argv[j] = argv[i];
1931556Srgrimes    }
1941556Srgrimes
1951556Srgrimes  if (read_stdin)
19676017Skris    new_argv[j++] = "-";
1971556Srgrimes
1981556Srgrimes  new_argv[j] = NULL;
1991556Srgrimes  *in_argc = new_argc;
2001556Srgrimes  *in_argv = new_argv;
2011556Srgrimes}
2021556Srgrimes
2031556Srgrimes/* Called before linking.  Returns 0 on success and -1 on failure.  */
2041556Srgrimesint lang_specific_pre_link (void)
2051556Srgrimes{
2061556Srgrimes  return 0;  /* Not used for cpp.  */
2071556Srgrimes}
2081556Srgrimes
2091556Srgrimes/* Number of extra output files that lang_specific_pre_link may generate.  */
2101556Srgrimesint lang_specific_extra_outfiles = 0;  /* Not used for cpp.  */
2111556Srgrimes