Move main option loop to opts.c

Neil Booth neil@daikokuya.co.uk
Tue Jun 24 23:04:00 GMT 2003


This moves the main loop over argv[] to opts.c, fixes a few missing
"break;"s that were pointed out, and pulls the warning about the
wrong front end to the generic code out of c-opts.c.  We now
get messages like:

$ ./cc1 -fbackslash /tmp/foo.c
cc1: warning: command line option "-fbackslash" is valid for F77 but not for C

Neil.

	* c-opts.c (complain_wrong_lang, write_langs): Remove.
	(c_common_handle_option): Complaints about wrong language are
	handled in opts.c now.
	* opts.c (complain_wrong_lang, write_langs, handle_options): New.
	(find_opt): Fix thinko.
	(handle_option): Update prototype.  Complain about switches for
	a different front end.
	(common_handle_option): Add missing breaks.
	* opts.h (lang_names, handle_options): New.
	(handle_option): Remove.
	* opts.sh: Write out language names array.
	* topelv.c (parse_options_and_default_flags): Use handle_options.
f:
	* top.c (ffe_handle_option): Add missing break.
	
Index: c-opts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-opts.c,v
retrieving revision 1.62
diff -u -p -r1.62 c-opts.c
--- c-opts.c	22 Jun 2003 13:41:24 -0000	1.62
+++ c-opts.c	24 Jun 2003 22:15:00 -0000
@@ -102,8 +102,6 @@ static size_t include_cursor;
 
 static void missing_arg (enum opt_code);
 static void set_Wimplicit (int);
-static void complain_wrong_lang (size_t, int);
-static void write_langs (char *, int);
 static void print_help (void);
 static void handle_OPT_d (const char *);
 static void set_std_cxx98 (int);
