Patchwork Make lang_specific_driver use cl_decoded_option structures

login
register
mail settings
Submitter Joseph S. Myers
Date Aug. 18, 2010, 8:58 p.m.
Message ID <Pine.LNX.4.64.1008182057100.3690@digraph.polyomino.org.uk>
Download mbox | patch
Permalink /patch/62089/
State New
Headers show

Comments

Joseph S. Myers - Aug. 18, 2010, 8:58 p.m.
This patch continues the transition to using central option-processing
code everywhere by moving lang_specific_driver to working with
cl_decoded_option structures rather than the argv array.

In the process of so doing, various oddities in the code have been
noted, and some fixed while others are left for discussion of the
desired semantics and fixing by front-end maintainers.

* The drivers had various different versions of logic to determine
  what is an option and what is an option argument, most of which
  could go wrong in some cases.  This is fixed by using the central
  logic in opts-common.c (which in turn uses *SWITCH_TAKES_ARG for
  unknown options) to produce the cl_decoded_option structures.  (The
  code for translating options in the driver, and do_self_spec, still
  need converting to use the central logic to eliminate the remaining
  possibilities for such inconsistencies.)  Similarly, the drivers
  would inconsistently try to give errors for missing option
  arguments; this is now unambiguously the responsibility of the
  central option processing code (while the drivers just need to check
  for CL_ERR_MISSING_ARG in some cases to avoid dereferencing null
  pointers).

* Some of the ad hoc checks for options taking arguments still handled
  the -b and -V options that were removed a while back.  Similarly,
  the Fortran driver's option processing code handled those options.
  The -b and -V handling is removed.

* The drivers would handle non-option arguments "", "-", other
  single-character arguments and longer non-option arguments in
  various ways inconsistent from driver to driver and between the
  different types of such arguments listed above.  I have tried to
  keep the logic in question the same as before this patch, although
  probably it should be fixed for greater consistency (except where
  special handling for "-" as stdin is needed, which may just be in
  cppspec.c, by treating all these cases the same as longer
  non-options, I think).

* Because of string comparison when the drivers checked for options
  such as "-lc" or "-lm" already being present, some drivers checking
  for such options would fail to detect what should be equivalent
  forms split into two arguments such as "-l c".  Fixed by using
  cl_decoded_option structures.

* The C++ driver checked for an option "-ObjC++".  No such option
  exists; it would be passed through to cc1plus, which would then
  reject it.  The code for this option is removed.

* The Fortran code has an error "overflowed output arg list for %qs"
  that is a call to fatal_error but looks like it should be an
  internal_error instead since if it triggers there is a bug in the
  calculation of how large the new option list should be.  The patch
  does not change this.  (Actually, it would be better just to resize
  dynamically as needed rather than hardcoding a calculation of the
  maximum size that might be needed, and so eliminate this error
  completely.  The same applies in other drivers)

* The Fortran driver has another relic of code for the C++ +e option
  (recall that this was removed in 2.95 and I removed further relics
  in <http://gcc.gnu.org/ml/gcc-patches/2010-06/msg02407.html>).
  This is removed by this patch.

* The Fortran driver had a comment saying "Also, if -v is specified,
  but no other options that do anything special (allowing -V version,
  etc.), remember to add special stuff to make gcc command actually
  invoke all the different phases of the compilation process so all
  the version numbers can be seen.".  Apart from the reference to -V,
  there is nothing special in the Fortran code at all regarding the
  lack of other options with -v.

* The Fortran driver has a comment about "-lg2c -lm" but it always
  appears to use -lgfortran, not -lg2c.  Left unchanged.

* There are various target macros (defaulted with #ifndef in
  individual driver files) to control the libraries for different
  languages etc. - MATH_LIBRARY is documented in tm.texi.in, but
  MATH_LIBRARY_PROFILE, LIBSTDCXX, LIBSTDCXX_PROFILE, LIBSTDCXX_STATIC
  and FORTRAN_LIBRARY are not.  (No target actually has a non-default
  value of LIBSTDCXX_PROFILE or FORTRAN_LIBRARY, but by analogy with
  the others they should still be considered target macros.)  Left
  unchanged.

* The Java driver has its own support for @FILE files but expandargv
  has already been called by the time lang_specific_driver is reached
  so I think this is dead code.  Left unchanged.

* The Java driver handles various options that were not previously
  known to the other drivers: -classpath, -bootclasspath, -CLASSPATH,
  -encoding, -extdirs.  I entered these in the .opt file, so now the
  generic driver will handle them as taking arguments - and then
  reject them later as not being processed by any spec if it wouldn't
  have accepted them anyway because of some spec that handled them.
  In general I think such a change is a good idea because differences
  between the drivers are bad - the existence of separate drivers is
  to some extent a workaround for the generic driver not being able to
  tell which runtime libraries are needed by the object files it is
  linking.  It may however change behavior in corner cases, where
  -encoding or -extdirs were used as linker options to say that a
  symbol "ncoding" or "xtdirs" is the entry point.

* The Java -d option - -d with a separate argument being an alias for
  -foutput-class-dir= - is problematic in that it is incompatible with
  the semantics of -d with a joined argument.  For now I made
  translate_options handle it (for all languages); when
  translate_options becomes generic .opt alias machinery, that
  machinery will need to handle this special case of joined and
  separate arguments having different semantics.

* Java -extdirs is also peculiar in that it is different from
  -fextdirs/--extdirs; -extdirs is processed by the driver only, not
  directly generating jc1 options, while -fextdirs is processed by jc1
  only.  This may not result in any semantic differences, but looks
  odd.

* The Java driver handled "--syntax-only" and "--indirect-dispatch"
  but those would have been translated to the -f forms before
  lang_specific_driver is called; such handling is removed as useless.

Bootstrapped with no regressions on x86_64-unknown-linux-gnu.  OK to
commit?

2010-08-18  Joseph Myers  <joseph@codesourcery.com>

	* Makefile.in (gccspec.o, cppspec.o): Update dependencies.
	* common.opt (L, nodefaultlibs, nostdlib, pg, static): New
	options.
	* config/avr/avr.h (LIBSTDCXX): Remove initial "-l".
	* config/freebsd.h (MATH_LIBRARY_PROFILE): Remove initial "-l".
	* config/i386/djgpp.h (LIBSTDCXX): Remove initial "-l".
	* config/rs6000/aix.h (LIBSTDCXX_STATIC): Remove initial "-l".
	* config/s390/tpf.h (MATH_LIBRARY, LIBSTDCXX): Remove initial
	"-l".
	* cppspec.c: Include opts.h.
	(lang_specific_driver): Use cl_decoded_option structures.
	* doc/tm.texi.in (MATH_LIBRARY): Update documentation.
	* doc/tm.texi: Regenerate.
	* gcc.c (translate_options): Translate -d to -foutput-class-dir=.
	(driver_handle_option): Allow driver options needing no special
	processing.
	(process_command): Decode options before call to
	lang_specific_driver.  Pass decoded options to
	lang_specific_driver.
	* gcc.h (lang_specific_driver): Update prototype.
	* gccspec.c: Include opts.h.
	(lang_specific_driver): Use cl_decoded_option structures.
	* opts-common.c (option_ok_for_language, generate_option,
	generate_option_input_file): New.
	(decode_cmdline_option): Use option_ok_for_language.
	(decode_cmdline_options_to_array): Use generate_option_input_file.
	(handle_generated_option): Use generate_option.
	* opts.h (generate_option, generate_option_input_file): Declare.

cp:
2010-08-18  Joseph Myers  <joseph@codesourcery.com>

	* Make-lang.in (g++spec.o): Update dependencies.
	* g++spec.c: Include opts.h
	(MATH_LIBRARY, LIBSTDCXX): Remove initial "-l".
	(lang_specific_driver): Use cl_decoded_option structures.

fortran:
2010-08-18  Joseph Myers  <joseph@codesourcery.com>

	* Make-lang.in (gfortranspec.o): Update dependencies.
	* gfortranspec.c: Include coretypes.h before gcc.h.  Include
	opts.h.
	(MATH_LIBRARY, FORTRAN_LIBRARY): Remove initial "-l".
	(ADD_ARG_LIBGFORTRAN, Option, lookup_option): Remove.
	(g77_xargc): Make unsigned.
	(g77_xargv): Change to g77_x_decoded_options.
	(g77_newargc): Make unsigned.
	(g77_newargv): Change to g77_new_decoded_options.
	(strings_same, options_same): New.
	(append_arg): Use cl_decoded_option structures.
	(append_option): New.
	(add_arg_libgfortran): New.
	(lang_specific_driver): Use cl_decoded_option structures.

java:
2010-08-18  Joseph Myers  <joseph@codesourcery.com>

	* Make-lang.in (jvspec.o): Update dependencies.
	* jvspec.c: Include opts.h.
	(PARAM_ARG): Remove.
	(find_spec_file): Do not add leading -specs=.
	(lang_specific_driver): Use cl_decoded_option structures.
	* lang.opt (C, CLASSPATH, D, bootclasspath, classpath, encoding,
	extdirs, fmain=, s-bc-abi): New options.
Mark Mitchell - Aug. 20, 2010, 4:22 a.m.
Joseph S. Myers wrote:

> This patch continues the transition to using central option-processing
> code everywhere by moving lang_specific_driver to working with
> cl_decoded_option structures rather than the argv array

OK if no objections from front-end maintainers within 48 hours.

Thanks,
Tobias Burnus - Aug. 20, 2010, 6:19 a.m.
Am 18.08.2010 22:58, schrieb Joseph S. Myers:
> * The Fortran code has an error "overflowed output arg list for %qs"
>    that is a call to fatal_error but looks like it should be an
>    internal_error instead since if it triggers there is a bug in the
>    calculation of how large the new option list should be.  The patch
>    does not change this.  (Actually, it would be better just to resize
>    dynamically as needed rather than hardcoding a calculation of the
>    maximum size that might be needed, and so eliminate this error
>    completely.  The same applies in other drivers)

Maybe it would be useful to change this to an internal error to increase 
the chance that it gets reported. (Though, seemingly no user has 
encountered this problem so far). I concur that resizing would be the 
proper solution.

> * The Fortran driver had a comment saying "Also, if -v is specified,
>    but no other options that do anything special (allowing -V version,
>    etc.), remember to add special stuff to make gcc command actually
>    invoke all the different phases of the compilation process so all
>    the version numbers can be seen.".  Apart from the reference to -V,
>    there is nothing special in the Fortran code at all regarding the
>    lack of other options with -v.

Could you update the comment?

> * The Fortran driver has a comment about "-lg2c -lm" but it always
>    appears to use -lgfortran, not -lg2c.  Left unchanged.

That's probably a copy from g77, which used g2c. Could you change this 
to -lgfortran.

Thanks for your patch - it is fantastic that someone does this 
janitorial work! (For completeness: The Fortran changes are OK.)

Tobias

> fortran:
> 2010-08-18  Joseph Myers<joseph@codesourcery.com>
>
> 	* Make-lang.in (gfortranspec.o): Update dependencies.
> 	* gfortranspec.c: Include coretypes.h before gcc.h.  Include
> 	opts.h.
> 	(MATH_LIBRARY, FORTRAN_LIBRARY): Remove initial "-l".
> 	(ADD_ARG_LIBGFORTRAN, Option, lookup_option): Remove.
> 	(g77_xargc): Make unsigned.
> 	(g77_xargv): Change to g77_x_decoded_options.
> 	(g77_newargc): Make unsigned.
> 	(g77_newargv): Change to g77_new_decoded_options.
> 	(strings_same, options_same): New.
> 	(append_arg): Use cl_decoded_option structures.
> 	(append_option): New.
> 	(add_arg_libgfortran): New.
> 	(lang_specific_driver): Use cl_decoded_option structures.
Joseph S. Myers - Aug. 20, 2010, 11:41 a.m.
On Fri, 20 Aug 2010, Tobias Burnus wrote:

> > * The Fortran driver had a comment saying "Also, if -v is specified,
> >    but no other options that do anything special (allowing -V version,
> >    etc.), remember to add special stuff to make gcc command actually
> >    invoke all the different phases of the compilation process so all
> >    the version numbers can be seen.".  Apart from the reference to -V,
> >    there is nothing special in the Fortran code at all regarding the
> >    lack of other options with -v.
> 
> Could you update the comment?

The patch does update the comment; sorry, that wasn't clear in my 
description of the issue.  That seemed better than just removing the -V 
mention along with the -V handling (and removing the subsequent paragraph 
about missing arguments, now caught elsewhere) and leaving the rest of the 
comment unchanged.

   /* First pass through arglist.
 
      If -nostdlib or a "turn-off-linking" option is anywhere in the
      command line, don't do any library-option processing (except
-     relating to -x).  Also, if -v is specified, but no other options
-     that do anything special (allowing -V version, etc.), remember
-     to add special stuff to make gcc command actually invoke all
-     the different phases of the compilation process so all the version
-     numbers can be seen.
-
-     Also, here is where all problems with missing arguments to options
-     are caught.  If this loop is exited normally, it means all options
-     have the appropriate number of arguments as far as the rest of this
-     program is concerned.  */
+     relating to -x).  */

Patch

Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 163280)
+++ gcc/doc/tm.texi	(working copy)
@@ -10694,10 +10694,11 @@  for overlap with regards to asm-declared
 
 @defmac MATH_LIBRARY
 Define this macro as a C string constant for the linker argument to link
-in the system math library, or @samp{""} if the target does not have a
+in the system math library, minus the initial @samp{"-l"}, or
+@samp{""} if the target does not have a
 separate math library.
 
