This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

cpplib: command line argument parsing


This is the current state of my patch to tighten up cpplib's command
line handling.

o I'm not sure if the internationalisation stuff is quite right -
could you please confirm if it's what you had in mind, Zack?

o The -W options are strcmp-ed one by one; this may be worth improving
with a binary search.  Please advise.

o -ifoutput is still accepted

Neil.

	* cppinit.c (opt_comp) New function.  Called by sort_options
	as the comparison routine.
	(sort_options) New function.  Sorts the array of command line
	options at run time for non-ASCII host environments.
	(parse_option) New function.  Parses a single command line
	option, possibly taking an argument.
	(cpp_handle_option) Rewritten to use parse_option for binary
	searching of options.
	(cpp_handle_options) Sorts the array of command line options
	during its first invocation.
	(print_help) Updated run-time help.

	* cpplib.h Remove prototype of cpp_handle_option; it is now
	local to cppinit.c

Index: cppinit.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cppinit.c,v
retrieving revision 1.41
diff -u -p -r1.41 cppinit.c
--- cppinit.c	2000/02/15 16:36:32	1.41
+++ cppinit.c	2000/02/17 13:18:26
@@ -201,6 +201,13 @@ static void initialize_dependency_output
 static void new_pending_define		PARAMS ((struct cpp_options *,
 						 const char *));
 
+#ifdef HOST_EBCDIC
+static int opt_comp                     PARAMS ((const void*, const void*));
+#endif
+static void sort_options                PARAMS ((void));
+static int parse_option                 PARAMS ((const char *));
+static int cpp_handle_option            PARAMS ((cpp_reader *, int, char **));
+
 /* Last argument to append_include_chain: chain to use */
 enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
 
@@ -1064,10 +1071,211 @@ new_pending_define (opts, text)
   APPEND (opts->pending, define, o);
 }
 