@@ -245,7 +243,7 @@ c_common_handle_option (size_t scode, co
 {
   const struct cl_option *option = &cl_options[scode];
   enum opt_code code = (enum opt_code) scode;
-  int result = 1, lang_mask;
+  int result = 1;
 
   if (code == N_OPTS)
     {
@@ -259,13 +257,6 @@ c_common_handle_option (size_t scode, co
       return 1;
     }
 
-  lang_mask = lang_flags[(c_language << 1) + flag_objc];
-  if (!(option->flags & lang_mask))
-    {
-      complain_wrong_lang (code, value);
-      return 1;
-    }
-
   if (arg == NULL && (option->flags & (CL_JOINED | CL_SEPARATE)))
     {
       missing_arg (code);
@@ -1509,42 +1500,6 @@ handle_OPT_d (const char *arg)
 	flag_dump_includes = 1;
 	break;
       }
-}
-
-/* Write a slash-separated list of languages in FLAGS to BUF.  */
-static void
-write_langs (char *buf, int flags)
-{
-  *buf = '\0';
-  if (flags & CL_C)
-    strcat (buf, "C");
-  if (flags & CL_ObjC)
-    {
-      if (*buf)
-	strcat (buf, "/");
-      strcat (buf, "ObjC");
-    }
-  if (flags & CL_CXX)
-    {
-      if (*buf)
-	strcat (buf, "/");
-      strcat (buf, "C++");
-    }
-}
-
-/* Complain that switch OPT_INDEX does not apply to this front end.  */
-static void
-complain_wrong_lang (size_t opt_index, int on)
-{
-  char ok_langs[60], bad_langs[60];
-  int ok_flags = cl_options[opt_index].flags;
-
-  write_langs (ok_langs, ok_flags);
-  write_langs (bad_langs, ~ok_flags);
-  /* Eventually this should become a hard error.  */
-  warning ("\"-%c%s%s\" is valid for %s but not for %s",
-	   cl_options[opt_index].opt_text[0], on ? "" : "no-",
-	   cl_options[opt_index].opt_text + 1, ok_langs, bad_langs);
 }
 
 /* Handle --help output.  */
Index: opts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/opts.c,v
retrieving revision 1.14
diff -u -p -r1.14 opts.c
--- opts.c	22 Jun 2003 20:21:34 -0000	1.14
+++ opts.c	24 Jun 2003 22:15:01 -0000
@@ -129,6 +129,10 @@ static size_t find_opt (const char *, in
 static int common_handle_option (size_t scode, const char *arg, int value);
 static void handle_param (const char *);
 static void set_Wextra (int);
+static unsigned int handle_option (char **argv, unsigned int lang_mask);
+static char *write_langs (unsigned int lang_mask);
+static void complain_wrong_lang (const char *, const struct cl_option *,
+				 unsigned int lang_mask);
 
 /* Perform a binary search to find which option the command-line INPUT
    matches.  Returns its index in the option array, and N_OPTS
@@ -200,7 +204,7 @@ find_opt (const char *input, int lang_ma
 
 	  /* If we haven't remembered a prior match, remember this
 	     one.  Any prior match is necessarily better.  */
-	  if (match_wrong_lang != cl_options_count)
+	  if (match_wrong_lang == cl_options_count)
 	    match_wrong_lang = mn;
 	}
 
@@ -230,15 +234,62 @@ integral_argument (const char *arg)
   return -1;
 }
 
-/* Handle the switch beginning at ARGV, with ARGC remaining.  */
-int
-handle_option (int argc ATTRIBUTE_UNUSED, char **argv, int lang_mask)
+/* Return a malloced slash-separated list of languages in MASK.  */
+static char *
+write_langs (unsigned int mask)
+{
+  unsigned int n = 0, len = 0;
+  const char *lang_name;
+  char *result;
+
+  for (n = 0; (lang_name = lang_names[n]) != 0; n++)
+    if (mask & (1U << n))
+      len += strlen (lang_name) + 1;
+
+  result = xmalloc (len);
+  len = 0;
+  for (n = 0; (lang_name = lang_names[n]) != 0; n++)
+    if (mask & (1U << n))
+      {
+	if (len)
+	  result[len++] = '/';
+	strcpy (result + len, lang_name);
+	len += strlen (lang_name);
+      }
+
+  result[len] = 0;
+
+  return result;
+}
+
+/* Complain that switch OPT_INDEX does not apply to this front end.  */
+static void
+complain_wrong_lang (const char *text, const struct cl_option *option,
+		     unsigned int lang_mask)
+{
+  char *ok_langs, *bad_lang;
+
+  ok_langs = write_langs (option->flags);
+  bad_lang = write_langs (lang_mask);
+
+  /* Eventually this should become a hard error IMO.  */
+  warning ("command line option \"%s\" is valid for %s but not for %s",
+	   text, ok_langs, bad_lang);
+
+  free (ok_langs);
+  free (bad_lang);
+}
+
+/* Handle the switch beginning at ARGV for the language indicated by
+   LANG_MASK.  Returns the number of switches consumed.  */
+static unsigned int
+handle_option (char **argv, unsigned int lang_mask)
 {
   size_t opt_index;
   const char *opt, *arg = 0;
   char *dup = 0;
   int value = 1;
-  int result = 0;
+  unsigned int result = 0;
   const struct cl_option *option;
 
   opt = argv[0];
@@ -273,7 +324,8 @@ handle_option (int argc ATTRIBUTE_UNUSED
 
       option = &cl_options[opt_index];
 
-      /* Reject negative form of switches that don't take negatives.  */
+      /* Reject negative form of switches that don't take negatives as
+	 unrecognized.  */
       if (!value && (option->flags & CL_REJECT_NEGATIVE))
 	goto done;
 
@@ -308,6 +360,14 @@ handle_option (int argc ATTRIBUTE_UNUSED
 	  result = 2;
 	}
 
+      /* Now we've swallowed any potential argument, complain if this
+	 is a switch for a different front end.  */
+      if (!(option->flags & (lang_mask | CL_COMMON)))
+	{
+	  complain_wrong_lang (argv[0], option, lang_mask);
+	  goto done;
+	}
+
       /* If the switch takes an integer, convert it.  */
       if (arg && (option->flags & CL_UINTEGER))
 	{
@@ -335,6 +395,26 @@ handle_option (int argc ATTRIBUTE_UNUSED
   return result;
 }
 
+/* Decode and handle the vector of command line options.  LANG_MASK
+   contains has a single bit set representing the current
+   language.  */
+void
+handle_options (unsigned int argc, char **argv, unsigned int lang_mask)
+{
+  unsigned int n, i;
+
+  for (i = 1; i < argc; i += n)
+    {
+      n = handle_option (argv + i, lang_mask);
+
+      if (!n)
+	{
+	  n = 1;
+	  error ("unrecognized command line option \"%s\"", argv[i]);
+	}
+    }
+}
+
 /* Handle target- and language-independent options.  Return zero to
    generate an "unknown option" message.  */
 static int
@@ -399,6 +479,7 @@ common_handle_option (size_t scode, cons
 
     case OPT_Wdeprecated_declarations:
       warn_deprecated_decl = value;
+      break;
 
     case OPT_Wdisabled_optimization:
       warn_disabled_optimization = value;
@@ -1015,6 +1096,7 @@ common_handle_option (size_t scode, cons
 
     case OPT_ftime_report:
       time_report = value;
+      break;
 
     case OPT_ftls_model_:
       if (!strcmp (arg, "global-dynamic"))
Index: opts.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/opts.h,v
retrieving revision 1.6
diff -u -p -r1.6 opts.h
--- opts.h	22 Jun 2003 09:04:57 -0000	1.6
+++ opts.h	24 Jun 2003 22:15:01 -0000
@@ -21,7 +21,8 @@ Software Foundation, 59 Temple Place - S
 #ifndef GCC_OPTS_H
 #define GCC_OPTS_H
 
-extern int handle_option (int argc, char **argv, int lang_mask);
+extern void handle_options (unsigned int argc, char **argv,
+			    unsigned int lang_mask);
 
 struct cl_option
 {
@@ -33,6 +34,7 @@ struct cl_option
 
 extern const struct cl_option cl_options[];
 extern const unsigned int cl_options_count;
+extern const char *const lang_names[];
 
 #define CL_JOINED		(1 << 24) /* If takes joined argument.  */
 #define CL_SEPARATE		(1 << 25) /* If takes a separate argument.  */
Index: opts.sh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/opts.sh,v
retrieving revision 1.18
diff -u -p -r1.18 opts.sh
--- opts.sh	22 Jun 2003 20:21:35 -0000	1.18
+++ opts.sh	24 Jun 2003 22:15:01 -0000
@@ -85,20 +85,25 @@ ${AWK} '
 	h_file = "'${H_FILE}'"
 	comma = ","
 
+	print "/* This file is auto-generated by opts.sh.  */\n" > c_file
+	print "#include \"" h_file "\""			>> c_file
+	print "#include \"opts.h\"\n"			>> c_file
+	print "const char * const lang_names[] =\n{"	>> c_file
+
 	print "/* This file is auto-generated by opts.sh.  */\n" > h_file
 	for (i = 0; i < n_langs; i++) {
 	    macros[i] = "CL_" langs[i]
 	    gsub( "[^A-Za-z0-9_]", "X", macros[i] )
 	    s = substr("         ", length (macros[i]))
 	    print "#define " macros[i] s " (1 << " i ")" >> h_file
+	    print "  \"" langs[i] "\","			>> c_file
 	}
-	print "\nenum opt_code\n{"			>> h_file
 
-	print "/* This file is auto-generated by opts.sh.  */\n" > c_file
-	print "#include \"" h_file "\""			>> c_file
-	print "#include \"opts.h\"\n"			>> c_file
+	print "  0\n};\n"				>> c_file
 	print "const unsigned int cl_options_count = N_OPTS;\n" >> c_file
 	print "const struct cl_option cl_options[] =\n{" >> c_file
+
+	print "\nenum opt_code\n{"			>> h_file
 
 	for (i = 0; i < n_opts; i++)
 	    back_chain[i] = "N_OPTS";
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.786
diff -u -p -r1.786 toplev.c
--- toplev.c	24 Jun 2003 16:50:28 -0000	1.786
+++ toplev.c	24 Jun 2003 22:15:02 -0000
@@ -4735,58 +4735,7 @@ parse_options_and_default_flags (int arg
   OPTIMIZATION_OPTIONS (optimize, optimize_size);
 #endif
 
-  /* Perform normal command line switch decoding.  */
-  for (i = 1; i < argc;)
-    {
-      int processed;
-
-      /* Give the language a chance to decode the option for itself.  */
-      processed = handle_option (argc - i, argv + i, lang_mask);
-
-      if (processed)
-	i += processed;
-      else
-	{
-	  const char *option = NULL;
-	  const char *lang = NULL;
-	  unsigned int j;
-
-	  /* It is possible that the command line switch is not valid for the
-	     current language, but it is valid for another language.  In order
-	     to be compatible with previous versions of the compiler (which
-	     did not issue an error message in this case) we check for this
-	     possibility here.  If we do find a match, then if extra_warnings
-	     is set we generate a warning message, otherwise we will just
-	     ignore the option.  */
-	  for (j = 0; j < ARRAY_SIZE (documented_lang_options); j++)
-	    {
-	      option = documented_lang_options[j].option;
-
-	      if (option == NULL)
-		lang = documented_lang_options[j].description;
-	      else if (! strncmp (argv[i], option, strlen (option)))
-		break;
-	    }
-
-	  if (j != ARRAY_SIZE (documented_lang_options))
-	    {
-	      if (extra_warnings)
-		{
-		  warning ("ignoring command line option '%s'", argv[i]);
-		  if (lang)
-		    warning
-		      ("(it is valid for %s but not the selected language)",
-		       lang);
-		}
-	    }
-	  else if (argv[i][0] == '-' && argv[i][1] == 'g')
-	    warning ("`%s': unknown or unsupported -g option", &argv[i][2]);
-	  else
-	    error ("unrecognized option `%s'", argv[i]);
-
-	  i++;
-	}
-    }
+  handle_options (argc, argv, lang_mask);
 
   if (flag_pie)
     flag_pic = flag_pie;
Index: f/top.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/f/top.c,v
retrieving revision 1.34
diff -u -p -r1.34 top.c
--- f/top.c	21 Jun 2003 20:28:18 -0000	1.34
+++ f/top.c	24 Jun 2003 22:15:03 -0000
@@ -440,6 +440,7 @@ ffe_handle_option (size_t scode, const c
       ffe_set_case_match (FFE_caseNONE);
       ffe_set_case_source (FFE_caseLOWER);
       ffe_set_case_symbol (FFE_caseNONE);
+      break;
 
     case OPT_fcase_preserve:
       ffe_set_case_intrin (FFE_caseNONE);



More information about the Gcc-patches mailing list