-You need only define this macro if the default of @samp{"-lm"} is wrong.
+You need only define this macro if the default of @samp{"m"} is wrong.
 @end defmac
 
 @defmac LIBRARY_PATH_ENV
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in	(revision 163280)
+++ gcc/doc/tm.texi.in	(working copy)
@@ -10674,10 +10674,11 @@  for overlap with regards to asm-declared
 
 @defmac MATH_LIBRARY
 Define this macro as a C string constant for the linker argument to link
-in the system math library, or @samp{""} if the target does not have a
+in the system math library, minus the initial @samp{"-l"}, or
+@samp{""} if the target does not have a
 separate math library.
 
-You need only define this macro if the default of @samp{"-lm"} is wrong.
+You need only define this macro if the default of @samp{"m"} is wrong.
 @end defmac
 
 @defmac LIBRARY_PATH_ENV
Index: gcc/opts-common.c
===================================================================
--- gcc/opts-common.c	(revision 163280)
+++ gcc/opts-common.c	(working copy)
@@ -127,6 +127,23 @@  integral_argument (const char *arg)
   return -1;
 }
 
+/* Return whether OPTION is OK for the language given by
+   LANG_MASK.  */
+static bool
+option_ok_for_language (const struct cl_option *option,
+			unsigned int lang_mask)
+{
+  if (!(option->flags & lang_mask))
+    return false;
+  else if ((option->flags & CL_TARGET)
+	   && (option->flags & (CL_LANG_ALL | CL_DRIVER))
+	   && !(option->flags & (lang_mask & ~CL_COMMON & ~CL_TARGET)))
+    /* Complain for target flag language mismatches if any languages
+       are specified.  */
+    return false;
+  return true;
+}
+
 /* Decode the switch beginning at ARGV for the language indicated by
    LANG_MASK (including CL_COMMON and CL_TARGET if applicable), into
    the structure *DECODED.  Returns the number of switches
@@ -228,14 +245,8 @@  decode_cmdline_option (const char **argv
     }
 
   /* Check if this is a switch for a different front end.  */
-  if (!(option->flags & lang_mask))
+  if (!option_ok_for_language (option, lang_mask))
     errors |= CL_ERR_WRONG_LANG;
-  else if ((option->flags & CL_TARGET)
-	   && (option->flags & (CL_LANG_ALL | CL_DRIVER))
-	   && !(option->flags & (lang_mask & ~CL_COMMON & ~CL_TARGET)))
-    /* Complain for target flag language mismatches if any languages
-       are specified.  */
-      errors |= CL_ERR_WRONG_LANG;
 
   if (arg == NULL && (separate_arg_flag || joined_arg_flag))
     errors |= CL_ERR_MISSING_ARG;