+enum opt_code
+{
+  OPT_stdin_stdout = 0, OPT_dollar, OPT_plus,
+  OPT__help, OPT__version,
+  OPT_A, OPT_C, OPT_D, OPT_H, OPT_I, OPT_M,
+  OPT_MD, OPT_MG, OPT_MM, OPT_MMD,
+  OPT_P, OPT_U, OPT_W,
+  OPT_d,
+  OPT_fleading_underscore, OPT_fno_leading_underscore,
+  OPT_fpreprocessed, OPT_fno_preprocessed,
+  OPT_g, OPT_h, 
+  OPT_idirafter, OPT_ifoutput, OPT_imacros, OPT_include,
+  OPT_iprefix, OPT_isystem, OPT_iwithprefix, OPT_iwithprefixbefore,
+  OPT_lang_asm, OPT_lang_c, OPT_lang_cplusplus, OPT_lang_c89,
+  OPT_lang_chill, OPT_lang_fortran, OPT_lang_objc, OPT_lang_objcplusplus,
+  OPT_nostdinc, OPT_nostdincplusplus,
+  OPT_o,
+  OPT_pedantic, OPT_pedantic_errors, OPT_remap,
+  OPT_std_c89, OPT_std_c99, OPT_std_c9x, OPT_std_gnu89, OPT_std_gnu99,
+  OPT_std_gnu9x, OPT_std_iso9899_1990, OPT_std_iso9899_199409,
+  OPT_std_iso9899_1999, OPT_std_iso9899_199x,
+  OPT_traditional, OPT_trigraphs,
+  OPT_v, OPT_w,
+  N_OPTS
+};
+
+struct cl_option
+{
+  const char* opt_text;
+  int arg_index;	/* -1 = takes no argument */
+  size_t opt_len;
+  enum opt_code opt_code;
+};
+
+/* Run-time sorted array of pointers to command-line options below */
+static const struct cl_option* cl_options[N_OPTS];
+
+static const char* missing_arg[] =
+{
+  N_("Argument missing after `%s' option"),
+  N_("Assertion missing after `%s' option"),
+  N_("Directory name missing after `%s' option"),
+  N_("File name missing after `%s' option"),
+  N_("Macro name missing after `%s' option"),
+  N_("Path name missing after `%s' option")
+};
+
+/* These lists must be ASCII sorted. Make enum order above match this. */
+#define DEF_OPT(text, msg_idx, code) {text, msg_idx, sizeof(text) - 1, code}
+static const struct cl_option cl_opt_array[] =
+{
+  DEF_OPT("",                      -1, OPT_stdin_stdout),
+  DEF_OPT("$",                     -1, OPT_dollar),
+  DEF_OPT("+",                     -1, OPT_plus),
+  DEF_OPT("-help",                 -1, OPT__help),
+  DEF_OPT("-version",              -1, OPT__version),
+  DEF_OPT("A",                      1, OPT_A),
+  DEF_OPT("C",                     -1, OPT_C),
+  DEF_OPT("D",                      4, OPT_D),
+  DEF_OPT("H",                     -1, OPT_H),
+  DEF_OPT("I",                      2, OPT_I),
+  DEF_OPT("M",                     -1, OPT_M),
+  DEF_OPT("MD",                     3, OPT_MD),
+  DEF_OPT("MG",                    -1, OPT_MG),
+  DEF_OPT("MM",                    -1, OPT_MM),
+  DEF_OPT("MMD",                    3, OPT_MMD),
+  DEF_OPT("P",                     -1, OPT_P),
+  DEF_OPT("U",                      4, OPT_U),
+  DEF_OPT("W",                      0, OPT_W), /* NB: Immed arg only, and not reqd */
+  DEF_OPT("d",                      0, OPT_d),
+  DEF_OPT("fleading-underscore",   -1, OPT_fleading_underscore),
+  DEF_OPT("fno-leading-underscore",-1, OPT_fno_leading_underscore),
+  DEF_OPT("fpreprocessed",         -1, OPT_fpreprocessed),
+  DEF_OPT("fno-preprocessed",      -1, OPT_fno_preprocessed),
+  DEF_OPT("g",                      0, OPT_g), /* NB: Immed arg only, and not reqd */
+  DEF_OPT("h",                     -1, OPT_h),
+  DEF_OPT("idirafter",              2, OPT_idirafter),
+  DEF_OPT("ifoutput",              -1, OPT_ifoutput),
+  DEF_OPT("imacros",                3, OPT_imacros),
+  DEF_OPT("include",                3, OPT_include),
+  DEF_OPT("iprefix",                5, OPT_iprefix),
+  DEF_OPT("isystem",                2, OPT_isystem),
+  DEF_OPT("iwithprefix",            2, OPT_iwithprefix),
+  DEF_OPT("iwithprefixbefore",      2, OPT_iwithprefixbefore),
+  DEF_OPT("lang-asm",              -1, OPT_lang_asm),
+  DEF_OPT("lang-c",                -1, OPT_lang_c),
+  DEF_OPT("lang-c++",              -1, OPT_lang_cplusplus),
+  DEF_OPT("lang-c89",              -1, OPT_lang_c89),
+  DEF_OPT("lang-chill",            -1, OPT_lang_chill),
+  DEF_OPT("lang-fortran",          -1, OPT_lang_fortran),
+  DEF_OPT("lang-objc",             -1, OPT_lang_objc),
+  DEF_OPT("lang-objc++",           -1, OPT_lang_objcplusplus),
+  DEF_OPT("nostdinc",              -1, OPT_nostdinc),
+  DEF_OPT("nostdinc++",            -1, OPT_nostdincplusplus),
+  DEF_OPT("o",                      3, OPT_o),
+  DEF_OPT("pedantic",              -1, OPT_pedantic),
+  DEF_OPT("pedantic-errors",       -1, OPT_pedantic_errors),
+  DEF_OPT("remap",                 -1, OPT_remap),
+  DEF_OPT("std=c89",               -1, OPT_std_c89),
+  DEF_OPT("std=c99",               -1, OPT_std_c99),
+  DEF_OPT("std=c9x",               -1, OPT_std_c9x),
+  DEF_OPT("std=gnu89",             -1, OPT_std_gnu89),
+  DEF_OPT("std=gnu99",             -1, OPT_std_gnu99),
+  DEF_OPT("std=gnu9x",             -1, OPT_std_gnu9x),
+  DEF_OPT("std=iso9899:1990",      -1, OPT_std_iso9899_1990),
+  DEF_OPT("std=iso9899:199409",    -1, OPT_std_iso9899_199409),
+  DEF_OPT("std=iso9899:1999",      -1, OPT_std_iso9899_1999),
+  DEF_OPT("std=iso9899:199x",      -1, OPT_std_iso9899_199x),
+  DEF_OPT("traditional",           -1, OPT_traditional),
+  DEF_OPT("trigraphs",             -1, OPT_trigraphs),
+  DEF_OPT("v",                     -1, OPT_v),
+  DEF_OPT("w",                     -1, OPT_w)
+};
+#undef DEF_OPT
+
+#ifdef HOST_EBCDIC
+static int
+opt_comp(const void* p1, const void* p2)
+{
+  return strcmp( (*(struct cl_option**) p1)->opt_text,
+		 (*(struct cl_option**) p2)->opt_text);
+}
+#endif
+
+/* Initialises the array of command line options.  For non-ASCII
+   hosts, the array needs to be sorted at runtime */
+static void
+sort_options(void)
+{
+  unsigned int i;
+
+  for (i = 0; i < N_OPTS; i++)
+    cl_options[i] = &cl_opt_array[i];
+#ifdef HOST_EBCDIC
+  qsort(cl_options, N_OPTS, sizeof(struct cl_option*), opt_comp);
+#endif
+}
+
+/* Perform a binary search to find which, if any, option the given
+   command-line matches.  Returns its index in the option array,
+   negative on failure.  Complications arise since some options can be
+   suffixed with an argument, and multiple complete matches can occur,
+   e.g. -iwithprefix and -iwithprefixbefore.  Moreover, we want to
+   accept options beginning with -g and -W that we do not recognise,
+   but not to swallow any subsequent command line argument; these are
+   handled as special cases in cpp_handle_option */
+static int parse_option(input)
+     const char* input;
+{
+  unsigned int md, mn, mx;
+  size_t opt_len;
+  int comp;
+
+  mn = 0;
+  mx = N_OPTS;
+
+  while (mx > mn)
+    {
+      md = (mn + mx) / 2;
+    
+      opt_len = cl_options[md]->opt_len;
+      comp = strncmp(input, cl_options[md]->opt_text, opt_len);
+    
+      if (comp > 0)
+	mn = md + 1;
+      else if (comp < 0)
+	mx = md;
+      else
+	{
+	  if (input[opt_len] == '\0')
+	    return md;
+	  /* We were passed more text.  If the option takes an argument,
+	     we may match a later option or we may have been passed the
+	     argument.  The longest possible option match succeeds.
+	     If the option takes no arguments we have not matched and
+	     continue the search (e.g. input="stdc++" match was "stdc") */
+	  mn = md + 1;
+	  if (cl_options[md]->arg_index >= 0)
+	    {
+	      /* Scan forwards.  If we get an exact match, return it.
+		 Otherwise, return the longest option-accepting match.
+		 This loops no more than twice with current options */
+	      mx = md;
+	      for (; mn < N_OPTS; mn++)
+		{
+		  opt_len = cl_options[mn]->opt_len;
+		  if (strncmp(input, cl_options[mn]->opt_text, opt_len))
+		    break;
+		  if (input[opt_len] == '\0')
+		    return mn;
+		  if (cl_options[mn]->arg_index >= 0)
+		    mx = mn;
+		}
+	      return mx;
+	    }
+	}
+    }
+
+  return -1;
+}
+
 /* Handle one command-line option in (argc, argv).
    Can be called multiple times, to handle multiple sets of options.
    Returns number of strings consumed.  */
-int
+static int
 cpp_handle_option (pfile, argc, argv)
      cpp_reader *pfile;
      int argc;
@@ -1089,374 +1297,216 @@ cpp_handle_option (pfile, argc, argv)
 	opts->in_fname = argv[i];
     }
   else
-    switch (argv[i][1])
-      {
-      case 'f':
-	if (!strcmp (argv[i], "-fleading-underscore"))
-	  user_label_prefix = "_";
-	else if (!strcmp (argv[i], "-fno-leading-underscore"))
-	  user_label_prefix = "";
-	else if (!strcmp (argv[i], "-fpreprocessed"))
-	  opts->preprocessed = 1;
-	else if (!strcmp (argv[i], "-fno-preprocessed"))
-	  opts->preprocessed = 0;
-	else
-	  {
-	    return i;
-	  }
-	break;
+    {
+      enum opt_code opt_code;
+      int opt_index;
+      char* arg = 0;
 
-      case 'I':			/* Add directory to path for includes.  */
-	if (!strcmp (argv[i] + 2, "-"))
-	  {
-	    /* -I- means:
-	       Use the preceding -I directories for #include "..."
-	       but not #include <...>.
-	       Don't search the directory of the present file
-	       for #include "...".  (Note that -I. -I- is not the same as
-	       the default setup; -I. uses the compiler's working dir.)  */
-	    if (! opts->ignore_srcdir)
-	      {
-		opts->ignore_srcdir = 1;
-		opts->pending->quote_head = opts->pending->brack_head;
-		opts->pending->quote_tail = opts->pending->brack_tail;
-		opts->pending->brack_head = 0;
-		opts->pending->brack_tail = 0;
-	      }
-	    else
-	      {
-		cpp_fatal (pfile, "-I- specified twice");
-		return argc;
-	      }
-	  }
-	else
-	  {
-	    char *fname;
-	    if (argv[i][2] != 0)
-	      fname = argv[i] + 2;
-	    else if (i + 1 == argc)
-	      goto missing_dirname;
-	    else
-	      fname = argv[++i];
-	    append_include_chain (pfile, opts->pending,
-				  xstrdup (fname), BRACKET);
-	  }
-	break;
+      /* Skip over '-' */
+      opt_index = parse_option(&argv[i][1]);
 
-      case 'i':
-	/* Add directory to beginning of system include path, as a system
-	   include directory. */
-	if (!strcmp (argv[i], "-isystem"))
-	  {
-	    if (i + 1 == argc)
-	      goto missing_filename;
-	    append_include_chain (pfile, opts->pending,
-				  xstrdup (argv[++i]), SYSTEM);
-	  }
-	else if (!strcmp (argv[i], "-include"))
-	  {
-	    if (i + 1 == argc)
-	      goto missing_filename;
-	    else
-	      {
-		struct pending_option *o = (struct pending_option *)
-		  xmalloc (sizeof (struct pending_option));
-		o->arg = argv[++i];
-
-		/* This list has to be built in reverse order so that
-		   when cpp_start_read pushes all the -include files onto
-		   the buffer stack, they will be scanned in forward order.  */
-		o->next = opts->pending->include_head;
-		opts->pending->include_head = o;
-	      }
-	  }
-	else if (!strcmp (argv[i], "-imacros"))
-	  {
-	    if (i + 1 == argc)
-	      goto missing_filename;
-	    else
-	      {
-		struct pending_option *o = (struct pending_option *)
-		  xmalloc (sizeof (struct pending_option));
-		o->arg = argv[++i];
-		o->next = NULL;
-
-		APPEND (opts->pending, imacros, o);
-	      }
-	  }
-	/* Add directory to end of path for includes,
-	   with the default prefix at the front of its name.  */
-	else if (!strcmp (argv[i], "-iwithprefix"))
-	  {
-	    char *fname;
-	    int len;
-	    if (i + 1 == argc)
-	      goto missing_dirname;
-	    ++i;
-	    len = strlen (argv[i]);
+      if (opt_index < 0)
+	return i;
 
-	    if (opts->include_prefix != 0)
-	      {
-		fname = xmalloc (opts->include_prefix_len + len + 1);
-		memcpy (fname, opts->include_prefix, opts->include_prefix_len);
-		memcpy (fname + opts->include_prefix_len, argv[i], len + 1);
-	      }
-	    else
-	      {
-		fname = xmalloc (sizeof GCC_INCLUDE_DIR - 8 + len);
-		memcpy (fname, GCC_INCLUDE_DIR, sizeof GCC_INCLUDE_DIR - 9);
-		memcpy (fname + sizeof GCC_INCLUDE_DIR - 9, argv[i], len + 1);
-	      }
-	  
-	    append_include_chain (pfile, opts->pending, fname, SYSTEM);
-	  }
-	/* Add directory to main path for includes,
-	   with the default prefix at the front of its name.  */
-	else if (!strcmp (argv[i], "-iwithprefixbefore"))
-	  {
-	    char *fname;
-	    int len;
-	    if (i + 1 == argc)
-	      goto missing_dirname;
-	    ++i;
-	    len = strlen (argv[i]);
+      opt_code = cl_options[opt_index]->opt_code;
+      if (cl_options[opt_index]->arg_index >= 0)
+	{
+	  arg = &argv[i][cl_options[opt_index]->opt_len + 1];
 
-	    if (opts->include_prefix != 0)
-	      {
-		fname = xmalloc (opts->include_prefix_len + len + 1);
-		memcpy (fname, opts->include_prefix, opts->include_prefix_len);
-		memcpy (fname + opts->include_prefix_len, argv[i], len + 1);
-	      }
-	    else
-	      {
-		fname = xmalloc (sizeof GCC_INCLUDE_DIR - 8 + len);
-		memcpy (fname, GCC_INCLUDE_DIR, sizeof GCC_INCLUDE_DIR - 9);
-		memcpy (fname + sizeof GCC_INCLUDE_DIR - 9, argv[i], len + 1);
-	      }
-	  
-	    append_include_chain (pfile, opts->pending, fname, BRACKET);
-	  }
-	/* Add directory to end of path for includes.  */
-	else if (!strcmp (argv[i], "-idirafter"))
-	  {
-	    if (i + 1 == argc)
-	      goto missing_dirname;
-	    append_include_chain (pfile, opts->pending,
-				  xstrdup (argv[++i]), AFTER);
-	  }
-	else if (!strcmp (argv[i], "-iprefix"))
-	  {
-	    if (i + 1 == argc)
-	      goto missing_filename;
-	    else
-	      {
-		opts->include_prefix = argv[++i];
-		opts->include_prefix_len = strlen (argv[i]);
-	      }
-	  }
-	else if (!strcmp (argv[i], "-ifoutput"))
-	  opts->output_conditionals = 1;
+	  /* Yuk. Special case for -g and -W as they must not swallow
+	     up any following argument.  If this becomes common, add
+	     another field to the cl_options table */
+	  if (arg[0] == '\0' && !(opt_code == OPT_g || opt_code == OPT_W))
+	    {
+	      arg = argv[++i];
+	      if (!arg)
+		{
+		  cpp_fatal (pfile,
+			     _(missing_arg[cl_options[opt_index]->arg_index]),
+			     argv[i - 1]);
+		  return argc;
+		}
+	    }
+	}
 
-	break;
-      
-      case 'o':
-	if (opts->out_fname != NULL)
-	  {
-	    cpp_fatal (pfile, "Output filename specified twice");
-	    return argc;
-	  }
-	if (i + 1 == argc)
-	  goto missing_filename;
-	opts->out_fname = argv[++i];
-	if (!strcmp (opts->out_fname, "-"))
-	  opts->out_fname = "";
-	break;
-      
-      case 'p':
-	if (!strcmp (argv[i], "-pedantic"))
+      switch (opt_code)
+	{
+	case N_OPTS: /* shut GCC up */
+	  break;
+	case OPT_fleading_underscore:
+	  user_label_prefix = "_";
+	  break;
+	case OPT_fno_leading_underscore:
+	  user_label_prefix = "";
+	  break;
+	case OPT_fpreprocessed:
+	  opts->preprocessed = 1;
+	  break;
+	case OPT_fno_preprocessed:
+	  opts->preprocessed = 0;
+	  break;
+	case OPT_w:
+	  opts->inhibit_warnings = 1;
+	  break;
+	case OPT_g:  /* Silently ignore anything but -g3 */
+	  if (!strcmp(&argv[i][2], "3"))
+	    opts->debug_output = 1;
+	  break;
+	case OPT_h:
+	case OPT__help:
+	  print_help ();
+	  exit (0);  /* XXX */
+	  break;
+	case OPT__version:
+	  fprintf (stderr, _("GNU CPP version %s (cpplib)\n"), version_string);
+	  exit (0);  /* XXX */
+	  break;
+	case OPT_C:
+	  opts->discard_comments = 0;
+	  break;
+	case OPT_P:
+	  opts->no_line_commands = 1;
+	  break;
+	case OPT_dollar:		/* Don't include $ in identifiers.  */
+	  opts->dollars_in_ident = 0;
+	  break;
+	case OPT_H:
+	  opts->print_include_names = 1;
+	  break;
+	case OPT_D:
+	  new_pending_define (opts, arg);
+	  break;
+	case OPT_pedantic_errors:
+	  opts->pedantic_errors = 1;
+	  /* fall through */
+	case OPT_pedantic:
 	  CPP_PEDANTIC (pfile) = 1;
-	else if (!strcmp (argv[i], "-pedantic-errors"))
-	  {
-	    CPP_PEDANTIC (pfile) = 1;
-	    opts->pedantic_errors = 1;
-	  }
-	break;
-      
-      case 't':
-	if (!strcmp (argv[i], "-traditional"))
-	  {
-	    opts->traditional = 1;
-	    opts->cplusplus_comments = 0;
-	    opts->trigraphs = 0;
-	    opts->warn_trigraphs = 0;
-	  }
-	else if (!strcmp (argv[i], "-trigraphs"))
+	  break;
+	case OPT_traditional:
+	  opts->traditional = 1;
+	  opts->cplusplus_comments = 0;
+	  opts->trigraphs = 0;
+	  opts->warn_trigraphs = 0;
+	  break;
+	case OPT_trigraphs:
 	  opts->trigraphs = 1;
-	break;
-      
-      case 'l':
-	if (! strcmp (argv[i], "-lang-c"))
-	  opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
-	    opts->c99 = 1, opts->objc = 0;
-	if (! strcmp (argv[i], "-lang-c89"))
-	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 0;
-	    opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
-	    opts->trigraphs = 1;
-	    new_pending_define (opts, "__STRICT_ANSI__");
-	  }
-	if (! strcmp (argv[i], "-lang-c++"))
-	  opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
-	    opts->c99 = 0, opts->objc = 0;
-	if (! strcmp (argv[i], "-lang-objc"))
-	  opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
-	    opts->c99 = 0, opts->objc = 1;
-	if (! strcmp (argv[i], "-lang-objc++"))
-	  opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
-	    opts->c99 = 0, opts->objc = 1;
-	if (! strcmp (argv[i], "-lang-asm"))
+	  break;
+	case OPT_plus:
+	  opts->cplusplus = 1;
+	  opts->cplusplus_comments = 1;
+	  break;
+	case OPT_remap:
+	  opts->remap = 1;
+	  break;
+	case OPT_ifoutput:
+	  opts->output_conditionals = 1;
+	  break;
+	case OPT_iprefix:
+	  opts->include_prefix = arg;
+	  opts->include_prefix_len = strlen (arg);
+	  break;
+	case OPT_lang_c:
+	  opts->cplusplus = 0, opts->cplusplus_comments = 1;
+	  opts->c89 = 0, opts->c99 = 1, opts->objc = 0;
+	  break;
+	case OPT_lang_c89:
+	  opts->cplusplus = 0, opts->cplusplus_comments = 0;
+	  opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
+	  opts->trigraphs = 1;
+	  new_pending_define (opts, "__STRICT_ANSI__");
+	  break;
+	case OPT_lang_cplusplus:
+	  opts->cplusplus = 1, opts->cplusplus_comments = 1;
+	  opts->c89 = 0, opts->c99 = 0, opts->objc = 0;
+	  break;
+	case OPT_lang_objc:
+	case OPT_lang_objcplusplus:
+	  opts->cplusplus = opt_code == OPT_lang_objcplusplus;
+	  opts->cplusplus_comments = 1;
+	  opts->c89 = 0, opts->c99 = 0, opts->objc = 1;
+	  break;
+	case OPT_lang_asm:
 	  opts->lang_asm = 1;
-	if (! strcmp (argv[i], "-lang-fortran"))
+	  break;
+	case OPT_lang_fortran:
 	  opts->lang_fortran = 1, opts->cplusplus_comments = 0;
-	if (! strcmp (argv[i], "-lang-chill"))
-	  opts->objc = 0, opts->cplusplus = 0, opts->chill = 1,
-	    opts->traditional = 1;
-	break;
-      
-      case '+':
-	opts->cplusplus = 1, opts->cplusplus_comments = 1;
-	break;
-
-      case 's':
-	if (!strcmp (argv[i], "-std=gnu89"))
-	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 1;
-	    opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
-	  }
-	else if (!strcmp (argv[i], "-std=gnu9x")
-		 || !strcmp (argv[i], "-std=gnu99"))
-	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 1;
-	    opts->c89 = 0, opts->c99 = 1, opts->objc = 0;
-	    new_pending_define (opts, "__STDC_VERSION__=199901L");
-	  }
-	else if (!strcmp (argv[i], "-std=iso9899:1990")
-		 || !strcmp (argv[i], "-std=c89"))
-	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 0;
-	    opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
-	    opts->trigraphs = 1;
-	    new_pending_define (opts, "__STRICT_ANSI__");
-	  }
-	else if (!strcmp (argv[i], "-std=iso9899:199409"))
-	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 0;
-	    opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
-	    opts->trigraphs = 1;
-	    new_pending_define (opts, "__STRICT_ANSI__");
-	    new_pending_define (opts, "__STDC_VERSION__=199409L");
-	  }
-	else if (!strcmp (argv[i], "-std=iso9899:199x")
-		 || !strcmp (argv[i], "-std=iso9899:1999")
-		 || !strcmp (argv[i], "-std=c9x")
-		 || !strcmp (argv[i], "-std=c99"))
+	  break;
+	case OPT_lang_chill:
+	  opts->objc = 0, opts->cplusplus = 0;
+	  opts->chill = 1, opts->traditional = 1;
+	  break;
+	case OPT_nostdinc:
+	  /* -nostdinc causes no default include directories.
+	     You must specify all include-file directories with -I.  */
+	  opts->no_standard_includes = 1;
+	  break;
+	case OPT_nostdincplusplus:
+	  /* -nostdinc++ causes no default C++-specific include directories. */
+	  opts->no_standard_cplusplus_includes = 1;
+	  break;
+	case OPT_std_gnu89:
+	  opts->cplusplus = 0, opts->cplusplus_comments = 1;
+	  opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
+	  break;
+	case OPT_std_gnu9x:
+	case OPT_std_gnu99:
+	  opts->cplusplus = 0, opts->cplusplus_comments = 1;
+	  opts->c89 = 0, opts->c99 = 1, opts->objc = 0;
+	  new_pending_define (opts, "__STDC_VERSION__=199901L");
+	  break;
+	case OPT_std_iso9899_199409:
+	  new_pending_define (opts, "__STDC_VERSION__=199409L");
+	  /* Fall through */
+	case OPT_std_iso9899_1990:
+	case OPT_std_c89:
+	  opts->cplusplus = 0, opts->cplusplus_comments = 0;
+	  opts->c89 = 1, opts->c99 = 0, opts->objc = 0;
+	  opts->trigraphs = 1;
+	  new_pending_define (opts, "__STRICT_ANSI__");
+	  break;
+	case OPT_std_iso9899_199x:
+	case OPT_std_iso9899_1999:
+	case OPT_std_c9x:
+	case OPT_std_c99:
+	  opts->cplusplus = 0, opts->cplusplus_comments = 1;
+	  opts->c89 = 0, opts->c99 = 1, opts->objc = 0;
+	  opts->trigraphs = 1;
+	  new_pending_define (opts, "__STRICT_ANSI__");
+	  new_pending_define (opts, "__STDC_VERSION__=199901L");
+	  break;
+	case OPT_o:
+	  if (opts->out_fname != NULL)
+	    {
+	      cpp_fatal (pfile, "Output filename specified twice");
+	      return argc;
+	    }
+	  opts->out_fname = arg;
+	  if (!strcmp (opts->out_fname, "-"))
+	    opts->out_fname = "";
+	  break;
+	case OPT_v:
+	  fprintf (stderr, _("GNU CPP version %s (cpplib)\n"), version_string);
+#ifdef TARGET_VERSION
+	  TARGET_VERSION;
+#endif
+	  fputc ('\n', stderr);
+	  opts->verbose = 1;
+	  break;
+	case OPT_stdin_stdout:
+	  /* JF handle '-' as file name meaning stdin or stdout */
+	  if (opts->in_fname == NULL)
+	    opts->in_fname = "";
+	  else if (opts->out_fname == NULL)
+	    opts->out_fname = "";
+	  break;
+	case OPT_d:
+	  /* Args to -d specify what parts of macros to dump.
+	     Silently ignore unrecognised options; they may
+	     be aimed at the compiler proper. */
 	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 1;