@@ -346,16 +357,7 @@  decode_cmdline_options_to_array (unsigne
       /* Interpret "-" or a non-switch as a file name.  */
       if (opt[0] != '-' || opt[1] == '\0')
 	{
-	  opt_array[num_decoded_options].opt_index = OPT_SPECIAL_input_file;
-	  opt_array[num_decoded_options].arg = opt;
-	  opt_array[num_decoded_options].orig_option_with_args_text = opt;
-	  opt_array[num_decoded_options].canonical_option_num_elements = 1;
-	  opt_array[num_decoded_options].canonical_option[0] = opt;
-	  opt_array[num_decoded_options].canonical_option[1] = NULL;
-	  opt_array[num_decoded_options].canonical_option[2] = NULL;
-	  opt_array[num_decoded_options].canonical_option[3] = NULL;
-	  opt_array[num_decoded_options].value = 1;
-	  opt_array[num_decoded_options].errors = 0;
+	  generate_option_input_file (opt, &opt_array[num_decoded_options]);
 	  num_decoded_options++;
 	  n = 1;
 	  continue;
@@ -550,45 +552,76 @@  handle_generated_option (size_t opt_inde
 			 unsigned int lang_mask, int kind,
 			 const struct cl_option_handlers *handlers)
 {
-  const struct cl_option *option = &cl_options[opt_index];
   struct cl_decoded_option decoded;
 
-  decoded.opt_index = opt_index;
-  decoded.arg = arg;
-  decoded.canonical_option[2] = NULL;
-  decoded.canonical_option[3] = NULL;
-  decoded.value = value;
-  decoded.errors = 0;
+  generate_option (opt_index, arg, value, lang_mask, &decoded);
+  return handle_option (&decoded, lang_mask, kind, handlers);
+}
+
+/* Fill in *DECODED with an option described by OPT_INDEX, ARG and
+   VALUE for a front end using LANG_MASK.  This is used when the
+   compiler generates options internally.  */
+
+void
+generate_option (size_t opt_index, const char *arg, int value,
+		 unsigned int lang_mask, struct cl_decoded_option *decoded)
+{
+  const struct cl_option *option = &cl_options[opt_index];
+
+  decoded->opt_index = opt_index;
+  decoded->arg = arg;
+  decoded->canonical_option[2] = NULL;
+  decoded->canonical_option[3] = NULL;
+  decoded->value = value;
+  decoded->errors = (option_ok_for_language (option, lang_mask)
+		     ? 0
+		     : CL_ERR_WRONG_LANG);
 
   if (arg)
     {
       if (option->flags & CL_SEPARATE)
 	{
-	  decoded.orig_option_with_args_text = concat (option->opt_text, " ",
-						       arg, NULL);
-	  decoded.canonical_option[0] = option->opt_text;
-	  decoded.canonical_option[1] = arg;
-	  decoded.canonical_option_num_elements = 2;
+	  decoded->orig_option_with_args_text = concat (option->opt_text, " ",
+							arg, NULL);
+	  decoded->canonical_option[0] = option->opt_text;
+	  decoded->canonical_option[1] = arg;
+	  decoded->canonical_option_num_elements = 2;
 	}
       else
 	{
 	  gcc_assert (option->flags & CL_JOINED);
-	  decoded.orig_option_with_args_text = concat (option->opt_text, arg,
-						       NULL);
-	  decoded.canonical_option[0] = decoded.orig_option_with_args_text;
-	  decoded.canonical_option[1] = NULL;
-	  decoded.canonical_option_num_elements = 1;
+	  decoded->orig_option_with_args_text = concat (option->opt_text, arg,
+							NULL);
+	  decoded->canonical_option[0] = decoded->orig_option_with_args_text;
+	  decoded->canonical_option[1] = NULL;
+	  decoded->canonical_option_num_elements = 1;
 	}
     }
   else
     {
-      decoded.orig_option_with_args_text = option->opt_text;
-      decoded.canonical_option[0] = option->opt_text;
-      decoded.canonical_option[1] = NULL;
-      decoded.canonical_option_num_elements = 1;
+      decoded->orig_option_with_args_text = option->opt_text;
+      decoded->canonical_option[0] = option->opt_text;
+      decoded->canonical_option[1] = NULL;
+      decoded->canonical_option_num_elements = 1;
     }
+}
 
-  return handle_option (&decoded, lang_mask, kind, handlers);
+/* Fill in *DECODED with an option for input file FILE.  */
+
+void
+generate_option_input_file (const char *file,
+			    struct cl_decoded_option *decoded)
+{
+  decoded->opt_index = OPT_SPECIAL_input_file;
+  decoded->arg = file;
+  decoded->orig_option_with_args_text = file;
+  decoded->canonical_option_num_elements = 1;
+  decoded->canonical_option[0] = file;
+  decoded->canonical_option[1] = NULL;
+  decoded->canonical_option[2] = NULL;
+  decoded->canonical_option[3] = NULL;
+  decoded->value = 1;
+  decoded->errors = 0;
 }
 
 /* Handle the switch DECODED for the language indicated by LANG_MASK,
Index: gcc/java/Make-lang.in
===================================================================
--- gcc/java/Make-lang.in	(revision 163280)
+++ gcc/java/Make-lang.in	(working copy)
@@ -57,7 +57,7 @@  JAVA_TARGET_INDEPENDENT_BIN_TOOLS = jcf-
 .PHONY: java
 
 jvspec.o: $(srcdir)/java/jvspec.c $(SYSTEM_H) coretypes.h $(TM_H) \
-  $(GCC_H) $(CONFIG_H) java/jcf.h java/javaop.h
+  $(GCC_H) $(CONFIG_H) java/jcf.h java/javaop.h opts.h
 	(SHLIB_LINK='$(SHLIB_LINK)'; \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
 		$(INCLUDES) $(srcdir)/java/jvspec.c $(OUTPUT_OPTION))
Index: gcc/java/jvspec.c
===================================================================
--- gcc/java/jvspec.c	(revision 163280)
+++ gcc/java/jvspec.c	(working copy)
@@ -29,14 +29,13 @@  The Free Software Foundation is independ
 #include "tm.h"
 #include "gcc.h"
 #include "jcf.h"
+#include "opts.h"
 
 /* Name of spec file.  */
 #define SPEC_FILE "libgcj.spec"
 
 /* This bit is set if we saw a `-xfoo' language specification.  */
 #define LANGSPEC	(1<<1)
-/* True if this arg is a parameter to the previous option-taking arg. */
-#define PARAM_ARG	(1<<2)
 /* True if this arg is a .java input file name. */
 #define JAVA_FILE_ARG	(1<<3)
 /* True if this arg is a .class input file name. */
@@ -88,17 +87,13 @@  static char *
 find_spec_file (const char *dir)
 {
   char *spec;
-  int x;
   struct stat sb;
 
-  spec = XNEWVEC (char, strlen (dir) + sizeof (SPEC_FILE)
-		  + sizeof ("-specs=") + 4);
-  strcpy (spec, "-specs=");
-  x = strlen (spec);
-  strcat (spec, dir);
+  spec = XNEWVEC (char, strlen (dir) + sizeof (SPEC_FILE) + 4);
+  strcpy (spec, dir);
   strcat (spec, "/");
   strcat (spec, SPEC_FILE);
-  if (! stat (spec + x, &sb))
+  if (! stat (spec, &sb))
     return spec;
   free (spec);
   return NULL;
@@ -142,10 +137,11 @@  verify_class_name (const char *name)
 }
 
 void
-lang_specific_driver (int *in_argc, const char *const **in_argv,
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+		      unsigned int *in_decoded_options_count,
 		      int *in_added_libraries)
 {
-  int i, j;
+  unsigned int i, j;
 
   int saw_save_temps = 0;
 
@@ -174,12 +170,8 @@  lang_specific_driver (int *in_argc, cons
      libraries.  */
   int added = 2;
 
-  /* Used to track options that take arguments, so we don't go wrapping
-     those with -xc++/-xnone.  */
-  const char *quote = NULL;
-
   /* The new argument list will be contained in this.  */
-  const char **arglist;
+  struct cl_decoded_option *new_decoded_options;
 
   /* Nonzero if we saw a `-xfoo' language specification on the
      command line.  Used to avoid adding our own -xc++ if the user
@@ -203,16 +195,16 @@  lang_specific_driver (int *in_argc, cons
   int *args;
 
   /* The total number of arguments with the new stuff.  */
-  int argc;
+  unsigned int argc;
 
   /* The argument list.  */
-  const char *const *argv;
+  struct cl_decoded_option *decoded_options;
 
   /* The number of libraries added in.  */
   int added_libraries;
 
   /* The total number of arguments with the new stuff.  */
-  int num_args = 1;
+  unsigned int num_args = 1;
 
   /* Nonzero if linking is supposed to happen.  */
   int will_link = 1;
@@ -226,182 +218,182 @@  lang_specific_driver (int *in_argc, cons
   /* If linking, nonzero if the BC-ABI is in use.  */
   int link_for_bc_abi = 0;
 
-  argc = *in_argc;
-  argv = *in_argv;
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
   added_libraries = *in_added_libraries;
 
   args = XCNEWVEC (int, argc);
 
   for (i = 1; i < argc; i++)
     {
-      /* If the previous option took an argument, we swallow it here.  */
-      if (quote)
+      switch (decoded_options[i].opt_index)
 	{
-	  quote = NULL;
-	  args[i] |= PARAM_ARG;
-	  continue;
-	}
-
-      /* We don't do this anymore, since we don't get them with minus
-	 signs on them.  */
-      if (argv[i][0] == '\0' || argv[i][1] == '\0')
-	continue;
+	case OPT_nostdlib:
+	case OPT_nodefaultlibs:
+	  library = 0;
+	  break;
+
+	case OPT_fmain_:
+	  main_class_name = decoded_options[i].arg;
+	  added--;
+	  break;
+
+	case OPT_fhelp:
+	  want_spec_file = 0;
+	  break;
 
-      if (argv[i][0] == '-')
-	{
-	  if (library != 0 && (strcmp (argv[i], "-nostdlib") == 0
-			       || strcmp (argv[i], "-nodefaultlibs") == 0))
-	    {
-	      library = 0;
-	    }
-	  else if (strncmp (argv[i], "-fmain=", 7) == 0)
-	    {
-	      main_class_name = argv[i] + 7;
-	      added--;
-	    }
-	  else if (strcmp (argv[i], "-fhelp") == 0)
-	    want_spec_file = 0;
-	  else if (strcmp (argv[i], "-v") == 0)
-	    {
-	      if (argc == 2)
-		{
-		  /* If they only gave us `-v', don't try to link
-		     in libgcj.  */ 
-		  library = 0;
-		}
-	    }
-	  else if (strncmp (argv[i], "-x", 2) == 0)
-	    saw_speclang = 1;
-	  else if (strcmp (argv[i], "-C") == 0)
-	    {
-	      saw_C = 1;
-	      want_spec_file = 0;
-	      if (library != 0)
-		added -= 2;
-	      library = 0;
-	      will_link = 0;
-	    }
-	  else if (strncmp (argv[i], "-fcompile-resource=", 19) == 0)
+	case OPT_v:
+	  if (argc == 2)
 	    {
-	      saw_resource = 1;
-	      want_spec_file = 0;
-	      if (library != 0)
-		--added;
+	      /* If they only gave us `-v', don't try to link
+		 in libgcj.  */ 
 	      library = 0;
-	      will_link = 0;
-	    }
-	  else if (argv[i][1] == 'D')
-	    saw_D = 1;
-	  else if (argv[i][1] == 'g')
-	    saw_g = 1;
-	  else if (argv[i][1] == 'O')
-	    saw_O = 1;
-	  else if ((argv[i][2] == '\0'
-		    && strchr ("bBVDUoeTuIYmLiAI", argv[i][1]) != NULL)
-		   || strcmp (argv[i], "-Tdata") == 0
-		   || strcmp (argv[i], "-MT") == 0
-		   || strcmp (argv[i], "-MF") == 0)
-	    {
-	      if (strcmp (argv[i], "-o") == 0)
-		saw_o = 1;
-	      quote = argv[i];
-	    }
-	  else if (strcmp (argv[i], "-classpath") == 0
-		   || strcmp (argv[i], "-bootclasspath") == 0
-		   || strcmp (argv[i], "-CLASSPATH") == 0
-		   || strcmp (argv[i], "-encoding") == 0
-		   || strcmp (argv[i], "-extdirs") == 0)
-	    {
-	      quote = argv[i];
-	      added -= 1;
 	    }
-	  else if (library != 0 
-		   && ((argv[i][2] == '\0'
-			&& strchr ("cSEM", argv[i][1]) != NULL)
-		       || strcmp (argv[i], "-MM") == 0))
-	    {
-	      /* Don't specify libraries if we won't link, since that would
-		 cause a warning.  */
-	      library = 0;
-	      added -= 2;
+	  break;
 
-	      /* Remember this so we can confirm -fmain option.  */
-	      will_link = 0;
-	    }
-	  else if (strcmp (argv[i], "-d") == 0)
-	    {
-	      /* `-d' option is for javac compatibility.  */
-	      quote = argv[i];
-	      added -= 1;
-	    }
-	  else if (strcmp (argv[i], "-fsyntax-only") == 0
-		   || strcmp (argv[i], "--syntax-only") == 0)
-	    {
-	      library = 0;
-	      will_link = 0;
+	case OPT_x:
+	  saw_speclang = 1;
+	  break;
+
+	case OPT_C:
+	  saw_C = 1;
+	  want_spec_file = 0;
+	  if (library != 0)
+	    added -= 2;
+	  library = 0;
+	  will_link = 0;
+	  break;
+
+	case OPT_fcompile_resource_:
+	  saw_resource = 1;
+	  want_spec_file = 0;
+	  if (library != 0)
+	    --added;
+	  library = 0;
+	  will_link = 0;
+	  break;
+
+	case OPT_D:
+	  saw_D = 1;
+	  break;
+
+	case OPT_g:
+	case OPT_gcoff:
+	case OPT_gdwarf_:
+	case OPT_ggdb:
+	case OPT_gstabs:
+	case OPT_gstabs_:
+	case OPT_gvms:
+	case OPT_gxcoff:
+	case OPT_gxcoff_:
+	  saw_g = 1;
+	  break;
+
+	case OPT_O:
+	case OPT_Os:
+	case OPT_Ofast:
+	  saw_O = 1;
+	  break;
+
+	case OPT_o:
+	  saw_o = 1;
+	  break;
+
+	case OPT_classpath:
+	case OPT_bootclasspath:
+	case OPT_CLASSPATH:
+	case OPT_encoding:
+	case OPT_extdirs:
+	  added -= 1;
+	  break;
+
+	case OPT_c:
+	case OPT_S:
+	case OPT_E:
+	case OPT_M:
+	case OPT_MM:
+	  /* Don't specify libraries if we won't link, since that would
+	     cause a warning.  */
+	  library = 0;
+	  added -= 2;
+
+	  /* Remember this so we can confirm -fmain option.  */
+	  will_link = 0;
+	  break;
+
+	case OPT_fsyntax_only:
+	  library = 0;
+	  will_link = 0;
+	  continue;
+
+	case OPT_save_temps:
+	  saw_save_temps = 1;
+	  break;
+
+	case OPT_static_libgcc:
+	case OPT_static:
+	  shared_libgcc = 0;
+	  break;
+
+	case OPT_findirect_dispatch:
+	  link_for_bc_abi = 1;
+	  break;
+
+	case OPT_SPECIAL_input_file:
+	  {
+	    const char *arg = decoded_options[i].arg;
+	    int len;
+
+	    /* We don't do this anymore, since we don't get them with minus
+	       signs on them.  */
+	    if (arg[0] == '\0' || arg[1] == '\0')
 	      continue;
-	    }
-          else if (strcmp (argv[i], "-save-temps") == 0)
-	    saw_save_temps = 1;
-          else if (strcmp (argv[i], "-static-libgcc") == 0
-                   || strcmp (argv[i], "-static") == 0)
-	    shared_libgcc = 0;
-	  else if (strcmp (argv[i], "-findirect-dispatch") == 0
-		   || strcmp (argv[i], "--indirect-dispatch") == 0)
-	    {
-	      link_for_bc_abi = 1;
-	    }
-	  else
-	    /* Pass other options through.  */
-	    continue;
-	}
-      else
-	{
-	  int len; 
 
-	  if (saw_speclang)
-	    {
-	      saw_speclang = 0;
-	      continue;
-	    }
+	    if (saw_speclang)
+	      {
+		saw_speclang = 0;
+		continue;
+	      }
+
+	    if (saw_resource)
+	      {
+		args[i] |= RESOURCE_FILE_ARG;
+		added += 2;  /* for -xjava and -xnone */
+	      }
+
+	    if (arg[0] == '@')
+	      {
+		args[i] |= INDIRECT_FILE_ARG;
+		indirect_files_count++;
+		added += 2;  /* for -xjava and -xnone */
+	      }
+
+	    len = strlen (arg);
+	    if (len > 5 && strcmp (arg + len - 5, ".java") == 0)
+	      {
+		args[i] |= JAVA_FILE_ARG;
+		java_files_count++;
+	      }
+	    if (len > 6 && strcmp (arg + len - 6, ".class") == 0)
+	      {
+		args[i] |= CLASS_FILE_ARG;
+		class_files_count++;
+	      }
+	    if (len > 4
+		&& (strcmp (arg + len - 4, ".zip") == 0
+		    || strcmp (arg + len - 4, ".jar") == 0))
+	      {
+		args[i] |= ZIP_FILE_ARG;
+		zip_files_count++;
+	      }
+	  }
 
-	  if (saw_resource)
-	    {
-	      args[i] |= RESOURCE_FILE_ARG;
-	      added += 2;  /* for -xjava and -xnone */
-	    }
-
-	  if (argv[i][0] == '@')
-	    {
-	      args[i] |= INDIRECT_FILE_ARG;
-	      indirect_files_count++;
-	      added += 2;  /* for -xjava and -xnone */
-	    }
-
-	  len = strlen (argv[i]);
-	  if (len > 5 && strcmp (argv[i] + len - 5, ".java") == 0)
-	    {
-	      args[i] |= JAVA_FILE_ARG;
-	      java_files_count++;
-	    }
-	  if (len > 6 && strcmp (argv[i] + len - 6, ".class") == 0)
-	    {
-	      args[i] |= CLASS_FILE_ARG;
-	      class_files_count++;
-	    }
-	  if (len > 4
-	      && (strcmp (argv[i] + len - 4, ".zip") == 0
-		  || strcmp (argv[i] + len - 4, ".jar") == 0))
-	    {
-	      args[i] |= ZIP_FILE_ARG;
-	      zip_files_count++;
-	    }
+	default:
+	  /* Pass other options through.  */
+	  continue;
 	}
     }
 
-  if (quote)
-    fatal_error ("argument to %qs missing", quote);
-
   if (saw_D && ! main_class_name)
     fatal_error ("can't specify %<-D%> without %<--main%>");
 
@@ -475,112 +467,83 @@  lang_specific_driver (int *in_argc, cons
 
   num_args += link_for_bc_abi;
 
-  arglist = XNEWVEC (const char *, num_args + 1);
+  new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
   j = 0;
 
-  arglist[j++] = argv[0];
+  new_decoded_options[j++] = decoded_options[0];
 
   if (combine_inputs || indirect_files_count > 0)
-    arglist[j++] = "-ffilelist-file";
+    generate_option (OPT_ffilelist_file, NULL, 1, CL_DRIVER,
+		     &new_decoded_options[j++]);
 
   if (combine_inputs)
     {
-      arglist[j++] = "-xjava";
-      arglist[j++] = filelist_filename;
-      arglist[j++] = "-xnone";
+      generate_option (OPT_x, "java", 1, CL_DRIVER,
+		       &new_decoded_options[j++]);
+      generate_option_input_file (filelist_filename,
+				  &new_decoded_options[j++]);
+      generate_option (OPT_x, "none", 1, CL_DRIVER,
+		       &new_decoded_options[j++]);
     }
 
   if (java_files_count > 0)
-    arglist[j++] = "-fsaw-java-file";
+    generate_option (OPT_fsaw_java_file, NULL, 1, CL_DRIVER,
+		     &new_decoded_options[j++]);
 
   jcf_path_init ();
   for (i = 1; i < argc; i++, j++)
     {
-      arglist[j] = argv[i];
+      new_decoded_options[j] = decoded_options[i];
 
-      if ((args[i] & PARAM_ARG))
+      if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
 	continue;
 
       if ((args[i] & RESOURCE_FILE_ARG) != 0)
 	{
-	  arglist[j++] = "-xjava";
-	  arglist[j++] = argv[i];
-	  arglist[j] = "-xnone";
+	  generate_option (OPT_x, "java", 1, CL_DRIVER,
+			   &new_decoded_options[j++]);
+	  new_decoded_options[j++] = decoded_options[i];
+	  generate_option (OPT_x, "none", 1, CL_DRIVER,
+			   &new_decoded_options[j]);
 	}
 
-      if (argv[i][0] == '-' && argv[i][1] == 'I')
-	{
-	  const char *arg;
-	  if (argv[i][2] == '\0')
-	    {
-	      gcc_assert (i + 1 < argc && (args[i + 1] & PARAM_ARG) != 0);
-	      arg = argv[i + 1];
-	      /* Drop the argument.  */
-	      ++i;
-	    }
-	  else
-	    arg = &argv[i][2];
-	  jcf_path_include_arg (arg);
-	  --j;
-	  continue;
-	}
-      if (! strcmp (argv[i], "-classpath")
-	  || ! strcmp (argv[i], "-CLASSPATH"))
-	{
-	  jcf_path_classpath_arg (argv[i + 1]);
-	  ++i;
-	  --j;
-	  continue;
-	}
-      if (! strcmp (argv[i], "-bootclasspath"))
-	{
-	  jcf_path_bootclasspath_arg (argv[i + 1]);
-	  ++i;
-	  --j;
-	  continue;
-	}
-      if (! strncmp (argv[i], "-fCLASSPATH=", 12)
-	  || ! strncmp (argv[i], "-fclasspath=", 12))
+      switch (decoded_options[i].opt_index)
 	{
-	  const char *p = strchr (argv[i], '=');
-	  jcf_path_classpath_arg (p + 1);
+	case OPT_I:
+	  jcf_path_include_arg (decoded_options[i].arg);
 	  --j;
 	  continue;
-	}
-      if (! strncmp (argv[i], "-fbootclasspath=", 16))
-	{
-	  const char *p = strchr (argv[i], '=');
-	  jcf_path_bootclasspath_arg (p + 1);
+
+	case OPT_classpath:
+	case OPT_CLASSPATH:
+	case OPT_fCLASSPATH_:
+	case OPT_fclasspath_:
+	  jcf_path_classpath_arg (decoded_options[i].arg);
 	  --j;
 	  continue;
-	}
-      if (! strcmp (argv[i], "-extdirs"))
-	{
-	  jcf_path_extdirs_arg (argv[i + 1]);
-	  ++i;
+
+	case OPT_bootclasspath:
+	case OPT_fbootclasspath_:
+	  jcf_path_bootclasspath_arg (decoded_options[i].arg);
 	  --j;
 	  continue;
-	}
 
-      if (strcmp (argv[i], "-encoding") == 0)
-	{
-	  arglist[j] = concat ("-f", argv[i]+1, "=", argv[i+1], NULL);
-	  i++;
+	case OPT_extdirs:
+	  jcf_path_extdirs_arg (decoded_options[i].arg);
+	  --j;
 	  continue;
-	}
 
-      if (strcmp (argv[i], "-d") == 0)
-	{
-	  arglist[j] = concat ("-foutput-class-dir=", argv[i + 1], NULL);
-	  ++i;
+	case OPT_encoding:
+	  generate_option (OPT_fencoding_, decoded_options[i].arg, 1,
+			   CL_DRIVER, &new_decoded_options[j]);
 	  continue;
-	}
 
-      if (spec_file == NULL && strncmp (argv[i], "-L", 2) == 0)
-	spec_file = find_spec_file (argv[i] + 2);
+	case OPT_L:
+	  if (spec_file == NULL)
+	    spec_file = find_spec_file (decoded_options[i].arg);
+	  break;
 
-      if (strncmp (argv[i], "-fmain=", 7) == 0)
-	{
+	case OPT_fmain_:
 	  if (! will_link)
 	    fatal_error ("cannot specify %<main%> class when not linking");
 	  --j;
@@ -589,9 +552,13 @@  lang_specific_driver (int *in_argc, cons
 
       if ((args[i] & INDIRECT_FILE_ARG) != 0)
 	{
-	  arglist[j++] = "-xjava";
-	  arglist[j++] = argv[i]+1;  /* Drop '@'. */
-	  arglist[j] = "-xnone";
+	  generate_option (OPT_x, "java", 1, CL_DRIVER,
+			   &new_decoded_options[j++]);
+	  /* Drop '@'.  */
+	  generate_option_input_file (decoded_options[i].arg + 1,
+				      &new_decoded_options[j++]);
+	  generate_option (OPT_x, "none", 1, CL_DRIVER,
+			   &new_decoded_options[j]);
 	}
 
       if ((args[i] & (CLASS_FILE_ARG|ZIP_FILE_ARG)) && saw_C)
@@ -603,7 +570,7 @@  lang_specific_driver (int *in_argc, cons
       if (combine_inputs
 	  && (args[i] & (CLASS_FILE_ARG|JAVA_FILE_ARG|ZIP_FILE_ARG)) != 0)
 	{
-	  fputs (argv[i], filelist_file);
+	  fputs (decoded_options[i].arg, filelist_file);
 	  fputc ('\n', filelist_file);
 	  --j;
 	  continue;
@@ -613,7 +580,8 @@  lang_specific_driver (int *in_argc, cons
   /* Handle classpath setting.  We specify the bootclasspath since
      that requires the fewest changes to our existing code...  */
   jcf_path_seal (0);
-  arglist[j++] = jcf_path_compute ("-fbootclasspath=");
+  generate_option (OPT_fbootclasspath_, jcf_path_compute (""), 1,
+		   CL_DRIVER, &new_decoded_options[j++]);
 
   if (combine_inputs)
     {
@@ -623,33 +591,36 @@  lang_specific_driver (int *in_argc, cons
 
   /* If we saw no -O or -g option, default to -g1, for javac compatibility. */
   if (saw_g + saw_O == 0)
-    arglist[j++] = "-g1";
+    generate_option (OPT_g, "1", 1, CL_DRIVER, &new_decoded_options[j++]);
 
   /* Read the specs file corresponding to libgcj.
      If we didn't find the spec file on the -L path, then we hope it
      is somewhere in the standard install areas.  */
   if (want_spec_file)
-    arglist[j++] = spec_file == NULL ? "-specs=libgcj.spec" : spec_file;
+    generate_option (OPT_specs_, spec_file == NULL ? "libgcj.spec" : spec_file,
+		     1, CL_DRIVER, &new_decoded_options[j++]);
 
   if (saw_C)
     {
-      arglist[j++] = "-fsyntax-only";
-      arglist[j++] = "-femit-class-files";
-      arglist[j++] = "-S";
-      arglist[j++] = "-o";
-      arglist[j++] = "NONE";
+      generate_option (OPT_fsyntax_only, NULL, 1, CL_DRIVER,
+		       &new_decoded_options[j++]);
+      generate_option (OPT_femit_class_files, NULL, 1, CL_DRIVER,
+		       &new_decoded_options[j++]);
+      generate_option (OPT_S, NULL, 1, CL_DRIVER, &new_decoded_options[j++]);
+      generate_option (OPT_o, "NONE", 1, CL_DRIVER,
+		       &new_decoded_options[j++]);
     }
   
   if (shared_libgcc)
-    arglist[j++] = "-shared-libgcc";
+    generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
+		     &new_decoded_options[j++]);
 
   if (link_for_bc_abi)
-    arglist[j++] = "-s-bc-abi";
-
-  arglist[j] = NULL;
+    generate_option (OPT_s_bc_abi, NULL, 1, CL_DRIVER,
+		     &new_decoded_options[j++]);
 
-  *in_argc = j;
-  *in_argv = arglist;
+  *in_decoded_options_count = j;
+  *in_decoded_options = new_decoded_options;
   *in_added_libraries = added_libraries;
 }
 
Index: gcc/java/lang.opt
===================================================================
--- gcc/java/lang.opt	(revision 163280)
+++ gcc/java/lang.opt	(working copy)
@@ -1,5 +1,5 @@ 
 ; Options for the Java front end.
-; Copyright (C) 2003, 2005, 2007, 2009 Free Software Foundation, Inc.
+; Copyright (C) 2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
 ;
 ; This file is part of GCC.
 ;
@@ -24,6 +24,17 @@ 
 Language
 Java
 
+C
+Driver
+; Java driver option in fact distinct from C-family option with the same name.
+
+CLASSPATH
+Driver Separate
+
+D
+Driver Joined Separate
+; Java driver option similar to C-family option.
+
 I
 Java Joined Separate
 ; Documented for C
@@ -76,6 +87,18 @@  Wredundant-modifiers
 Java Var(flag_redundant)
 Warn if modifiers are specified when not necessary
 
+bootclasspath
+Driver Separate
+
+classpath
+Driver Separate
+
+encoding
+Driver Separate
+
+extdirs
+Driver Separate
+
 fCLASSPATH=
 Java JoinedOrMissing RejectNegative
 --CLASSPATH	Deprecated; use --classpath instead
@@ -136,6 +159,9 @@  fextdirs=
 Java Joined RejectNegative
 --extdirs=<path>	Set the extension directory path
 
+fmain=
+Driver JoinedOrMissing RejectNegative
+
 fsource-filename=
 Java Joined Undocumented 
 
@@ -208,6 +234,9 @@  ftarget=
 Java Joined
 Set the target VM version
 
+s-bc-abi
+Driver
+
 version
 Java RejectDriver
 
Index: gcc/cppspec.c
===================================================================
--- gcc/cppspec.c	(revision 163280)
+++ gcc/cppspec.c	(working copy)
@@ -22,6 +22,7 @@  along with GCC; see the file COPYING3.  
 #include "coretypes.h"
 #include "tm.h"
 #include "gcc.h"
+#include "opts.h"
 
 /* The `cpp' executable installed in $(bindir) and $(cpp_install_dir)
    is a customized version of the gcc driver.  It forces -E; -S and -c
@@ -41,13 +42,14 @@  static const char *const known_suffixes[
   NULL
 };
 
-/* Filter argc and argv before processing by the gcc driver proper.  */
+/* Filter the command line before processing by the gcc driver proper.  */
 void
-lang_specific_driver (int *in_argc, const char *const **in_argv,
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+		      unsigned int *in_decoded_options_count,
 		      int *in_added_libraries ATTRIBUTE_UNUSED)
 {
-  int argc = *in_argc;
-  const char *const *argv = *in_argv;
+  struct cl_decoded_option *decoded_options = *in_decoded_options;
+  unsigned int argc = *in_decoded_options_count;
 
   /* Do we need to read stdin? */
   int read_stdin = 1;
@@ -60,16 +62,16 @@  lang_specific_driver (int *in_argc, cons
 
   /* Positions to insert -xc, -xassembler-with-cpp, and -o, if necessary.
      0 means unnecessary.  */
-  int lang_c_here = 0;
-  int lang_S_here = 0;
-  int o_here = 0;
+  unsigned int lang_c_here = 0;
+  unsigned int lang_S_here = 0;
+  unsigned int o_here = 0;
 
   /* Do we need to fix up an input file with an unrecognized suffix? */
   int need_fixups = 1;
 
-  int i, j, quote = 0;
-  const char **new_argv;
-  int new_argc;
+  unsigned int i, j;
+  struct cl_decoded_option *new_decoded_options;
+  unsigned int new_argc;
   extern int is_cpp_driver;
 
   is_cpp_driver = 1;
@@ -79,117 +81,111 @@  lang_specific_driver (int *in_argc, cons
      the output file.  If we see a third input file, barf.  */
   for (i = 1; i < argc; i++)
     {
-      if (quote == 1)
+      switch (decoded_options[i].opt_index)
 	{
-	  quote = 0;
-	  continue;
-	}
+	case OPT_E:
+	  need_E = 0;
+	  break;
+
+	case OPT_S:
+	case OPT_c:
+	  fatal_error ("%qs is not a valid option to the preprocessor",
+		       decoded_options[i].orig_option_with_args_text);
+	  return;
+
+	case OPT_x:
+	  need_fixups = 0;
+	  break;
+
+	case OPT_SPECIAL_input_file:
+	  {
+	    const char *file = decoded_options[i].arg;
 
-      if (argv[i][0] == '-')
-	{
-	  if (argv[i][1] == '\0')
-	    read_stdin = 0;
-	  else if (argv[i][2] == '\0')
-	    {
-	      if (argv[i][1] == 'E')
-		need_E = 0;
-	      else if (argv[i][1] == 'S' || argv[i][1] == 'c')
-		{
-		  fatal_error ("%qs is not a valid option to the "
-			       "preprocessor", argv[i]);
-		  return;
-		}
-	      else if (argv[i][1] == 'x')
-		{
-		  need_fixups = 0;
-		  quote = 1;
-		}
-	      else if (SWITCH_TAKES_ARG (argv[i][1]))
-		quote = 1;
-	    }
-	  else if (argv[i][1] == 'x')
-	    need_fixups = 0;
-	  else if (WORD_SWITCH_TAKES_ARG (&argv[i][1]))
-	    quote = 1;
-	}
-      else /* not an option */
-	{
-	  seen_input++;
-	  if (seen_input == 3)
-	    {
-	      fatal_error ("too many input files");
-	      return;
-	    }
-	  else if (seen_input == 2)
-	    {
-	      o_here = i;
-	    }
-	  else
-	    {
+	    if (strcmp (file, "-") == 0)
 	      read_stdin = 0;
-	      if (need_fixups)
-		{
-		  int l = strlen (argv[i]);
-		  int known = 0;
-		  const char *const *suff;
-
-		  for (suff = known_suffixes; *suff; suff++)
-		    if (!strcmp (*suff, &argv[i][l - strlen(*suff)]))
+	    else
+	      {
+		seen_input++;
+		if (seen_input == 3)
+		  {
+		    fatal_error ("too many input files");
+		    return;
+		  }
+		else if (seen_input == 2)
+		  {
+		    o_here = i;
+		  }
+		else
+		  {
+		    read_stdin = 0;
+		    if (need_fixups)
 		      {
-			known = 1;
-			break;
+			int l = strlen (file);
+			int known = 0;
+			const char *const *suff;
+
+			for (suff = known_suffixes; *suff; suff++)
+			  if (!strcmp (*suff, &file[l - strlen(*suff)]))
+			    {
+			      known = 1;
+			      break;
+			    }
+
+			if (! known)
+			  {
+			    /* .s files are a special case; we have to
+			       treat them like .S files so
+			       -D__ASSEMBLER__ will be in effect.  */
+			    if (!strcmp (".s", &file[l - 2]))
+			      lang_S_here = i;
+			    else
+			      lang_c_here = i;
+			  }
 		      }
-
-		  if (! known)
-		    {
-		      /* .s files are a special case; we have to treat
-			 them like .S files so -D__ASSEMBLER__ will be
-			 in effect.  */
-		      if (!strcmp (".s", &argv[i][l - 2]))
-			lang_S_here = i;
-		      else
-			lang_c_here = i;
-		    }
-		}
-	    }
+		  }
+	      }
+	  }
+	  break;
 	}
     }
 
   /* If we don't need to edit the command line, we can bail early.  */
 
-  new_argc = argc + need_E + read_stdin
-    + !!o_here + !!lang_c_here + !!lang_S_here;
+  new_argc = argc + need_E + read_stdin + !!lang_c_here + !!lang_S_here;
 
-  if (new_argc == argc)
+  if (new_argc == argc && !o_here)
     return;
 
-  /* One more slot for a terminating null.  */
-  new_argv = XNEWVEC (const char *, new_argc + 1);
+  new_decoded_options = XNEWVEC (struct cl_decoded_option, new_argc);
 
-  new_argv[0] = argv[0];
+  new_decoded_options[0] = new_decoded_options[0];
   j = 1;
 
   if (need_E)
-    new_argv[j++] = "-E";
+    generate_option (OPT_E, NULL, 1, CL_DRIVER, &new_decoded_options[j++]);
 
   for (i = 1; i < argc; i++, j++)
     {
       if (i == lang_c_here)
-	new_argv[j++] = "-xc";
+	generate_option (OPT_x, "c", 1, CL_DRIVER, &new_decoded_options[j++]);
       else if (i == lang_S_here)
-	new_argv[j++] = "-xassembler-with-cpp";
+	generate_option (OPT_x, "assembler-with-cpp", 1, CL_DRIVER,
+			 &new_decoded_options[j++]);
       else if (i == o_here)
-	new_argv[j++] = "-o";
+	{
+	  generate_option (OPT_o, decoded_options[i].arg, 1, CL_DRIVER,
+			   &new_decoded_options[j]);
+	  continue;
+	}
 
-      new_argv[j] = argv[i];
+      new_decoded_options[j] = decoded_options[i];
     }
 
   if (read_stdin)
-    new_argv[j++] = "-";
+    generate_option_input_file ("-", &new_decoded_options[j++]);
 
-  new_argv[j] = NULL;
-  *in_argc = new_argc;
-  *in_argv = new_argv;
+  *in_decoded_options_count = new_argc;
+  *in_decoded_options = new_decoded_options;
 }
 
 /* Called before linking.  Returns 0 on success and -1 on failure.  */
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 163280)
+++ gcc/gcc.c	(working copy)
@@ -1367,6 +1367,16 @@  translate_options (int *argcp, const cha
 	  if (nskip + i > argc)
 	    nskip = argc - i;
 
+	  /* Convert -d with a separate argument to
+	     -foutput-class-dir= for Java.  */
+	  if (c == 'd' && p[1] == 0 && argv[i + 1] != NULL)
+	    {
+	      newv[newindex++] = concat ("-foutput-class-dir=", argv[i + 1],
+					 NULL);
+	      nskip = 0;
+	      i += 2;
+	    }
+
 	  while (nskip > 0)
 	    {
 	      newv[newindex++] = argv[i++];
@@ -3847,12 +3857,6 @@  driver_handle_option (const struct cl_de
       do_save = false;
       break;
 
-    case OPT_S:
-    case OPT_c:
-    case OPT_E:
-      /* have_c already set in a prescan above.  */
-      break;
-
     case OPT_o:
       have_o = 1;
 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
@@ -3876,7 +3880,10 @@  driver_handle_option (const struct cl_de
       break;
 
     default:
-      gcc_unreachable ();
+      /* Various driver options need no special processing at this
+	 point, having been handled in a prescan above or being
+	 handled by specs.  */
+      break;
     }
 
   if (do_save)
@@ -3981,10 +3988,11 @@  process_command (int argc, const char **
      is relocated. The toolchain was either relocated using GCC_EXEC_PREFIX
      or an automatically created GCC_EXEC_PREFIX from argv[0].  */
 
+  decode_cmdline_options_to_array (argc, argv, CL_DRIVER,
+				   &decoded_options, &decoded_options_count);
+
   /* Do language-specific adjustment/addition of flags.  */
-  lang_specific_driver (&argc,
-			CONST_CAST2 (const char *const **, const char ***,
-				     &argv),
+  lang_specific_driver (&decoded_options, &decoded_options_count,
 			&added_libraries);
 
   if (gcc_exec_prefix)
@@ -4116,9 +4124,6 @@  process_command (int argc, const char **
 
   last_language_n_infiles = -1;
 
-  decode_cmdline_options_to_array (argc, argv, CL_DRIVER,
-				   &decoded_options, &decoded_options_count);
-
   handlers.unknown_option_callback = driver_unknown_option_callback;
   handlers.wrong_lang_callback = driver_wrong_lang_callback;
   handlers.post_handling_callback = driver_post_handling_callback;
Index: gcc/gcc.h
===================================================================
--- gcc/gcc.h	(revision 163280)
+++ gcc/gcc.h	(working copy)
@@ -41,7 +41,8 @@  extern void set_input (const char *);
 /* Spec files linked with gcc.c must provide definitions for these.  */
 
 /* Called before processing to change/add/remove arguments.  */
-extern void lang_specific_driver (int *, const char *const **, int *);
+extern void lang_specific_driver (struct cl_decoded_option **,
+				  unsigned int *, int *);
 
 /* Called before linking.  Returns 0 on success and -1 on failure.  */
 extern int lang_specific_pre_link (void);
Index: gcc/cp/Make-lang.in
===================================================================
--- gcc/cp/Make-lang.in	(revision 163280)
+++ gcc/cp/Make-lang.in	(working copy)
@@ -53,7 +53,8 @@  c++: cc1plus$(exeext)
 # Tell GNU make to ignore these if they exist.
 .PHONY: c++
 
-g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) $(CONFIG_H)
+g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
+    $(CONFIG_H) opts.h
 	(SHLIB_LINK='$(SHLIB_LINK)'; \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
 		$(INCLUDES) $(srcdir)/cp/g++spec.c)
Index: gcc/cp/g++spec.c
===================================================================
--- gcc/cp/g++spec.c	(revision 163280)
+++ gcc/cp/g++spec.c	(working copy)
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  
 #include "coretypes.h"
 #include "tm.h"
 #include "gcc.h"
+#include "opts.h"
 
 /* This bit is set if we saw a `-xfoo' language specification.  */
 #define LANGSPEC	(1<<1)
@@ -34,14 +35,14 @@  along with GCC; see the file COPYING3.  
 #define SKIPOPT		(1<<4)
 
 #ifndef MATH_LIBRARY
-#define MATH_LIBRARY "-lm"
+#define MATH_LIBRARY "m"
 #endif
 #ifndef MATH_LIBRARY_PROFILE
 #define MATH_LIBRARY_PROFILE MATH_LIBRARY
 #endif
 
 #ifndef LIBSTDCXX
-#define LIBSTDCXX "-lstdc++"
+#define LIBSTDCXX "stdc++"
 #endif
 #ifndef LIBSTDCXX_PROFILE
 #define LIBSTDCXX_PROFILE LIBSTDCXX
@@ -51,10 +52,11 @@  along with GCC; see the file COPYING3.  
 #endif
 
 void
-lang_specific_driver (int *in_argc, const char *const **in_argv,
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+		      unsigned int *in_decoded_options_count,
 		      int *in_added_libraries)
 {
-  int i, j;
+  unsigned int i, j;
 
   /* If nonzero, the user gave us the `-p' or `-pg' flag.  */
   int saw_profile_flag = 0;
@@ -71,12 +73,8 @@  lang_specific_driver (int *in_argc, cons
      -xc++/-xnone.  */
   int added = 0;
 
-  /* Used to track options that take arguments, so we don't go wrapping
-     those with -xc++/-xnone.  */
-  const char *quote = NULL;
-
   /* The new argument list will be contained in this.  */
-  const char **arglist;
+  struct cl_decoded_option *new_decoded_options;
 
   /* Nonzero if we saw a `-xfoo' language specification on the
      command line.  Used to avoid adding our own -xc++ if the user
@@ -84,10 +82,10 @@  lang_specific_driver (int *in_argc, cons
   int saw_speclang = 0;
 
   /* "-lm" or "-lmath" if it appears on the command line.  */
-  const char *saw_math = 0;
+  const struct cl_decoded_option *saw_math = NULL;
 
   /* "-lc" if it appears on the command line.  */
-  const char *saw_libc = 0;
+  const struct cl_decoded_option *saw_libc = NULL;
 
   /* An array used to flag each argument that needs a bit set for
      LANGSPEC, MATHLIB, or WITHLIBC.  */
@@ -103,220 +101,206 @@  lang_specific_driver (int *in_argc, cons
   int shared_libgcc = 1;
 
   /* The total number of arguments with the new stuff.  */
-  int argc;
+  unsigned int argc;
 
   /* The argument list.  */
-  const char *const *argv;
+  struct cl_decoded_option *decoded_options;
 
   /* The number of libraries added in.  */
   int added_libraries;
 
   /* The total number of arguments with the new stuff.  */
-  int num_args = 1;
+  unsigned int num_args = 1;
 
-  argc = *in_argc;
-  argv = *in_argv;
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
   added_libraries = *in_added_libraries;
 
   args = XCNEWVEC (int, argc);
 
   for (i = 1; i < argc; i++)
     {
-      /* If the previous option took an argument, we swallow it here.  */
-      if (quote)
-	{
-	  quote = NULL;
-	  continue;
-	}
+      const char *arg = decoded_options[i].arg;
+      if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
+	continue; /* Avoid examining arguments of options missing them.  */
 
-      /* We don't do this anymore, since we don't get them with minus
-	 signs on them.  */
-      if (argv[i][0] == '\0' || argv[i][1] == '\0')
-	continue;
-
-      if (argv[i][0] == '-')
+      switch (decoded_options[i].opt_index)
 	{
-	  if (strcmp (argv[i], "-nostdlib") == 0
-	      || strcmp (argv[i], "-nodefaultlibs") == 0)
-	    {
-	      library = -1;
-	    }
-	  else if (strcmp (argv[i], MATH_LIBRARY) == 0)
+	case OPT_nostdlib:
+	case OPT_nodefaultlibs:
+	  library = -1;
+	  break;
+
+	case OPT_l:
+	  if (strcmp (arg, MATH_LIBRARY) == 0)
 	    {
 	      args[i] |= MATHLIB;
 	      need_math = 0;
 	    }
-	  else if (strcmp (argv[i], "-lc") == 0)
+	  else if (strcmp (arg, "c") == 0)
 	    args[i] |= WITHLIBC;
-	  else if (strcmp (argv[i], "-pg") == 0 || strcmp (argv[i], "-p") == 0)
-	    saw_profile_flag++;
-	  else if (strncmp (argv[i], "-x", 2) == 0)
-	    {
-	      const char * arg;
-	      if (argv[i][2] != '\0')
-		arg = argv[i]+2;
-	      else if ((argv[i+1]) != NULL)
-		/* We need to swallow arg on next loop.  */
-		quote = arg = argv[i+1];
-  	      else  /* Error condition, message will be printed later.  */
-		arg = "";
-	      if (library == 0
-		  && (strcmp (arg, "c++") == 0
-		      || strcmp (arg, "c++-cpp-output") == 0
-		      || strcmp (arg, "objective-c++") == 0
-		      || strcmp (arg, "objective-c++-cpp-output") == 0))
-		library = 1;
+	  else
+	    /* Unrecognized libraries (e.g. -lfoo) may require libstdc++.  */
+	    library = (library == 0) ? 1 : library;
+	  break;
+
+	case OPT_pg:
+	case OPT_p:
+	  saw_profile_flag++;
+	  break;
+
+	case OPT_x:
+	  if (library == 0
+	      && (strcmp (arg, "c++") == 0
+		  || strcmp (arg, "c++-cpp-output") == 0
+		  || strcmp (arg, "objective-c++") == 0
+		  || strcmp (arg, "objective-c++-cpp-output") == 0))
+	    library = 1;
 		
-	      saw_speclang = 1;
-	    }
-	  else if (strcmp (argv[i], "-ObjC++") == 0)
-	    {
-	      if (library == 0)
-		library = 1;
-	      saw_speclang = 1;
-	    }
+	  saw_speclang = 1;
+	  break;
+
+	case OPT_Xlinker:
+	case OPT_Wl_:
 	  /* Arguments that go directly to the linker might be .o files,
 	     or something, and so might cause libstdc++ to be needed.  */
-	  else if (strcmp (argv[i], "-Xlinker") == 0)
-	    {
-	      quote = argv[i];
-	      if (library == 0)
-		library = 1;
-	    }
-	  else if (strncmp (argv[i], "-Wl,", 4) == 0)
-	    library = (library == 0) ? 1 : library;
-	  /* Unrecognized libraries (e.g. -lfoo) may require libstdc++.  */
-	  else if (strncmp (argv[i], "-l", 2) == 0)
-	    library = (library == 0) ? 1 : library;
-	  else if (((argv[i][2] == '\0'
-		     && strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
-		    || strcmp (argv[i], "-Tdata") == 0))
-	    quote = argv[i];
-	  else if ((argv[i][2] == '\0'
-		    && strchr ("cSEM", argv[i][1]) != NULL)
-		   || strcmp (argv[i], "-MM") == 0
-		   || strcmp (argv[i], "-fsyntax-only") == 0)
-	    {
-	      /* Don't specify libraries if we won't link, since that would
-		 cause a warning.  */
-	      library = -1;
-	    }
-	  else if (strcmp (argv[i], "-static") == 0)
-	    static_link = 1;
-	  else if (strcmp (argv[i], "-static-libgcc") == 0)
-	    shared_libgcc = 0;
-	  else if (strcmp (argv[i], "-static-libstdc++") == 0)
-	    {
-	      library = library >= 0 ? 2 : library;
-	      args[i] |= SKIPOPT;
-	    }
-	  else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv[i][1]))
-	    i++;
-	  else
-	    /* Pass other options through.  */
-	    continue;
-	}
-      else
-	{
-	  int len;
+	  if (library == 0)
+	    library = 1;
+	  break;
 
-	  if (saw_speclang)
-	    {
-	      saw_speclang = 0;
+	case OPT_c:
+	case OPT_S:
+	case OPT_E:
+	case OPT_M:
+	case OPT_MM:
+	case OPT_fsyntax_only:
+	  /* Don't specify libraries if we won't link, since that would
+	     cause a warning.  */
+	  library = -1;
+	  break;
+
+	case OPT_static:
+	  static_link = 1;
+	  break;
+
+	case OPT_static_libgcc:
+	  shared_libgcc = 0;
+	  break;
+
+	case OPT_static_libstdc__:
+	  library = library >= 0 ? 2 : library;
+	  args[i] |= SKIPOPT;
+	  break;
+
+	case OPT_SPECIAL_input_file:
+	  {
+	    int len;
+
+	    /* We don't do this anymore, since we don't get them with minus
+	       signs on them.  */
+	    if (arg[0] == '\0' || arg[1] == '\0')
 	      continue;
-	    }
 
-	  /* If the filename ends in .[chi], put options around it.
-	     But not if a specified -x option is currently active.  */
-	  len = strlen (argv[i]);
-	  if (len > 2
-	      && (argv[i][len - 1] == 'c'
-		  || argv[i][len - 1] == 'i'
-		  || argv[i][len - 1] == 'h')
-	      && argv[i][len - 2] == '.')
-	    {
-	      args[i] |= LANGSPEC;
-	      added += 2;
-	    }
-
-	  /* If we don't know that this is a header file, we might
-	     need to be linking in the libraries.  */
-	  if (library == 0)
-	    {
-	      if ((len <= 2 || strcmp (argv[i] + (len - 2), ".H") != 0)
-		  && (len <= 2 || strcmp (argv[i] + (len - 2), ".h") != 0)
-		  && (len <= 4 || strcmp (argv[i] + (len - 4), ".hpp") != 0)
-		  && (len <= 3 || strcmp (argv[i] + (len - 3), ".hp") != 0)
-		  && (len <= 4 || strcmp (argv[i] + (len - 4), ".hxx") != 0)
-		  && (len <= 4 || strcmp (argv[i] + (len - 4), ".h++") != 0)
-		  && (len <= 4 || strcmp (argv[i] + (len - 4), ".HPP") != 0)
-		  && (len <= 4 || strcmp (argv[i] + (len - 4), ".tcc") != 0)
-		  && (len <= 3 || strcmp (argv[i] + (len - 3), ".hh") != 0))
-		library = 1;
-	    }
+	    if (saw_speclang)
+	      {
+		saw_speclang = 0;
+		continue;
+	      }
+
+	    /* If the filename ends in .[chi], put options around it.
+	       But not if a specified -x option is currently active.  */
+	    len = strlen (arg);
+	    if (len > 2
+		&& (arg[len - 1] == 'c'
+		    || arg[len - 1] == 'i'
+		    || arg[len - 1] == 'h')
+		&& arg[len - 2] == '.')
+	      {
+		args[i] |= LANGSPEC;
+		added += 2;
+	      }
+
+	    /* If we don't know that this is a header file, we might
+	       need to be linking in the libraries.  */
+	    if (library == 0)
+	      {
+		if ((len <= 2 || strcmp (arg + (len - 2), ".H") != 0)
+		    && (len <= 2 || strcmp (arg + (len - 2), ".h") != 0)
+		    && (len <= 4 || strcmp (arg + (len - 4), ".hpp") != 0)
+		    && (len <= 3 || strcmp (arg + (len - 3), ".hp") != 0)
+		    && (len <= 4 || strcmp (arg + (len - 4), ".hxx") != 0)
+		    && (len <= 4 || strcmp (arg + (len - 4), ".h++") != 0)
+		    && (len <= 4 || strcmp (arg + (len - 4), ".HPP") != 0)
+		    && (len <= 4 || strcmp (arg + (len - 4), ".tcc") != 0)
+		    && (len <= 3 || strcmp (arg + (len - 3), ".hh") != 0))
+		  library = 1;
+	      }
+	  }
+	  break;
 	}
     }
 
-  if (quote)
-    fatal_error ("argument to %qs missing", quote);
-
   /* There's no point adding -shared-libgcc if we don't have a shared
      libgcc.  */
 #ifndef ENABLE_SHARED_LIBGCC
   shared_libgcc = 0;
 #endif
 
-  /* Make sure to have room for the trailing NULL argument.
-     Add one for shared_libgcc or extra static library.  */
-  num_args = argc + added + need_math + (library > 0) * 4 + 2;
-  arglist = XNEWVEC (const char *, num_args);
+  /* Add one for shared_libgcc or extra static library.  */
+  num_args = argc + added + need_math + (library > 0) * 4 + 1;
+  new_decoded_options = XNEWVEC (struct cl_decoded_option, num_args);
 
   i = 0;
   j = 0;
 
   /* Copy the 0th argument, i.e., the name of the program itself.  */
-  arglist[i++] = argv[j++];
+  new_decoded_options[j++] = decoded_options[i++];
 
   /* NOTE: We start at 1 now, not 0.  */
   while (i < argc)
     {
-      arglist[j] = argv[i];
+      new_decoded_options[j] = decoded_options[i];
 
       /* Make sure -lstdc++ is before the math library, since libstdc++
 	 itself uses those math routines.  */
       if (!saw_math && (args[i] & MATHLIB) && library > 0)
 	{
 	  --j;
-	  saw_math = argv[i];
+	  saw_math = &decoded_options[i];
 	}
 
       if (!saw_libc && (args[i] & WITHLIBC) && library > 0)
 	{
 	  --j;
-	  saw_libc = argv[i];
+	  saw_libc = &decoded_options[i];
 	}
 
       /* Wrap foo.[chi] files in a language specification to
 	 force the gcc compiler driver to run cc1plus on them.  */
       if (args[i] & LANGSPEC)
 	{
-	  int len = strlen (argv[i]);
-	  switch (argv[i][len - 1])
+	  const char *arg = decoded_options[i].arg;
+	  int len = strlen (arg);
+	  switch (arg[len - 1])
 	    {
 	    case 'c':
-	      arglist[j++] = "-xc++";
+	      generate_option (OPT_x, "c++", 1, CL_DRIVER,
+			       &new_decoded_options[j++]);
 	      break;
 	    case 'i':
-	      arglist[j++] = "-xc++-cpp-output";
+	      generate_option (OPT_x, "c++-cpp-output", 1, CL_DRIVER,
+			       &new_decoded_options[j++]);
 	      break;
 	    case 'h':
-	      arglist[j++] = "-xc++-header";
+	      generate_option (OPT_x, "c++-header", 1, CL_DRIVER,
+			       &new_decoded_options[j++]);
 	      break;
 	    default:
 	      gcc_unreachable ();
 	    }
-	  arglist[j++] = argv[i];
-	  arglist[j] = "-xnone";
+	  new_decoded_options[j++] = decoded_options[i];
+	  generate_option (OPT_x, "none", 1, CL_DRIVER,
+			   &new_decoded_options[j]);
 	}
 
       if ((args[i] & SKIPOPT) != 0)
@@ -332,48 +316,51 @@  lang_specific_driver (int *in_argc, cons
 #ifdef HAVE_LD_STATIC_DYNAMIC
       if (library > 1 && !static_link)
 	{
-	  arglist[j] = "-Wl,-Bstatic";
+	  generate_option (OPT_Wl_, "-Bstatic", 1, CL_DRIVER,
+			   &new_decoded_options[j]);
 	  j++;
 	}
 #endif
-      arglist[j] = saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX;
-      if (arglist[j][0] != '-' || arglist[j][1] == 'l')
-	added_libraries++;
+      generate_option (OPT_l,
+		       saw_profile_flag ? LIBSTDCXX_PROFILE : LIBSTDCXX, 1,
+		       CL_DRIVER, &new_decoded_options[j]);
+      added_libraries++;
       j++;
       /* Add target-dependent static library, if necessary.  */
       if ((static_link || library > 1) && LIBSTDCXX_STATIC != NULL)
 	{
-	  arglist[j] = LIBSTDCXX_STATIC;
-	  if (arglist[j][0] != '-' || arglist[j][1] == 'l')
-	    added_libraries++;
+	  generate_option (OPT_l, LIBSTDCXX_STATIC, 1,
+			   CL_DRIVER, &new_decoded_options[j]);
+	  added_libraries++;
 	  j++;
 	}
 #ifdef HAVE_LD_STATIC_DYNAMIC
       if (library > 1 && !static_link)
 	{
-	  arglist[j] = "-Wl,-Bdynamic";
+	  generate_option (OPT_Wl_, "-Bdynamic", 1, CL_DRIVER,
+			   &new_decoded_options[j]);
 	  j++;
 	}
 #endif
     }
   if (saw_math)
-    arglist[j++] = saw_math;
+    new_decoded_options[j++] = *saw_math;
   else if (library > 0 && need_math)
     {
-      arglist[j] = saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY;
-      if (arglist[j][0] != '-' || arglist[j][1] == 'l')
-	added_libraries++;
+      generate_option (OPT_l,
+		       saw_profile_flag ? MATH_LIBRARY_PROFILE : MATH_LIBRARY,
+		       1, CL_DRIVER, &new_decoded_options[j]);
+      added_libraries++;
       j++;
     }
   if (saw_libc)
-    arglist[j++] = saw_libc;
+    new_decoded_options[j++] = *saw_libc;
   if (shared_libgcc && !static_link)
-    arglist[j++] = "-shared-libgcc";
-
-  arglist[j] = NULL;
+    generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
+		     &new_decoded_options[j++]);
 
-  *in_argc = j;
-  *in_argv = arglist;
+  *in_decoded_options_count = j;
+  *in_decoded_options = new_decoded_options;
   *in_added_libraries = added_libraries;
 }
 
Index: gcc/opts.h
===================================================================
--- gcc/opts.h	(revision 163280)
+++ gcc/opts.h	(working copy)
@@ -208,6 +208,11 @@  bool handle_option (const struct cl_deco
 bool handle_generated_option (size_t opt_index, const char *arg, int value,
 			      unsigned int lang_mask, int kind,
 			      const struct cl_option_handlers *handlers);
+void generate_option (size_t opt_index, const char *arg, int value,
+		      unsigned int lang_mask,
+		      struct cl_decoded_option *decoded);
+void generate_option_input_file (const char *file,
+				 struct cl_decoded_option *decoded);
 extern void read_cmdline_option (struct cl_decoded_option *decoded,
 				 unsigned int lang_mask,
 				 const struct cl_option_handlers *handlers);
Index: gcc/fortran/Make-lang.in
===================================================================
--- gcc/fortran/Make-lang.in	(revision 163280)
+++ gcc/fortran/Make-lang.in	(working copy)
@@ -78,7 +78,7 @@  fortran: f951$(exeext)
 .PHONY: fortran
 
 gfortranspec.o: $(srcdir)/fortran/gfortranspec.c $(SYSTEM_H) $(TM_H) $(GCC_H) \
-	$(CONFIG_H) coretypes.h intl.h
+	$(CONFIG_H) coretypes.h intl.h opts.h
 	(SHLIB_LINK='$(SHLIB_LINK)'; \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
 		$(INCLUDES) $(srcdir)/fortran/gfortranspec.c)
Index: gcc/fortran/gfortranspec.c
===================================================================
--- gcc/fortran/gfortranspec.c	(revision 163280)
+++ gcc/fortran/gfortranspec.c	(working copy)
@@ -48,149 +48,62 @@  along with GCC; see the file COPYING3.  
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
 #include "gcc.h"
+#include "opts.h"
 
-#include "coretypes.h"
 #include "tm.h"
 #include "intl.h"
 
 #ifndef MATH_LIBRARY
-#define MATH_LIBRARY "-lm"
+#define MATH_LIBRARY "m"
 #endif
 
 #ifndef FORTRAN_LIBRARY
-#define FORTRAN_LIBRARY "-lgfortran"
-#endif
-
-#ifdef HAVE_LD_STATIC_DYNAMIC
-#define ADD_ARG_LIBGFORTRAN(arg) \
-  { \
-    if (static_lib && !static_linking) \
-      append_arg ("-Wl,-Bstatic"); \
-    append_arg (arg); \
-    if (static_lib && !static_linking) \
-      append_arg ("-Wl,-Bdynamic"); \
-  }
-#else
-#define ADD_ARG_LIBGFORTRAN(arg) append_arg (arg);
+#define FORTRAN_LIBRARY "gfortran"
 #endif
 
-
-/* Options this driver needs to recognize, not just know how to
-   skip over.  */
-typedef enum
-{
-  OPTION_b,			/* Aka --prefix.  */
-  OPTION_B,			/* Aka --target.  */
-  OPTION_c,			/* Aka --compile.  */
-  OPTION_E,			/* Aka --preprocess.  */
-  OPTION_help,			/* --help.  */
-  OPTION_i,			/* -imacros, -include, -include-*.  */
-  OPTION_l,
-  OPTION_L,			/* Aka --library-directory.  */
-  OPTION_nostdlib,		/* Aka --no-standard-libraries, or
-				   -nodefaultlibs.  */
-  OPTION_o,			/* Aka --output.  */
-  OPTION_S,			/* Aka --assemble.  */
-  OPTION_static,		/* -static.  */
-  OPTION_static_libgfortran,	/* -static-libgfortran.  */
-  OPTION_syntax_only,		/* -fsyntax-only.  */
-  OPTION_v,			/* Aka --verbose.  */
-  OPTION_version,		/* --version.  */
-  OPTION_V,			/* Aka --use-version.  */
-  OPTION_x,			/* Aka --language.  */
-  OPTION_			/* Unrecognized or unimportant.  */
-}
-Option;
-
 /* The original argument list and related info is copied here.  */
-static int g77_xargc;
-static const char *const *g77_xargv;
-static void lookup_option (Option *, int *, const char **, const char *);
-static void append_arg (const char *);
+static unsigned int g77_xargc;
+static const struct cl_decoded_option *g77_x_decoded_options;
+static void append_arg (const struct cl_decoded_option *);
 
 /* The new argument list will be built here.  */
-static int g77_newargc;
-static const char **g77_newargv;
-
-/* Assumes text[0] == '-'.  Returns number of argv items that belong to
-   (and follow) this one, an option id for options important to the
-   caller, and a pointer to the first char of the arg, if embedded (else
-   returns NULL, meaning no arg or it's the next argv).
+static unsigned int g77_newargc;
+static struct cl_decoded_option *g77_new_decoded_options;
 
-   Note that this also assumes gcc.c's pass converting long options
-   to short ones, where available, has already been run.  */
+/* Return whether strings S1 and S2 are both NULL or both the same
+   string.  */
 
-static void
-lookup_option (Option *xopt, int *xskip, const char **xarg, const char *text)
+static bool
+strings_same (const char *s1, const char *s2)
 {
-  Option opt = OPTION_;
-  int skip;
-  const char *arg = NULL;
-
-  if ((skip = SWITCH_TAKES_ARG (text[1])))
-    skip -= (text[2] != '\0');	/* See gcc.c.  */
-
-  if (text[1] == 'B')
-    opt = OPTION_B, skip = (text[2] == '\0'), arg = text + 2;
-  else if (text[1] == 'b')
-    opt = OPTION_b, skip = (text[2] == '\0'), arg = text + 2;
-  else if ((text[1] == 'c') && (text[2] == '\0'))
-    opt = OPTION_c, skip = 0;
-  else if ((text[1] == 'E') && (text[2] == '\0'))
-    opt = OPTION_E, skip = 0;
-  else if (text[1] == 'i')
-    opt = OPTION_i, skip = 0;
-  else if (text[1] == 'l')
-    opt = OPTION_l;
-  else if (text[1] == 'L')
-    opt = OPTION_L, arg = text + 2;
-  else if (text[1] == 'o')
-    opt = OPTION_o;
-  else if ((text[1] == 'S') && (text[2] == '\0'))
-    opt = OPTION_S, skip = 0;
-  else if (text[1] == 'V')
-    opt = OPTION_V, skip = (text[2] == '\0');
-  else if ((text[1] == 'v') && (text[2] == '\0'))
-    opt = OPTION_v, skip = 0;
-  else if (text[1] == 'x')
-    opt = OPTION_x, arg = text + 2;
-  else if (text[1] == 'J')
-    ;
-  else
-    {
-      if ((skip = WORD_SWITCH_TAKES_ARG (text + 1)) != 0)  /* See gcc.c.  */
-	;
-      else if (!strcmp (text, "-fhelp"))	/* Really --help!! */
-	opt = OPTION_help;
-      else if (!strcmp (text, "-nostdlib")
-	       || !strcmp (text, "-nodefaultlibs"))
-	opt = OPTION_nostdlib;
-      else if (!strcmp (text, "-fsyntax-only"))
-	opt = OPTION_syntax_only;
-      else if (!strcmp (text, "-static-libgfortran"))
-	opt = OPTION_static_libgfortran;
-      else if (!strcmp (text, "-static"))
-	opt = OPTION_static;
-      else if (!strcmp (text, "-fversion"))	/* Really --version!! */
-	opt = OPTION_version;
-      else if (!strcmp (text, "-Xlinker") || !strcmp (text, "-specs"))
-	skip = 1;
-      else
-	skip = 0;
-    }
+  return s1 == s2 || (s1 != NULL && s2 != NULL && strcmp (s1, s2) == 0);
+}
 
-  if (xopt != NULL)
-    *xopt = opt;
-  if (xskip != NULL)
-    *xskip = skip;
-  if (xarg != NULL)
-    {
-      if ((arg != NULL) && (arg[0] == '\0'))
-	*xarg = NULL;
-      else
-	*xarg = arg;
-    }
+/* Return whether decoded option structures OPT1 and OPT2 are the
+   same.  */
+
+static bool
+options_same (const struct cl_decoded_option *opt1,
+	      const struct cl_decoded_option *opt2)
+{
+  return (opt1->opt_index == opt2->opt_index
+	  && strings_same (opt1->arg, opt2->arg)
+	  && strings_same (opt1->orig_option_with_args_text,
+			   opt2->orig_option_with_args_text)
+	  && strings_same (opt1->canonical_option[0],
+			   opt2->canonical_option[0])
+	  && strings_same (opt1->canonical_option[1],
+			   opt2->canonical_option[1])
+	  && strings_same (opt1->canonical_option[2],
+			   opt2->canonical_option[2])
+	  && strings_same (opt1->canonical_option[3],
+			   opt2->canonical_option[3])
+	  && (opt1->canonical_option_num_elements
+	      == opt2->canonical_option_num_elements)
+	  && opt1->value == opt2->value
+	  && opt1->errors == opt2->errors);
 }
 
 /* Append another argument to the list being built.  As long as it is
@@ -198,52 +111,78 @@  lookup_option (Option *xopt, int *xskip,
    the new arg count.  Otherwise allocate a new list, etc.  */
 
 static void
-append_arg (const char *arg)
+append_arg (const struct cl_decoded_option *arg)
 {
-  static int newargsize;
+  static unsigned int newargsize;
 
 #if 0
   fprintf (stderr, "`%s'\n", arg);
 #endif
 
-  if (g77_newargv == g77_xargv
+  if (g77_new_decoded_options == g77_x_decoded_options
       && g77_newargc < g77_xargc
-      && (arg == g77_xargv[g77_newargc]
-	  || !strcmp (arg, g77_xargv[g77_newargc])))
+      && options_same (arg, &g77_x_decoded_options[g77_newargc]))
     {
       ++g77_newargc;
       return;			/* Nothing new here.  */
     }
 
-  if (g77_newargv == g77_xargv)
+  if (g77_new_decoded_options == g77_x_decoded_options)
     {				/* Make new arglist.  */
-      int i;
+      unsigned int i;
 
       newargsize = (g77_xargc << 2) + 20;	/* This should handle all.  */
-      g77_newargv = (const char **) xmalloc (newargsize * sizeof (char *));
+      g77_new_decoded_options = XNEWVEC (struct cl_decoded_option, newargsize);
 
       /* Copy what has been done so far.  */
       for (i = 0; i < g77_newargc; ++i)
-	g77_newargv[i] = g77_xargv[i];
+	g77_new_decoded_options[i] = g77_x_decoded_options[i];
     }
 
   if (g77_newargc == newargsize)
-    fatal_error ("overflowed output arg list for %qs", arg);
+    fatal_error ("overflowed output arg list for %qs",
+		 arg->orig_option_with_args_text);
+
+  g77_new_decoded_options[g77_newargc++] = *arg;
+}
 
-  g77_newargv[g77_newargc++] = arg;
+/* Append an option described by OPT_INDEX, ARG and VALUE to the list
+   being built.  */
+static void
+append_option (size_t opt_index, const char *arg, int value)
+{
+  struct cl_decoded_option decoded;
+
+  generate_option (opt_index, arg, value, CL_DRIVER, &decoded);
+  append_arg (&decoded);
+}
+
+/* Append a libgfortran argument to the list being built.  If
+   FORCE_STATIC, ensure the library is linked statically.  */
+
+static void
+add_arg_libgfortran (bool force_static ATTRIBUTE_UNUSED)
+{
+#ifdef HAVE_LD_STATIC_DYNAMIC
+  if (force_static)
+    append_option (OPT_Wl_, "-Bstatic", 1);
+#endif
+  append_option (OPT_l, FORTRAN_LIBRARY, 1);
+#ifdef HAVE_LD_STATIC_DYNAMIC
+  if (force_static)
+    append_option (OPT_Wl_, "-Bdynamic", 1);
+#endif
 }
 
 void
-lang_specific_driver (int *in_argc, const char *const **in_argv,
+lang_specific_driver (struct cl_decoded_option **in_decoded_options,
+		      unsigned int *in_decoded_options_count,
 		      int *in_added_libraries ATTRIBUTE_UNUSED)
 {
-  int argc = *in_argc;
-  const char *const *argv = *in_argv;
-  int i;
+  unsigned int argc = *in_decoded_options_count;
+  struct cl_decoded_option *decoded_options = *in_decoded_options;
+  unsigned int i;
   int verbose = 0;
-  Option opt;
-  int skip;
-  const char *arg;
 
   /* This will be NULL if we encounter a situation where we should not
      link in libf2c.  */
@@ -261,13 +200,11 @@  lang_specific_driver (int *in_argc, cons
   /* By default, we throw on the math library if we have one.  */
   int need_math = (MATH_LIBRARY[0] != '\0');
 
-#ifdef HAVE_LD_STATIC_DYNAMIC
   /* Whether we should link a static libgfortran. */
   int static_lib = 0; 
 
   /* Whether we need to link statically.  */
   int static_linking = 0;
-#endif
 
   /* The number of input and output files in the incoming arg list.  */
   int n_infiles = 0;
@@ -276,91 +213,65 @@  lang_specific_driver (int *in_argc, cons
 #if 0
   fprintf (stderr, "Incoming:");
   for (i = 0; i < argc; i++)
-    fprintf (stderr, " %s", argv[i]);
+    fprintf (stderr, " %s", decoded_options[i].orig_option_with_args_text);
   fprintf (stderr, "\n");
 #endif
 
   g77_xargc = argc;
-  g77_xargv = argv;
+  g77_x_decoded_options = decoded_options;
   g77_newargc = 0;
-  g77_newargv = CONST_CAST2 (const char **, const char *const *, argv);
+  g77_new_decoded_options = decoded_options;
 
   /* First pass through arglist.
 
      If -nostdlib or a "turn-off-linking" option is anywhere in the
      command line, don't do any library-option processing (except
-     relating to -x).  Also, if -v is specified, but no other options
-     that do anything special (allowing -V version, etc.), remember
-     to add special stuff to make gcc command actually invoke all
-     the different phases of the compilation process so all the version
-     numbers can be seen.
-
-     Also, here is where all problems with missing arguments to options
-     are caught.  If this loop is exited normally, it means all options
-     have the appropriate number of arguments as far as the rest of this
-     program is concerned.  */
+     relating to -x).  */
 
   for (i = 1; i < argc; ++i)
     {
-      if ((argv[i][0] == '+') && (argv[i][1] == 'e'))
-	{
-	  continue;
-	}
-
-      if ((argv[i][0] != '-') || (argv[i][1] == '\0'))
+      switch (decoded_options[i].opt_index)
 	{
+	case OPT_SPECIAL_input_file:
 	  ++n_infiles;
 	  continue;
-	}
-
-      lookup_option (&opt, &skip, NULL, argv[i]);
 
-      switch (opt)
-	{
-	case OPTION_nostdlib:
-	case OPTION_c:
-	case OPTION_S:
-	case OPTION_syntax_only:
-	case OPTION_E:
+	case OPT_nostdlib:
+	case OPT_nodefaultlibs:
+	case OPT_c:
+	case OPT_S:
+	case OPT_fsyntax_only:
+	case OPT_E:
 	  /* These options disable linking entirely or linking of the
 	     standard libraries.  */
 	  library = 0;
 	  break;
 
-	case OPTION_static_libgfortran:
+	case OPT_static_libgfortran:
 #ifdef HAVE_LD_STATIC_DYNAMIC
 	  static_lib = 1;
 #endif
 	  break;
 
-	case OPTION_static:
+	case OPT_static:
 #ifdef HAVE_LD_STATIC_DYNAMIC
 	  static_linking = 1;
 #endif
 	  break;
 
-	case OPTION_l:
+	case OPT_l:
 	  ++n_infiles;
 	  break;
 
-	case OPTION_o:
+	case OPT_o:
 	  ++n_outfiles;
 	  break;
 
-	case OPTION_v:
+	case OPT_v:
 	  verbose = 1;
 	  break;
 
-	case OPTION_b:
-	case OPTION_B:
-	case OPTION_L:
-	case OPTION_i:
-	case OPTION_V:
-	  /* These options are useful in conjunction with -v to get
-	     appropriate version info.  */
-	  break;
-
-	case OPTION_version:
+	case OPT_fversion:
 	  printf ("GNU Fortran %s%s\n", pkgversion_string, version_string);
 	  printf ("Copyright %s 2010 Free Software Foundation, Inc.\n\n",
 		  _("(C)"));
@@ -371,7 +282,7 @@  For more information about these matters
 	  exit (0);
 	  break;
 
-	case OPTION_help:
+	case OPT_fhelp:
 	  /* Let gcc.c handle this, as it has a really
 	     cool facility for handling --help and --verbose --help.  */
 	  return;
@@ -379,14 +290,6 @@  For more information about these matters
 	default:
 	  break;
 	}
-
-      /* This is the one place we check for missing arguments in the
-	 program.  */
-
-      if (i + skip < argc)
-	i += skip;
-      else
-	fatal_error ("argument to %qs missing", argv[i]);
     }
 
   if ((n_outfiles != 0) && (n_infiles == 0))
@@ -398,50 +301,50 @@  For more information about these matters
 
   /* Second pass through arglist, transforming arguments as appropriate.  */
 
-  append_arg (argv[0]);		/* Start with command name, of course.  */
+  append_arg (&decoded_options[0]); /* Start with command name, of course.  */
 
   for (i = 1; i < argc; ++i)
     {
-      if (argv[i][0] == '\0')
+      if (decoded_options[i].errors & CL_ERR_MISSING_ARG)
+	{
+	  append_arg (&decoded_options[i]);
+	  continue;
+	}
+
+      if (decoded_options[i].opt_index == OPT_SPECIAL_input_file
+	  && decoded_options[i].arg[0] == '\0')
 	{
-	  append_arg (argv[i]);	/* Interesting.  Just append as is.  */
+	  /* Interesting.  Just append as is.  */
+	  append_arg (&decoded_options[i]);
 	  continue;
 	}
 
-      if ((argv[i][0] == '-') && (argv[i][1] != 'l'))
+      if (decoded_options[i].opt_index != OPT_l
+	  && (decoded_options[i].opt_index != OPT_SPECIAL_input_file
+	      || strcmp (decoded_options[i].arg, "-") == 0))
 	{
 	  /* Not a filename or library.  */
 
 	  if (saw_library == 1 && need_math)	/* -l<library>.  */
-	    append_arg (MATH_LIBRARY);
+	    append_option (OPT_l, MATH_LIBRARY, 1);
 
 	  saw_library = 0;
 
-	  lookup_option (&opt, &skip, &arg, argv[i]);
-
-	  if (argv[i][1] == '\0')
+	  if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
 	    {
-	      append_arg (argv[i]);	/* "-" == Standard input.  */
+	      append_arg (&decoded_options[i]);	/* "-" == Standard input.  */
 	      continue;
 	    }
 
-	  if (opt == OPTION_x)
+	  if (decoded_options[i].opt_index == OPT_x)
 	    {
 	      /* Track input language.  */
-	      const char *lang;
-
-	      if (arg == NULL)
-		lang = argv[i + 1];
-	      else
-		lang = arg;
+	      const char *lang = decoded_options[i].arg;
 
 	      saw_speclang = (strcmp (lang, "none") != 0);
 	    }
 
-	  append_arg (argv[i]);
-
-	  for (; skip != 0; --skip)
-	    append_arg (argv[++i]);
+	  append_arg (&decoded_options[i]);
 
 	  continue;
 	}
@@ -452,29 +355,29 @@  For more information about these matters
 	saw_library = 0;	/* -xfoo currently active.  */
       else
 	{			/* -lfoo or filename.  */
-	  if (strcmp (argv[i], MATH_LIBRARY) == 0)
+	  if (decoded_options[i].opt_index == OPT_l
+	      && strcmp (decoded_options[i].arg, MATH_LIBRARY) == 0)
 	    {
 	      if (saw_library == 1)
 		saw_library = 2;	/* -l<library> -lm.  */
 	      else
-		{
-		  ADD_ARG_LIBGFORTRAN (FORTRAN_LIBRARY);
-		}
+		add_arg_libgfortran (static_lib && !static_linking);
 	    }
-	  else if (strcmp (argv[i], FORTRAN_LIBRARY) == 0)
+	  else if (decoded_options[i].opt_index == OPT_l
+	      && strcmp (decoded_options[i].arg, FORTRAN_LIBRARY) == 0)
 	    {
 	      saw_library = 1;	/* -l<library>.  */
-	      ADD_ARG_LIBGFORTRAN (argv[i]);
+	      add_arg_libgfortran (static_lib && !static_linking);
 	      continue;
 	    }
 	  else
 	    {			/* Other library, or filename.  */
 	      if (saw_library == 1 && need_math)
-		append_arg (MATH_LIBRARY);
+		append_option (OPT_l, MATH_LIBRARY, 1);
 	      saw_library = 0;
 	    }
 	}
-      append_arg (argv[i]);
+      append_arg (&decoded_options[i]);
     }
 
   /* Append `-lg2c -lm' as necessary.  */
@@ -482,17 +385,17 @@  For more information about these matters
   if (library)
     {				/* Doing a link and no -nostdlib.  */
       if (saw_speclang)
-	append_arg ("-xnone");
+	append_option (OPT_x, "none", 1);
 
       switch (saw_library)
 	{
 	case 0:
-	  ADD_ARG_LIBGFORTRAN (library);
+	  add_arg_libgfortran (static_lib && !static_linking);
 	  /* Fall through.  */
 
 	case 1:
 	  if (need_math)
-	    append_arg (MATH_LIBRARY);
+	    append_option (OPT_l, MATH_LIBRARY, 1);
 	default:
 	  break;
 	}
@@ -501,30 +404,30 @@  For more information about these matters
 #ifdef ENABLE_SHARED_LIBGCC
   if (library)
     {
-      int i;
+      unsigned int i;
 
       for (i = 1; i < g77_newargc; i++)
-	if (g77_newargv[i][0] == '-')
-	  if (strcmp (g77_newargv[i], "-static-libgcc") == 0
-	      || strcmp (g77_newargv[i], "-static") == 0)
-	    break;
+	if (g77_new_decoded_options[i].opt_index == OPT_static_libgcc
+	    || g77_new_decoded_options[i].opt_index == OPT_static)
+	  break;
 
       if (i == g77_newargc)
-	append_arg ("-shared-libgcc");
+	append_option (OPT_shared_libgcc, NULL, 1);
     }
 
 #endif
 
-  if (verbose && g77_newargv != g77_xargv)
+  if (verbose && g77_new_decoded_options != g77_x_decoded_options)
     {
       fprintf (stderr, _("Driving:"));
       for (i = 0; i < g77_newargc; i++)
-	fprintf (stderr, " %s", g77_newargv[i]);
+	fprintf (stderr, " %s",
+		 g77_new_decoded_options[i].orig_option_with_args_text);
       fprintf (stderr, "\n");
     }
 
-  *in_argc = g77_newargc;
-  *in_argv = g77_newargv;
+  *in_decoded_options_count = g77_newargc;
+  *in_decoded_options = g77_new_decoded_options;
 }
 
 
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 163280)
+++ gcc/common.opt	(working copy)
@@ -69,6 +69,9 @@  Driver Joined Separate
 E
 Driver
 
+L
+Driver Joined Separate
+
 O
 Common JoinedOrMissing Optimization
 -O<number>	Set optimization level to <number>
@@ -1645,6 +1648,12 @@  Driver Joined Separate
 no-canonical-prefixes
 Driver
 
+nodefaultlibs
+Driver
+
+nostdlib
+Driver
+
 o
 Common Driver Joined Separate MissingArgError(missing filename after %qs)
 -o <file>	Place output into <file>
@@ -1664,6 +1673,9 @@  pedantic-errors
 Common
 Like -pedantic but issue them as errors
 
+pg
+Driver
+
 pipe
 Driver Var(use_pipes)
 
@@ -1740,6 +1752,9 @@  Driver Separate
 specs=
 Driver Joined
 
+static
+Driver
+
 static-libgcc
 Driver
 
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 163280)
+++ gcc/Makefile.in	(working copy)
@@ -2197,13 +2197,15 @@  gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) cor
   $(DRIVER_DEFINES) \
   -c $(srcdir)/gcc.c $(OUTPUT_OPTION))
 
-gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
+gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
+    opts.h
 	(SHLIB_LINK='$(SHLIB_LINK)'; \
 	$(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
   $(DRIVER_DEFINES) \
   -c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
 
-cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
+cppspec.o: cppspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
+    opts.h
 
 specs.h : s-specs ; @true
 s-specs : Makefile
Index: gcc/gccspec.c
===================================================================
--- gcc/gccspec.c	(revision 163280)
+++ gcc/gccspec.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* Specific flags and argument handling of the C front-end.
-   Copyright (C) 1999, 2001, 2003, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001, 2003, 2007, 2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,75 +22,77 @@  along with GCC; see the file COPYING3.  
 #include "coretypes.h"
 #include "tm.h"
 #include "gcc.h"
+#include "opts.h"
 
-/* Filter argc and argv before processing by the gcc driver proper.  */
+/* Filter command line before processing by the gcc driver proper.  */
 void
-lang_specific_driver (int *in_argc ATTRIBUTE_UNUSED,
-		      const char *const **in_argv ATTRIBUTE_UNUSED,
+lang_specific_driver (struct cl_decoded_option **in_decoded_options ATTRIBUTE_UNUSED,
+		      unsigned int *in_decoded_options_count ATTRIBUTE_UNUSED,
 		      int *in_added_libraries ATTRIBUTE_UNUSED)
 {
   /* Systems which use the NeXT runtime by default should arrange
      for the shared libgcc to be used when -fgnu-runtime is passed
      through specs.  */
 #if defined(ENABLE_SHARED_LIBGCC) && ! defined(NEXT_OBJC_RUNTIME)
-  int i;
+  unsigned int i;
 
   /* The new argument list will be contained in this.  */
-  const char **arglist;
+  struct cl_decoded_option *new_decoded_options;
 
   /* True if we should add -shared-libgcc to the command-line.  */
   int shared_libgcc = 0;
 
   /* The total number of arguments with the new stuff.  */
-  int argc;
+  unsigned int argc;
 
   /* The argument list.  */
-  const char *const *argv;
+  struct cl_decoded_option *decoded_options;
 
-  argc = *in_argc;
-  argv = *in_argv;
+  argc = *in_decoded_options_count;
+  decoded_options = *in_decoded_options;
 
   for (i = 1; i < argc; i++)
     {
-      if (argv[i][0] == '-')
+      switch (decoded_options[i].opt_index)
 	{
-	  if (strcmp (argv[i], "-static-libgcc") == 0
-	      || strcmp (argv[i], "-static") == 0)
-	    return;
-	}
-      else
-	{
-	  int len;
-
-	  /* If the filename ends in .m or .mi, we are compiling ObjC
-	     and want to pass -shared-libgcc.  */
-	  len = strlen (argv[i]);
-	  if ((len > 2 && argv[i][len - 2] == '.' && argv[i][len - 1] == 'm')
-	      ||  (len > 3 && argv[i][len - 3] == '.' && argv[i][len - 2] == 'm'
-		   && argv[i][len - 1] == 'i'))
-	    shared_libgcc = 1;
+	case OPT_static_libgcc:
+	case OPT_static:
+	  return;
+
+	case OPT_SPECIAL_input_file:
+	  {
+	    const char *file = decoded_options[i].arg;
+	    int len;
+
+	    /* If the filename ends in .m or .mi, we are compiling
+	       ObjC and want to pass -shared-libgcc.  */
+	    len = strlen (file);
+	    if ((len > 2 && file[len - 2] == '.' && file[len - 1] == 'm')
+		||  (len > 3 && file[len - 3] == '.' && file[len - 2] == 'm'
+		     && file[len - 1] == 'i'))
+	      shared_libgcc = 1;
+	  }
+	  break;
 	}
     }
 
   if  (shared_libgcc)
     {
-      /* Make sure to have room for the trailing NULL argument.  */
-      arglist = XNEWVEC (const char *, argc + 2);
+      new_decoded_options = XNEWVEC (struct cl_decoded_option, argc + 1);
 
       i = 0;
       do
 	{
-	  arglist[i] = argv[i];
+	  new_decoded_options[i] = decoded_options[i];
 	  i++;
 	}
       while (i < argc);
 
-      arglist[i++] = "-shared-libgcc";
-
-      arglist[i] = NULL;
+      generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
+		       &new_decoded_options[i++]);
 
-      *in_argc = i;
-      *in_argv = arglist;
+      *in_decoded_options_count = i;
+      *in_decoded_options = new_decoded_options;
     }
 #endif
 }
Index: gcc/config/s390/tpf.h
===================================================================
--- gcc/config/s390/tpf.h	(revision 163280)
+++ gcc/config/s390/tpf.h	(working copy)
@@ -1,5 +1,6 @@ 
 /* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
-   Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2007, 2009,
+   2010 Free Software Foundation, Inc.
    Contributed by P.J. Darcy (darcypj@us.ibm.com),
                   Hartmut Penner (hpenner@de.ibm.com), and
                   Ulrich Weigand (uweigand@de.ibm.com).
@@ -124,6 +125,6 @@  along with GCC; see the file COPYING3.  
 #define MD_UNWIND_SUPPORT "config/s390/tpf-unwind.h"
 
 /* IBM copies these libraries over with these names.  */
-#define MATH_LIBRARY "-lCLBM"
-#define LIBSTDCXX "-lCPP1"
+#define MATH_LIBRARY "CLBM"
+#define LIBSTDCXX "CPP1"
 #endif /* ! _TPF_H */
Index: gcc/config/i386/djgpp.h
===================================================================
--- gcc/config/i386/djgpp.h	(revision 163280)
+++ gcc/config/i386/djgpp.h	(working copy)
@@ -1,6 +1,6 @@ 
 /* Configuration for an i386 running MS-DOS with DJGPP.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005,
-   2007 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2007,
+   2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -166,7 +166,7 @@  along with GCC; see the file COPYING3.  
 #define PTRDIFF_TYPE "int"
 
 /* Used to be defined in xm-djgpp.h, but moved here for cross-compilers.  */
-#define LIBSTDCXX "-lstdcxx"
+#define LIBSTDCXX "stdcxx"
 
 #define TARGET_VERSION fprintf (stderr, " (80386, MS-DOS DJGPP)"); 
 
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	(revision 163280)
+++ gcc/config/avr/avr.h	(working copy)
@@ -780,7 +780,7 @@  mmcu=*:-mmcu=%*}"
 #define LIB_SPEC \
   "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lc }}}}}"
 
-#define LIBSTDCXX "-lgcc"
+#define LIBSTDCXX "gcc"
 /* No libstdc++ for now.  Empty string doesn't work.  */
 
 #define LIBGCC_SPEC \
Index: gcc/config/rs6000/aix.h
===================================================================
--- gcc/config/rs6000/aix.h	(revision 163280)
+++ gcc/config/rs6000/aix.h	(working copy)
@@ -156,7 +156,7 @@ 
 %{p:-L%R/lib/profiled -L%R/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc"
 
 /* Static linking with shared libstdc++ requires libsupc++ as well.  */
-#define LIBSTDCXX_STATIC "-lsupc++"
+#define LIBSTDCXX_STATIC "supc++"
 
 /* This now supports a natural alignment mode.  */
 /* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints.  */
Index: gcc/config/freebsd.h
===================================================================
--- gcc/config/freebsd.h	(revision 163280)
+++ gcc/config/freebsd.h	(working copy)
@@ -1,5 +1,6 @@ 
 /* Base configuration file for all FreeBSD targets.
-   Copyright (C) 1999, 2000, 2001, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009,
+   2010 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -76,7 +77,7 @@  along with GCC; see the file COPYING3.  
 #undef  WINT_TYPE
 #define WINT_TYPE "int"
 
-#define MATH_LIBRARY_PROFILE    "-lm_p"
+#define MATH_LIBRARY_PROFILE    "m_p"
 
 /* Code generation parameters.  */