-	    opts->c89 = 0, opts->c99 = 1, opts->objc = 0;
-	    opts->trigraphs = 1;
-	    new_pending_define (opts, "__STRICT_ANSI__");
-	    new_pending_define (opts, "__STDC_VERSION__=199901L");
-	  }
-	break;
+	    char c;
 
-      case 'w':
-	opts->inhibit_warnings = 1;
-	break;
-      
-      case 'W':
-	if (!strcmp (argv[i], "-Wtrigraphs"))
-	  opts->warn_trigraphs = 1;
-	else if (!strcmp (argv[i], "-Wno-trigraphs"))
-	  opts->warn_trigraphs = 0;
-	else if (!strcmp (argv[i], "-Wcomment"))
-	  opts->warn_comments = 1;
-	else if (!strcmp (argv[i], "-Wno-comment"))
-	  opts->warn_comments = 0;
-	else if (!strcmp (argv[i], "-Wcomments"))
-	  opts->warn_comments = 1;
-	else if (!strcmp (argv[i], "-Wno-comments"))
-	  opts->warn_comments = 0;
-	else if (!strcmp (argv[i], "-Wtraditional"))
-	  opts->warn_stringify = 1;
-	else if (!strcmp (argv[i], "-Wno-traditional"))
-	  opts->warn_stringify = 0;
-	else if (!strcmp (argv[i], "-Wundef"))
-	  opts->warn_undef = 1;
-	else if (!strcmp (argv[i], "-Wno-undef"))
-	  opts->warn_undef = 0;
-	else if (!strcmp (argv[i], "-Wimport"))
-	  opts->warn_import = 1;
-	else if (!strcmp (argv[i], "-Wno-import"))
-	  opts->warn_import = 0;
-	else if (!strcmp (argv[i], "-Werror"))
-	  opts->warnings_are_errors = 1;
-	else if (!strcmp (argv[i], "-Wno-error"))
-	  opts->warnings_are_errors = 0;
-	else if (!strcmp (argv[i], "-Wall"))
-	  {
-	    opts->warn_trigraphs = 1;
-	    opts->warn_comments = 1;
-	  }
-	break;
-      
-      case 'M':
-	/* The style of the choices here is a bit mixed.
-	   The chosen scheme is a hybrid of keeping all options in one string
-	   and specifying each option in a separate argument:
-	   -M|-MM|-MD file|-MMD file [-MG].  An alternative is:
-	   -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
-	   -M[M][G][D file].  This is awkward to handle in specs, and is not
-	   as extensible.  */
-	/* ??? -MG must be specified in addition to one of -M or -MM.
-	   This can be relaxed in the future without breaking anything.
-	   The converse isn't true.  */
-      
-	/* -MG isn't valid with -MD or -MMD.  This is checked for later.  */
-	if (!strcmp (argv[i], "-MG"))
-	  {
-	    opts->print_deps_missing_files = 1;
-	    break;
-	  }
-	if (!strcmp (argv[i], "-M"))
-	  opts->print_deps = 2;
-	else if (!strcmp (argv[i], "-MM"))
-	  opts->print_deps = 1;
-	else if (!strcmp (argv[i], "-MD"))
-	  opts->print_deps = 2;
-	else if (!strcmp (argv[i], "-MMD"))
-	  opts->print_deps = 1;
-	/* For -MD and -MMD options, write deps on file named by next arg.  */
-	if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
-	  {
-	    if (i+1 == argc)
-	      goto missing_filename;
-	    opts->deps_file = argv[++i];
-	  }
-	else
-	  {
-	    /* For -M and -MM, write deps on standard output
-	       and suppress the usual output.  */
-	    opts->no_output = 1;
-	  }	  
-	break;
-      
-      case 'd':
-	{
-	  char *p = argv[i] + 2;
-	  char c;
-	  while ((c = *p++) != 0)
-	    {
-	      /* Arg to -d specifies what parts of macros to dump */
+	    while ((c = *arg++) != '\0')
 	      switch (c)
 		{
 		case 'M':
@@ -1473,72 +1523,47 @@ cpp_handle_option (pfile, argc, argv)
 		  opts->dump_includes = 1;
 		  break;
 		}
-	    }
-	}
-	break;
-    
-      case 'g':
-	if (argv[i][2] == '3')
-	  opts->debug_output = 1;
-	break;
-      
-      case '-':
-	if (!strcmp (argv[i], "--help"))
-	  print_help ();
-	else if (!strcmp (argv[i], "--version"))
-	  fprintf (stderr, _("GNU CPP version %s (cpplib)\n"), version_string);
-	exit (0);  /* XXX */
-	break;
-	
-      case 'v':
-	fprintf (stderr, _("GNU CPP version %s (cpplib)\n"), version_string);
-#ifdef TARGET_VERSION
-	TARGET_VERSION;
-#endif
-	fputc ('\n', stderr);
-	opts->verbose = 1;
-	break;
-      
-      case 'H':
-	opts->print_include_names = 1;
-	break;
+	  }
+	  break;
+	  /* The style of the choices here is a bit mixed.
+	     The chosen scheme is a hybrid of keeping all options in one string
+	     and specifying each option in a separate argument:
+	     -M|-MM|-MD file|-MMD file [-MG].  An alternative is:
+	     -M|-MM|-MD file|-MMD file|-MG|-MMG; or more concisely:
+	     -M[M][G][D file].  This is awkward to handle in specs, and is not
+	     as extensible.  */
+	  /* ??? -MG must be specified in addition to one of -M or -MM.
+	     This can be relaxed in the future without breaking anything.
+	     The converse isn't true.  */
       
-      case 'D':
-	{
-	  const char *text;
-	  if (argv[i][2] != 0)
-	    text = argv[i] + 2;
-	  else if (i + 1 == argc)
-	    {
-	      cpp_fatal (pfile, "Macro name missing after -D option");
-	      return argc;
-	    }
+	  /* -MG isn't valid with -MD or -MMD.  This is checked for later.  */
+	case OPT_MG:
+	  opts->print_deps_missing_files = 1;
+	  break;
+	case OPT_M:
+	case OPT_MD:
+	case OPT_MM:
+	case OPT_MMD:
+	  if (opt_code == OPT_M || opt_code == OPT_MD)
+	    opts->print_deps = 2;
 	  else
-	    text = argv[++i];
-	  new_pending_define (opts, text);
-	}
-	break;
-      
-      case 'A':
-	{
-	  char *p;
-	
-	  if (argv[i][2] != 0)
-	    p = argv[i] + 2;
-	  else if (i + 1 == argc)
-	    {
-	      cpp_fatal (pfile, "Assertion missing after -A option");
-	      return argc;
-	    }
+	    opts->print_deps = 1;
+
+	  /* For -MD and -MMD options, write deps on file named by next arg.  */
+	  /* For -M and -MM, write deps on standard output
+	     and suppress the usual output.  */
+	  if (opt_code == OPT_MD || opt_code == OPT_MMD)
+	      opts->deps_file = arg;
 	  else
-	    p = argv[++i];
-	
-	  if (strcmp (p, "-"))
+	      opts->no_output = 1;
+	  break;
+	case OPT_A:
+	  if (strcmp (arg, "-"))
 	    {
 	      struct pending_option *o = (struct pending_option *)
 		xmalloc (sizeof (struct pending_option));
 
-	      o->arg = p;
+	      o->arg = arg;
 	      o->next = NULL;
 	      o->undef = 0;
 	      APPEND (opts->pending, assert, o);
@@ -1570,81 +1595,148 @@ cpp_handle_option (pfile, argc, argv)
 	      opts->pending->define_head = NULL;
 	      opts->pending->define_tail = NULL;
 	    }
-	}
-	break;
-    
-      case 'U':
-	{
-	  struct pending_option *o = (struct pending_option *)
-	    xmalloc (sizeof (struct pending_option));
+	  break;
+	case OPT_U:
+	  {
+	    struct pending_option *o = (struct pending_option *)
+	      xmalloc (sizeof (struct pending_option));
 	  
-	  if (argv[i][2] != 0)
-	    o->arg = argv[i] + 2;
-	  else if (i + 1 == argc)
+	    o->arg = arg;
+	    o->next = NULL;
+	    o->undef = 1;
+	    APPEND (opts->pending, define, o);
+	  }
+	  break;
+	case OPT_I:           /* Add directory to path for includes.  */
+	  if (!strcmp (arg, "-"))
 	    {
-	      cpp_fatal (pfile, "Macro name missing after -U option");
-	      return argc;
+	      /* -I- means:
+		 Use the preceding -I directories for #include "..."
+		 but not #include <...>.
+		 Don't search the directory of the present file
+		 for #include "...".  (Note that -I. -I- is not the same as
+		 the default setup; -I. uses the compiler's working dir.)  */
+	      if (! opts->ignore_srcdir)
+		{
+		  opts->ignore_srcdir = 1;
+		  opts->pending->quote_head = opts->pending->brack_head;
+		  opts->pending->quote_tail = opts->pending->brack_tail;
+		  opts->pending->brack_head = 0;
+		  opts->pending->brack_tail = 0;
+		}
+	      else
+		{
+		  cpp_fatal (pfile, "-I- specified twice");
+		  return argc;
+		}
 	    }
 	  else
-	    o->arg = argv[++i];
+	    append_include_chain (pfile, opts->pending,
+				  xstrdup (arg), BRACKET);
+	  break;
+	case OPT_isystem:
+	  /* Add directory to beginning of system include path, as a system
+	     include directory. */
+	  append_include_chain (pfile, opts->pending,
+				xstrdup (arg), SYSTEM);
+	  break;
+	case OPT_include:
+	  {
+	    struct pending_option *o = (struct pending_option *)
+	      xmalloc (sizeof (struct pending_option));
+	    o->arg = arg;
+
+	    /* This list has to be built in reverse order so that
+	       when cpp_start_read pushes all the -include files onto
+	       the buffer stack, they will be scanned in forward order.  */
+	    o->next = opts->pending->include_head;
+	    opts->pending->include_head = o;
+	  }
+	  break;
+	case OPT_imacros:
+	  {
+	    struct pending_option *o = (struct pending_option *)
+	      xmalloc (sizeof (struct pending_option));
+	    o->arg = arg;
+	    o->next = NULL;
+	    
+	    APPEND (opts->pending, imacros, o);
+	  }
+	  break;
+	case OPT_iwithprefix:
+	  /* Add directory to end of path for includes,
+	     with the default prefix at the front of its name.  */
+	  /* fall through */
+	case OPT_iwithprefixbefore:
+	  /* Add directory to main path for includes,
+	     with the default prefix at the front of its name.  */
+	  {
+	    char *fname;
+	    int len;
+	    
+	    len = strlen (arg);
 
-	  o->next = NULL;
-	  o->undef = 1;
-	  APPEND (opts->pending, define, o);
+	    if (opts->include_prefix != 0)
+	      {
+		fname = xmalloc (opts->include_prefix_len + len + 1);
+		memcpy (fname, opts->include_prefix, opts->include_prefix_len);
+		memcpy (fname + opts->include_prefix_len, arg, len + 1);
+	      }
+	    else
+	      {
+		fname = xmalloc (sizeof GCC_INCLUDE_DIR - 8 + len);
+		memcpy (fname, GCC_INCLUDE_DIR, sizeof GCC_INCLUDE_DIR - 9);
+		memcpy (fname + sizeof GCC_INCLUDE_DIR - 9, arg, len + 1);
+	      }
+	    
+	    append_include_chain (pfile, opts->pending, fname, 
+				  opt_code == OPT_iwithprefix ? SYSTEM: BRACKET);
+	  }
+	  break;
+	case OPT_idirafter:
+	  /* Add directory to end of path for includes.  */
+	  append_include_chain (pfile, opts->pending,
+				xstrdup (arg), AFTER);
+	  break;
+	case OPT_W:
+	  /* Silently ignore unrecognised options */
+	  if (!strcmp (argv[i], "-Wtrigraphs"))
+	    opts->warn_trigraphs = 1;
+	  else if (!strcmp (argv[i], "-Wno-trigraphs"))
+	    opts->warn_trigraphs = 0;
+	  else if (!strcmp (argv[i], "-Wcomment"))
+	    opts->warn_comments = 1;
+	  else if (!strcmp (argv[i], "-Wno-comment"))
+	    opts->warn_comments = 0;
+	  else if (!strcmp (argv[i], "-Wcomments"))
+	    opts->warn_comments = 1;
+	  else if (!strcmp (argv[i], "-Wno-comments"))
+	    opts->warn_comments = 0;
+	  else if (!strcmp (argv[i], "-Wtraditional"))
+	    opts->warn_stringify = 1;
+	  else if (!strcmp (argv[i], "-Wno-traditional"))
+	    opts->warn_stringify = 0;
+	  else if (!strcmp (argv[i], "-Wundef"))
+	    opts->warn_undef = 1;
+	  else if (!strcmp (argv[i], "-Wno-undef"))
+	    opts->warn_undef = 0;
+	  else if (!strcmp (argv[i], "-Wimport"))
+	    opts->warn_import = 1;
+	  else if (!strcmp (argv[i], "-Wno-import"))
+	    opts->warn_import = 0;
+	  else if (!strcmp (argv[i], "-Werror"))
+	    opts->warnings_are_errors = 1;
+	  else if (!strcmp (argv[i], "-Wno-error"))
+	    opts->warnings_are_errors = 0;
+	  else if (!strcmp (argv[i], "-Wall"))
+	    {
+	      opts->warn_trigraphs = 1;
+	      opts->warn_comments = 1;
+	    }
+	  break;
 	}
-	break;
-      
-      case 'C':
-	opts->discard_comments = 0;
-	break;
-      
-      case 'E':			/* -E comes from cc -E; ignore it.  */
-	break;
-      
-      case 'P':
-	opts->no_line_commands = 1;
-	break;
-      
-      case '$':			/* Don't include $ in identifiers.  */
-	opts->dollars_in_ident = 0;
-	break;
-      
-      case 'n':
-	if (!strcmp (argv[i], "-nostdinc"))
-	  /* -nostdinc causes no default include directories.
-	     You must specify all include-file directories with -I.  */
-	  opts->no_standard_includes = 1;
-	else if (!strcmp (argv[i], "-nostdinc++"))
-	  /* -nostdinc++ causes no default C++-specific include directories. */
-	  opts->no_standard_cplusplus_includes = 1;
-	break;
-      
-      case 'r':
-	if (!strcmp (argv[i], "-remap"))
-	  opts->remap = 1;
-	break;
-      
-      case '\0': /* JF handle '-' as file name meaning stdin or stdout */
-	if (opts->in_fname == NULL)
-	  opts->in_fname = "";
-	else if (opts->out_fname == NULL)
-	  opts->out_fname = "";
-	else
-	  return i;  /* error */
-	break;
-
-      default:
-	return i;
-      }
-
+    }
   return i + 1;
-
- missing_filename:
-  cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
-  return argc;
- missing_dirname:
-  cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
-  return argc;
 }
 
 /* Handle command-line options in (argc, argv).
@@ -1660,6 +1752,14 @@ cpp_handle_options (pfile, argc, argv)
 {
   int i;
   int strings_processed;
+  static int opts_sorted = 0;
+
+  if (!opts_sorted)
+    {
+      opts_sorted = 1;
+      sort_options();
+    }
+
   for (i = 0; i < argc; i += strings_processed)
     {
       strings_processed = cpp_handle_option (pfile, argc - i, argv + i);
@@ -1683,11 +1783,13 @@ Switches:\n\
   -isystem <dir>            Add <dir> to the start of the system include path\n\
   -idirafter <dir>          Add <dir> to the end of the system include path\n\
   -I <dir>                  Add <dir> to the end of the main include path\n\
+  -I-                       Fine-grained include path control; see info docs\n\
   -nostdinc                 Do not search system include directories\n\
                              (dirs specified with -isystem will still be used)\n\
   -nostdinc++               Do not search system include directories for C++\n\
   -o <file>                 Put output into <file>\n\
   -pedantic                 Issue all warnings demanded by strict ANSI C\n\
+  -pedantic-errors          Issue -pedantic warnings as errors instead\n\
   -traditional              Follow K&R pre-processor behaviour\n\
   -trigraphs                Support ANSI C trigraphs\n\
   -lang-c                   Assume that the input sources are in C\n\
@@ -1722,7 +1824,7 @@ Switches:\n\
   -MD                       As -M, but put output in a .d file\n\
   -MMD                      As -MD, but ignore system header files\n\
   -MG                       Treat missing header file as generated files\n\
-  -g                        Include #define and #undef directives in the output\n\
+  -g3                       Include #define and #undef directives in the output\n\
   -D<macro>                 Define a <macro> with string '1' as its value\n\
   -D<macro>=<val>           Define a <macro> with <val> as its value\n\
   -A<question> (<answer>)   Assert the <answer> to <question>\n\
@@ -1738,6 +1840,7 @@ Switches:\n\
   -P                        Do not generate #line directives\n\
   -$                        Do not allow '$' in identifiers\n\
   -remap                    Remap file names when including files.\n\
+  --version                 Display version information\n\
   -h or --help              Display this information\n\
 "), stdout);
 }
Index: cpplib.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cpplib.h,v
retrieving revision 1.56
diff -u -p -r1.56 cpplib.h
--- cpplib.h	2000/02/10 23:47:04	1.56
+++ cpplib.h	2000/02/17 13:18:27
@@ -58,7 +58,6 @@ enum cpp_token {
 typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
 typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader *));
 
-extern int cpp_handle_option PARAMS ((cpp_reader *, int, char **));
 extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
 extern enum cpp_token cpp_get_token PARAMS ((cpp_reader *));
 extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *));

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]