OSDN Git Service

* c-decl.c (c_init_decl_processing): Clear input_file_name
[pf3gnuchains/gcc-fork.git] / gcc / c-opts.c
index 02f1ada..1dd5966 100644 (file)
@@ -1,5 +1,5 @@
 /* C/ObjC/C++ command line option handling.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    Contributed by Neil Booth.
 
 This file is part of GCC.
@@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "c-common.h"
 #include "c-pragma.h"
@@ -30,249 +32,125 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-inline.h"
 #include "diagnostic.h"
 #include "intl.h"
+#include "cppdefault.h"
+#include "c-incpath.h"
+#include "debug.h"             /* For debug_hooks.  */
+#include "c-options.h"
 
+#ifndef DOLLARS_IN_IDENTIFIERS
+# define DOLLARS_IN_IDENTIFIERS true
+#endif
+
+#ifndef TARGET_SYSTEM_ROOT
+# define TARGET_SYSTEM_ROOT NULL
+#endif
+
+#ifndef TARGET_EBCDIC
+# define TARGET_EBCDIC 0
+#endif
+
+static int saved_lineno;
+
+/* CPP's options.  */
 static cpp_options *cpp_opts;
 
+/* Input filename.  */
+static const char *in_fname;
+
+/* Filename and stream for preprocessed output.  */
+static const char *out_fname;
+static FILE *out_stream;
+
+/* Append dependencies to deps_file.  */
+static bool deps_append;
+
+/* If dependency switches (-MF etc.) have been given.  */
+static bool deps_seen;
+
+/* If -v seen.  */
+static bool verbose;
+
+/* Dependency output file.  */
+static const char *deps_file;
+
+/* The prefix given by -iprefix, if any.  */
+static const char *iprefix;
+
+/* The system root, if any.  Overridden by -isysroot.  */
+static const char *sysroot = TARGET_SYSTEM_ROOT;
+
+/* Zero disables all standard directories for headers.  */
+static bool std_inc = true;
+
+/* Zero disables the C++-specific standard directories for headers.  */
+static bool std_cxx_inc = true;
+
+/* If the quote chain has been split by -I-.  */
+static bool quote_chain_split;
+
+/* If -Wunused-macros.  */
+static bool warn_unused_macros;
+
+/* Number of deferred options, deferred options array size.  */
+static size_t deferred_count, deferred_size;
+
+/* Number of deferred options scanned for -include.  */
+static size_t include_cursor;
+
 static void missing_arg PARAMS ((size_t));
-static size_t parse_option PARAMS ((const char *, int));
+static size_t find_opt PARAMS ((const char *, int));
 static void set_Wimplicit PARAMS ((int));
 static void complain_wrong_lang PARAMS ((size_t));
 static void write_langs PARAMS ((char *, int));
 static void print_help PARAMS ((void));
 static void handle_OPT_d PARAMS ((const char *));
+static void set_std_cxx98 PARAMS ((int));
+static void set_std_c89 PARAMS ((int, int));
+static void set_std_c99 PARAMS ((int));
+static void check_deps_environment_vars PARAMS ((void));
+static void handle_deferred_opts PARAMS ((void));
+static void sanitize_cpp_opts PARAMS ((void));
+static void add_prefixed_path PARAMS ((const char *, size_t));
+static void push_command_line_include PARAMS ((void));
+static void cb_file_change PARAMS ((cpp_reader *, const struct line_map *));
+static void finish_options PARAMS ((void));
+static int c_common_handle_option (enum opt_code, const char *arg, int on);
+
+#ifndef STDC_0_IN_SYSTEM_HEADERS
+#define STDC_0_IN_SYSTEM_HEADERS 0
+#endif
+
+#define CL_C                   (1 << 0) /* Only C.  */
+#define CL_OBJC                        (1 << 1) /* Only ObjC.  */
+#define CL_CXX                 (1 << 2) /* Only C++.  */
+#define CL_OBJCXX              (1 << 3) /* Only ObjC++.  */
+#define CL_JOINED              (1 << 4) /* If takes joined argument.  */
+#define CL_SEPARATE            (1 << 5) /* If takes a separate argument.  */
+#define CL_REJECT_NEGATIVE     (1 << 6) /* Reject no- form.  */
 
-#define CL_C_ONLY      (1 << 0) /* Only C.  */
-#define CL_OBJC_ONLY   (1 << 1) /* Only ObjC.  */
-#define CL_CXX_ONLY    (1 << 2) /* Only C++.  */
-#define CL_OBJCXX_ONLY (1 << 3) /* Only ObjC++.  */
-#define CL_JOINED      (1 << 4) /* If takes joined argument.  */
-#define CL_SEPARATE    (1 << 5) /* If takes a separate argument.  */
-
-#define CL_ARG         (CL_JOINED | CL_SEPARATE)
-#define CL_C           (CL_C_ONLY | CL_OBJC_ONLY)
-#define CL_OBJC                (CL_OBJC_ONLY | CL_OBJCXX_ONLY)
-#define CL_CXX         (CL_CXX_ONLY | CL_OBJCXX_ONLY)
-#define CL_ALL         (CL_C | CL_CXX)
-
-/* This is the list of all command line options, with the leading "-"
-   removed.  It must be sorted in ASCII collating order.  All options
-   beginning with "f" or "W" are implicitly assumed to take a "no-"
-   form; this form should not be listed.  The variable "on" is true if
-   the positive form is given, otherwise it is false.  If you don't
-   want to allow a "no-" form, your handler should reject "on" being
-   false by returning zero.  See, for example, the handling of
-   -ftabstop=.
-
-   If the user gives an option to a front end that doesn't support it,
+#include "c-options.c"
+
+/* If the user gives an option to a front end that doesn't support it,
    an error is output, mentioning which front ends the option is valid
    for.  If you don't want this, you must accept it for all front
    ends, and test for the front end in the option handler.  See, for
-   example, the handling of -Wno-strict-prototypes for C++.
-
-   If you request an argument with CL_JOINED, CL_SEPARATE or their
-   combination CL_ARG, it is stored in the variable "arg", which is
-   guaranteed to be non-NULL and to not be an empty string.  It points
-   to the argument either within the argv[] vector or within one of
-   that vector's strings, and so the text is permanent and copies need
-   not be made.  Be sure to add an error message in missing_arg() if
-   the default is not appropriate.  */
-
-#define COMMAND_LINE_OPTIONS                                                \
-  OPT("-help",                  CL_ALL,   OPT__help)                        \
-  OPT("C",                      CL_ALL,   OPT_C)                            \
-  OPT("CC",                     CL_ALL,   OPT_CC)                           \
-  OPT("E",                     CL_ALL,   OPT_E)                             \
-  OPT("H",                      CL_ALL,   OPT_H)                            \
-  OPT("P",                      CL_ALL,   OPT_P)                            \
-  OPT("Wall",                  CL_ALL,   OPT_Wall)                          \
-  OPT("Wbad-function-cast",    CL_C,     OPT_Wbad_function_cast)            \
-  OPT("Wcast-qual",            CL_ALL,   OPT_Wcast_qual)                    \
-  OPT("Wchar-subscripts",      CL_ALL,   OPT_Wchar_subscripts)              \
-  OPT("Wcomment",              CL_ALL,   OPT_Wcomment)                      \
-  OPT("Wcomments",              CL_ALL,   OPT_Wcomments)                    \
-  OPT("Wconversion",           CL_ALL,   OPT_Wconversion)                   \
-  OPT("Wctor-dtor-privacy",    CL_CXX,   OPT_Wctor_dtor_privacy)            \
-  OPT("Wdeprecated",           CL_CXX,   OPT_Wdeprecated)                   \
-  OPT("Wdiv-by-zero",          CL_C,     OPT_Wdiv_by_zero)                  \
-  OPT("Weffc++",               CL_CXX,   OPT_Weffcxx)                       \
-  OPT("Wendif-labels",         CL_ALL,   OPT_Wendif_labels)                 \
-  OPT("Werror",                 CL_ALL,   OPT_Werror)                       \
-  OPT("Werror-implicit-function-declaration",                               \
-                               CL_C,     OPT_Werror_implicit_function_decl) \
-  OPT("Wfloat-equal",          CL_ALL,   OPT_Wfloat_equal)                  \
-  OPT("Wformat",               CL_ALL,   OPT_Wformat)                       \
-  OPT("Wformat-extra-args",    CL_ALL,   OPT_Wformat_extra_args)            \
-  OPT("Wformat-nonliteral",    CL_ALL,   OPT_Wformat_nonliteral)            \
-  OPT("Wformat-security",      CL_ALL,   OPT_Wformat_security)              \
-  OPT("Wformat-y2k",           CL_ALL,   OPT_Wformat_y2k)                   \
-  OPT("Wformat-zero-length",   CL_C,     OPT_Wformat_zero_length)           \
-  OPT("Wformat=",              CL_ALL | CL_JOINED, OPT_Wformat_eq)          \
-  OPT("Wimplicit",             CL_CXX,   OPT_Wimplicit)                     \
-  OPT("Wimplicit-function-declaration",        CL_C, OPT_Wimplicit_function_decl)   \
-  OPT("Wimplicit-int",         CL_C,     OPT_Wimplicit_int)                 \
-  OPT("Wimport",                CL_ALL,   OPT_Wimport)                      \
-  OPT("Wlong-long",            CL_ALL,   OPT_Wlong_long)                    \
-  OPT("Wmain",                 CL_C,     OPT_Wmain)                         \
-  OPT("Wmissing-braces",       CL_ALL,   OPT_Wmissing_braces)               \
-  OPT("Wmissing-declarations", CL_C,     OPT_Wmissing_declarations)         \
-  OPT("Wmissing-format-attribute",CL_ALL, OPT_Wmissing_format_attribute)     \
-  OPT("Wmissing-prototypes",   CL_ALL,   OPT_Wmissing_prototypes)           \
-  OPT("Wmultichar",            CL_ALL,   OPT_Wmultichar)                    \
-  OPT("Wnested-externs",       CL_C,     OPT_Wnested_externs)               \
-  OPT("Wnon-template-friend",  CL_CXX,   OPT_Wnon_template_friend)          \
-  OPT("Wnon-virtual-dtor",     CL_CXX,   OPT_Wnon_virtual_dtor)             \
-  OPT("Wnonnull",              CL_C,     OPT_Wnonnull)                      \
-  OPT("Wold-style-cast",       CL_CXX,   OPT_Wold_style_cast)               \
-  OPT("Woverloaded-virtual",   CL_CXX,   OPT_Woverloaded_virtual)           \
-  OPT("Wparentheses",          CL_ALL,   OPT_Wparentheses)                  \
-  OPT("Wpmf-conversions",      CL_CXX,   OPT_Wpmf_conversions)              \
-  OPT("Wpointer-arith",                CL_ALL,   OPT_Wpointer_arith)                \
-  OPT("Wprotocol",             CL_OBJC,  OPT_Wprotocol)                     \
-  OPT("Wredundant-decls",      CL_ALL,   OPT_Wredundant_decls)              \
-  OPT("Wreorder",              CL_CXX,   OPT_Wreorder)                      \
-  OPT("Wreturn-type",          CL_ALL,   OPT_Wreturn_type)                  \
-  OPT("Wselector",             CL_OBJC,  OPT_Wselector)                     \
-  OPT("Wsequence-point",       CL_C,     OPT_Wsequence_point)               \
-  OPT("Wsign-compare",         CL_ALL,   OPT_Wsign_compare)                 \
-  OPT("Wsign-promo",           CL_CXX,   OPT_Wsign_promo)                   \
-  OPT("Wstrict-prototypes",    CL_ALL,   OPT_Wstrict_prototypes)            \
-  OPT("Wsynth",                        CL_CXX,   OPT_Wsynth)                        \
-  OPT("Wsystem-headers",       CL_ALL,   OPT_Wsystem_headers)               \
-  OPT("Wtraditional",          CL_C,     OPT_Wtraditional)                  \
-  OPT("Wtrigraphs",            CL_ALL,   OPT_Wtrigraphs)                    \
-  OPT("Wundef",                        CL_ALL,   OPT_Wundef)                        \
-  OPT("Wunknown-pragmas",      CL_ALL,   OPT_Wunknown_pragmas)              \
-  OPT("Wunused-macros",                CL_ALL,   OPT_Wunused_macros)                \
-  OPT("Wwrite-strings",                CL_ALL,   OPT_Wwrite_strings)                \
-  OPT("ansi",                  CL_ALL,   OPT_ansi)                          \
-  OPT("d",                      CL_ALL | CL_JOINED, OPT_d)                  \
-  OPT("faccess-control",       CL_CXX,   OPT_faccess_control)               \
-  OPT("fall-virtual",          CL_CXX,   OPT_fall_virtual)                  \
-  OPT("falt-external-templates",CL_CXX,   OPT_falt_external_templates)      \
-  OPT("fasm",                  CL_ALL,   OPT_fasm)                          \
-  OPT("fbuiltin",              CL_ALL,   OPT_fbuiltin)                      \
-  OPT("fbuiltin-",             CL_ALL | CL_JOINED, OPT_fbuiltin_)           \
-  OPT("fcheck-new",            CL_CXX,   OPT_fcheck_new)                    \
-  OPT("fcond-mismatch",                CL_ALL,   OPT_fcond_mismatch)                \
-  OPT("fconserve-space",       CL_CXX,   OPT_fconserve_space)               \
-  OPT("fconst-strings",                CL_CXX,   OPT_fconst_strings)                \
-  OPT("fconstant-string-class=", CL_OBJC | CL_JOINED,                       \
-                                         OPT_fconstant_string_class)        \
-  OPT("fdefault-inline",       CL_CXX,   OPT_fdefault_inline)               \
-  OPT("fdollars-in-identifiers",CL_ALL,   OPT_fdollars_in_identifiers)      \
-  OPT("fdump-",                        CL_ALL | CL_JOINED, OPT_fdump)               \
-  OPT("felide-constructors",   CL_CXX,   OPT_felide_constructors)           \
-  OPT("fenforce-eh-specs",     CL_CXX,   OPT_fenforce_eh_specs)             \
-  OPT("fenum-int-equiv",       CL_CXX,   OPT_fenum_int_equiv)               \
-  OPT("fexternal-templates",   CL_CXX,   OPT_fexternal_templates)           \
-  OPT("ffor-scope",            CL_CXX,   OPT_ffor_scope)                    \
-  OPT("ffreestanding",         CL_C,     OPT_ffreestanding)                 \
-  OPT("fgnu-keywords",         CL_CXX,   OPT_fgnu_keywords)                 \
-  OPT("fgnu-runtime",          CL_OBJC,  OPT_fgnu_runtime)                  \
-  OPT("fguiding-decls",                CL_CXX,   OPT_fguiding_decls)                \
-  OPT("fhandle-exceptions",    CL_CXX,   OPT_fhandle_exceptions)            \
-  OPT("fhonor-std",            CL_CXX,   OPT_fhonor_std)                    \
-  OPT("fhosted",               CL_C,     OPT_fhosted)                       \
-  OPT("fhuge-objects",         CL_CXX,   OPT_fhuge_objects)                 \
-  OPT("fimplement-inlines",    CL_CXX,   OPT_fimplement_inlines)            \
-  OPT("fimplicit-inline-templates", CL_CXX, OPT_fimplicit_inline_templates)  \
-  OPT("fimplicit-templates",   CL_CXX,   OPT_fimplicit_templates)           \
-  OPT("flabels-ok",            CL_CXX,   OPT_flabels_ok)                    \
-  OPT("fms-extensions",                CL_ALL,   OPT_fms_extensions)                \
-  OPT("fname-mangling-version-",CL_CXX | CL_JOINED, OPT_fname_mangling)             \
-  OPT("fnew-abi",              CL_CXX,   OPT_fnew_abi)                      \
-  OPT("fnext-runtime",         CL_OBJC,  OPT_fnext_runtime)                 \
-  OPT("fnonansi-builtins",     CL_CXX,   OPT_fnonansi_builtins)             \
-  OPT("fnonnull-objects",      CL_CXX,   OPT_fnonnull_objects)              \
-  OPT("foperator-names",       CL_CXX,   OPT_foperator_names)               \
-  OPT("foptional-diags",       CL_CXX,   OPT_foptional_diags)               \
-  OPT("fpermissive",           CL_CXX,   OPT_fpermissive)                   \
-  OPT("fpreprocessed",         CL_ALL,   OPT_fpreprocessed)                 \
-  OPT("frepo",                 CL_CXX,   OPT_frepo)                         \
-  OPT("frtti",                 CL_CXX,   OPT_frtti)                         \
-  OPT("fshort-double",         CL_ALL,   OPT_fshort_double)                 \
-  OPT("fshort-enums",          CL_ALL,   OPT_fshort_enums)                  \
-  OPT("fshort-wchar",          CL_ALL,   OPT_fshort_wchar)                  \
-  OPT("fshow-column",          CL_ALL,   OPT_fshow_column)                  \
-  OPT("fsigned-bitfields",     CL_ALL,   OPT_fsigned_bitfields)             \
-  OPT("fsigned-char",          CL_ALL,   OPT_fsigned_char)                  \
-  OPT("fsquangle",             CL_CXX,   OPT_fsquangle)                     \
-  OPT("fstats",                        CL_CXX,   OPT_fstats)                        \
-  OPT("fstrict-prototype",     CL_CXX,   OPT_fstrict_prototype)             \
-  OPT("ftabstop=",              CL_ALL | CL_JOINED, OPT_ftabstop)           \
-  OPT("ftemplate-depth-",      CL_CXX | CL_JOINED, OPT_ftemplate_depth)     \
-  OPT("fthis-is-variable",     CL_CXX,   OPT_fthis_is_variable)             \
-  OPT("funsigned-bitfields",   CL_ALL,   OPT_funsigned_bitfields)           \
-  OPT("funsigned-char",                CL_ALL,   OPT_funsigned_char)                \
-  OPT("fuse-cxa-atexit",       CL_CXX,   OPT_fuse_cxa_atexit)               \
-  OPT("fvtable-gc",            CL_CXX,   OPT_fvtable_gc)                    \
-  OPT("fvtable-thunks",                CL_CXX,   OPT_fvtable_thunks)                \
-  OPT("fweak",                 CL_CXX,   OPT_fweak)                         \
-  OPT("fxref",                 CL_CXX,   OPT_fxref)                         \
-  OPT("gen-decls",             CL_OBJC,  OPT_gen_decls)                     \
-  OPT("nostdinc",               CL_ALL,   OPT_nostdinc)                             \
-  OPT("nostdinc++",             CL_ALL,   OPT_nostdincplusplus)                     \
-  OPT("pedantic",              CL_ALL,   OPT_pedantic)                      \
-  OPT("pedantic-errors",       CL_ALL,   OPT_pedantic_errors)               \
-  OPT("print-objc-runtime-info", CL_OBJC, OPT_print_objc_runtime_info)      \
-  OPT("std=",                  CL_ALL | CL_JOINED, OPT_std_bad)             \
-  OPT("std=c++98",             CL_CXX,   OPT_std_cplusplus98)               \
-  OPT("std=c89",               CL_C,     OPT_std_c89)                       \
-  OPT("std=c99",               CL_C,     OPT_std_c99)                       \
-  OPT("std=c9x",               CL_C,     OPT_std_c9x)                       \
-  OPT("std=gnu89",             CL_C,     OPT_std_gnu89)                     \
-  OPT("std=gnu99",             CL_C,     OPT_std_gnu99)                     \
-  OPT("std=gnu9x",             CL_C,     OPT_std_gnu9x)                     \
-  OPT("std=iso9899:1990",      CL_C,     OPT_std_iso9899_1990)              \
-  OPT("std=iso9899:199409",    CL_C,     OPT_std_iso9899_199409)            \
-  OPT("std=iso9899:1999",      CL_C,     OPT_std_iso9899_1999)              \
-  OPT("std=iso9899:199x",      CL_C,     OPT_std_iso9899_199x)              \
-  OPT("traditional-cpp",       CL_ALL,   OPT_traditional_cpp)               \
-  OPT("trigraphs",              CL_ALL,   OPT_trigraphs)                    \
-  OPT("undef",                 CL_ALL,   OPT_undef)                         \
-  OPT("v",                      CL_ALL,      OPT_v)                         \
-  OPT("w",                      CL_ALL,      OPT_w)
-
-#define OPT(text, flags, code) code,
-enum opt_code
-{
-  COMMAND_LINE_OPTIONS
-  N_OPTS
-};
-#undef OPT
-
-struct cl_option
+   example, the handling of -fcond-mismatch.
+
+   If you requested a joined or separate argument, it is stored in the
+   variable "arg", which is guaranteed to be non-NULL and to not be an
+   empty string.  It points to the argument either within the argv[]
+   vector or within one of that vector's strings, and so the text is
+   permanent and copies need not be made.  Be sure to add an error
+   message in missing_arg() if the default is not appropriate.  */
+
+/* Holds switches parsed by c_common_decode_option (), but whose
+   handling is deferred to c_common_post_options ().  */
+static void defer_opt PARAMS ((enum opt_code, const char *));
+static struct deferred_opt
 {
-  const char *opt_text;
-  unsigned char opt_len;
-  unsigned char flags;
-  ENUM_BITFIELD (opt_code) opt_code : 2 * CHAR_BIT;
-};
-
-#define OPT(text, flags, code) { text, sizeof(text) - 1, flags, code },
-#ifdef HOST_EBCDIC
-static struct cl_option cl_options[] =
-#else
-static const struct cl_option cl_options[] =
-#endif
-{
-  COMMAND_LINE_OPTIONS
-};
-#undef OPT
-#undef COMMAND_LINE_OPTIONS
-
-#ifdef HOST_EBCDIC
-static int opt_comp PARAMS ((const void *, const void *));
-
-/* Run-time sorting of options array.  */
-static int
-opt_comp (p1, p2)
-     const void *p1, *p2;
-{
-  return strcmp (((struct cl_option *) p1)->opt_text,
-                ((struct cl_option *) p2)->opt_text);
-}
-#endif
+  enum opt_code code;
+  const char *arg;
+} *deferred_opts;
 
 /* Complain that switch OPT_INDEX expects an argument but none was
    provided.  */
@@ -280,22 +158,58 @@ static void
 missing_arg (opt_index)
      size_t opt_index;
 {
+  const char *opt_text = cl_options[opt_index].opt_text;
+
   switch (opt_index)
     {
-    case OPT_Wformat_eq:
+    case OPT__output_pch_:
+    case OPT_Wformat_:
     case OPT_d:
+    case OPT_fabi_version_:
     case OPT_fbuiltin_:
-    case OPT_fdump:
-    case OPT_fname_mangling:
-    case OPT_ftabstop:
-    case OPT_ftemplate_depth:
-    case OPT_std_bad:
+    case OPT_fdump_:
+    case OPT_fname_mangling_version_:
+    case OPT_ftabstop_:
+    case OPT_ftemplate_depth_:
+    case OPT_iprefix:
+    case OPT_iwithprefix:
+    case OPT_iwithprefixbefore:
     default:
-      error ("missing argument to \"-%s\"", cl_options[opt_index].opt_text);
+      error ("missing argument to \"-%s\"", opt_text);
+      break;
+
+    case OPT_fconstant_string_class_:
+      error ("no class name specified with \"-%s\"", opt_text);
       break;
 
-    case OPT_fconstant_string_class:
-      error ("no class name specified with -fconstant-string-class=");
+    case OPT_A:
+      error ("assertion missing after \"-%s\"", opt_text);
+      break;
+
+    case OPT_D:
+    case OPT_U:
+      error ("macro name missing after \"-%s\"", opt_text);
+      break;
+
+    case OPT_I:
+    case OPT_idirafter:
+    case OPT_isysroot:
+    case OPT_isystem:
+      error ("missing path after \"-%s\"", opt_text);
+      break;
+
+    case OPT_MF:
+    case OPT_MD:
+    case OPT_MMD:
+    case OPT_include:
+    case OPT_imacros:
+    case OPT_o:
+      error ("missing filename after \"-%s\"", opt_text);
+      break;
+
+    case OPT_MQ:
+    case OPT_MT:
+      error ("missing target after \"-%s\"", opt_text);
       break;
     }
 }
@@ -307,15 +221,18 @@ missing_arg (opt_index)
    Complications arise since some options can be suffixed with an
    argument, and multiple complete matches can occur, e.g. -pedantic
    and -pedantic-errors.  Also, some options are only accepted by some
-   languages.  */
+   languages.  If a switch matches for a different language and
+   doesn't match any alternatives for the true front end, the index of
+   the matched switch is returned anyway.  The caller should check for
+   this case.  */
 static size_t
-parse_option (input, lang_flag)
+find_opt (input, lang_flag)
      const char *input;
      int lang_flag;
 {
   size_t md, mn, mx;
   size_t opt_len;
-  size_t wrong_lang = N_OPTS;
+  size_t result = N_OPTS;
   int comp;
 
   mn = 0;
@@ -326,7 +243,7 @@ parse_option (input, lang_flag)
       md = (mn + mx) / 2;
 
       opt_len = cl_options[md].opt_len;
-      comp = memcmp (input, cl_options[md].opt_text, opt_len);
+      comp = strncmp (input, cl_options[md].opt_text, opt_len);
 
       if (comp < 0)
        mx = md;
@@ -336,13 +253,7 @@ parse_option (input, lang_flag)
        {
          /* The switch matches.  It it an exact match?  */
          if (input[opt_len] == '\0')
-           {
-           exact_match:
-             if (cl_options[md].flags & lang_flag)
-               return md;
-             wrong_lang = md;
-             break;
-           }
+           return md;
          else
            {
              mn = md + 1;
@@ -356,9 +267,10 @@ parse_option (input, lang_flag)
              /* Is this switch valid for this front end?  */
              if (!(cl_options[md].flags & lang_flag))
                {
-                 /* If subsequently we don't find a good match,
-                    report this as a bad match.  */
-                 wrong_lang = md;
+                 /* If subsequently we don't find a better match,
+                    return this and let the caller report it as a bad
+                    match.  */
+                 result = md;
                  continue;
                }
 
@@ -374,10 +286,10 @@ parse_option (input, lang_flag)
              for (md = md + 1; md < (size_t) N_OPTS; md++)
                {
                  opt_len = cl_options[md].opt_len;
-                 if (memcmp (input, cl_options[md].opt_text, opt_len))
+                 if (strncmp (input, cl_options[md].opt_text, opt_len))
                    break;
                  if (input[opt_len] == '\0')
-                   goto exact_match;
+                   return md;
                  if (cl_options[md].flags & lang_flag
                      && cl_options[md].flags & CL_JOINED)
                    mx = md;
@@ -388,10 +300,31 @@ parse_option (input, lang_flag)
        }
     }
 
-  if (wrong_lang != N_OPTS)
-    complain_wrong_lang (wrong_lang);
+  return result;
+}
+
+/* Defer option CODE with argument ARG.  */
+static void
+defer_opt (code, arg)
+     enum opt_code code;
+     const char *arg;
+{
+  /* FIXME: this should be in c_common_init_options, which should take
+     argc and argv.  */
+  if (!deferred_opts)
+    {
+      extern int save_argc;
+      deferred_size = save_argc;
+      deferred_opts = (struct deferred_opt *)
+       xmalloc (deferred_size * sizeof (struct deferred_opt));
+    }
+
+  if (deferred_count == deferred_size)
+    abort ();
 
-  return N_OPTS;
+  deferred_opts[deferred_count].code = code;
+  deferred_opts[deferred_count].arg = arg;
+  deferred_count++;
 }
 
 /* Common initialization before parsing options.  */
@@ -399,27 +332,16 @@ void
 c_common_init_options (lang)
      enum c_language_kind lang;
 {
-#ifdef HOST_EBCDIC
-  /* For non-ASCII hosts, the cl_options array needs to be sorted at
-     runtime.  */
-  qsort (cl_options, N_OPTS, sizeof (struct cl_option), opt_comp);
-#endif
-
   c_language = lang;
-  parse_in = cpp_create_reader (lang == clk_c
-                               ? CLK_GNUC89 : CLK_GNUCXX);
+  parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89 : CLK_GNUCXX,
+                               ident_hash);
   cpp_opts = cpp_get_options (parse_in);
-
+  cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
   if (flag_objc)
     cpp_opts->objc = 1;
 
   flag_const_strings = (lang == clk_cplusplus);
   warn_pointer_arith = (lang == clk_cplusplus);
-  if (lang == clk_c)
-    warn_sign_compare = -1;
-
-  /* Mark as "unspecified" (see c_common_post_options).  */
-  flag_bounds_check = -1;
 }
 
 /* Handle one command-line option in (argc, argv).
@@ -430,32 +352,31 @@ c_common_decode_option (argc, argv)
      int argc;
      char **argv;
 {
+  static const int lang_flags[] = {CL_C, CL_OBJC, CL_CXX, CL_OBJCXX};
   size_t opt_index;
   const char *opt, *arg = 0;
   char *dup = 0;
   bool on = true;
-  int result, lang_flag;
+  int result = 0, temp, lang_flag;
   const struct cl_option *option;
-  enum opt_code code;
 
-  result = cpp_handle_option (parse_in, argc, argv);
   opt = argv[0];
 
-  /* Until handling CPP stuff, ignore non-switches.  */
+  /* Interpret "-" or a non-switch as a file name.  */
   if (opt[0] != '-' || opt[1] == '\0')
-    return result;
-
-  switch (c_language)
     {
-    case clk_c:                        lang_flag = (flag_objc
-                                            ? CL_C
-                                            : CL_C_ONLY);
-                               break;
-    case clk_cplusplus:                lang_flag = (flag_objc
-                                            ? CL_CXX
-                                            : CL_CXX_ONLY);
-                               break;
-    default:                   abort ();
+      if (!in_fname)
+       in_fname = opt;
+      else if (!out_fname)
+       out_fname = opt;
+      else
+       {
+         error ("too many filenames given.  Type %s --help for usage",
+                progname);
+         return argc;
+       }
+
+      return 1;
     }
 
   /* Drop the "no-" from negative switches.  */
@@ -473,15 +394,22 @@ c_common_decode_option (argc, argv)
     }
 
   /* Skip over '-'.  */
-  opt_index = parse_option (opt + 1, lang_flag);
+  lang_flag = lang_flags[(c_language << 1) + flag_objc];
+  opt_index = find_opt (opt + 1, lang_flag);
   if (opt_index == N_OPTS)
     goto done;
 
-  result = 1;
   option = &cl_options[opt_index];
 
+  /* Reject negative form of switches that don't take negatives.  */
+  if (!on && (option->flags & CL_REJECT_NEGATIVE))
+    goto done;
+
+  /* We've recognised this switch.  */
+  result = 1;
+
   /* Sort out any argument the switch takes.  */
-  if (option->flags & CL_ARG)
+  if (option->flags & (CL_JOINED | CL_SEPARATE))
     {
       if (option->flags & CL_JOINED)
        {
@@ -509,7 +437,36 @@ c_common_decode_option (argc, argv)
        }
     }
 
-  switch (code = option->opt_code)
+  /* Complain about the wrong language after we've swallowed any
+     necessary extra argument.  Eventually make this a hard error
+     after the call to find_opt, and return argc.  */
+  if (!(cl_options[opt_index].flags & lang_flag))
+    {
+      complain_wrong_lang (opt_index);
+      goto done;
+    }
+
+  temp = c_common_handle_option (opt_index, arg, on);
+  if (temp <= 0)
+    result = temp;
+
+ done:
+  if (dup)
+    free (dup);
+  return result;
+}
+
+/* Handle switch OPT_INDEX with argument ARG.  ON is true, unless no-
+   form of an -f or -W option was given.  Returns 0 if the switch was
+   invalid, a negative number to prevent language-independent
+   processing in toplev.c (a hack necessary for the short-term).  */
+static int
+c_common_handle_option (enum opt_code code, const char *arg, int on)
+{
+  const struct cl_option *option = &cl_options[code];
+  int result = 1;
+
+  switch (code)
     {
     case N_OPTS: /* Shut GCC up.  */
       break;
@@ -518,6 +475,14 @@ c_common_decode_option (argc, argv)
       print_help ();
       break;
 
+    case OPT__output_pch_:
+      pch_file = arg;
+      break;
+
+    case OPT_A:
+      defer_opt (code, arg);
+      break;
+
     case OPT_C:
       cpp_opts->discard_comments = 0;
       break;
@@ -527,6 +492,10 @@ c_common_decode_option (argc, argv)
       cpp_opts->discard_comments_in_macro_exp = 0;
       break;
 
+    case OPT_D:
+      defer_opt (code, arg);
+      break;
+
     case OPT_E:
       flag_preprocess_only = 1;
       break;
@@ -535,8 +504,66 @@ c_common_decode_option (argc, argv)
       cpp_opts->print_include_names = 1;
       break;
 
+    case OPT_I:
+      if (strcmp (arg, "-"))
+       add_path (xstrdup (arg), BRACKET, 0);
+      else
+       {
+         if (quote_chain_split)
+           error ("-I- specified twice");
+         quote_chain_split = true;
+         split_quote_chain ();
+       }
+      break;
+
+    case OPT_M:
+    case OPT_MM:
+      /* When doing dependencies with -M or -MM, suppress normal
+        preprocessed output, but still do -dM etc. as software
+        depends on this.  Preprocessed output does occur if -MD, -MMD
+        or environment var dependency generation is used.  */
+      cpp_opts->deps.style = (code == OPT_M ? DEPS_SYSTEM: DEPS_USER);
+      flag_no_output = 1;
+      cpp_opts->inhibit_warnings = 1;
+      break;
+
+    case OPT_MD:
+    case OPT_MMD:
+      cpp_opts->deps.style = (code == OPT_MD ? DEPS_SYSTEM: DEPS_USER);
+      deps_file = arg;
+      break;
+
+    case OPT_MF:
+      deps_seen = true;
+      deps_file = arg;
+      break;
+
+    case OPT_MG:
+      deps_seen = true;
+      cpp_opts->deps.missing_files = true;
+      break;
+
+    case OPT_MP:
+      deps_seen = true;
+      cpp_opts->deps.phony_targets = true;
+      break;
+
+    case OPT_MQ:
+    case OPT_MT:
+      deps_seen = true;
+      defer_opt (code, arg);
+      break;
+
     case OPT_P:
-      cpp_opts->no_line_commands = 1;
+      flag_no_line_commands = 1;
+      break;
+
+    case OPT_U:
+      defer_opt (code, arg);
+      break;
+
+    case OPT_Wabi:
+      warn_abi = on;
       break;
 
     case OPT_Wall:
@@ -545,13 +572,14 @@ c_common_decode_option (argc, argv)
       set_Wimplicit (on);
       warn_char_subscripts = on;
       warn_missing_braces = on;
-      warn_multichar = on;     /* Was C++ only.  */
       warn_parentheses = on;
       warn_return_type = on;
       warn_sequence_point = on;        /* Was C only.  */
-      warn_sign_compare = on;  /* Was C++ only.  */
+      if (c_language == clk_cplusplus)
+       warn_sign_compare = on;
       warn_switch = on;
-
+      warn_strict_aliasing = on;
+      
       /* Only warn about unknown pragmas that are not in system
         headers.  */                                        
       warn_unknown_pragmas = on;
@@ -569,7 +597,6 @@ c_common_decode_option (argc, argv)
       else
        {
          /* C++-specific warnings.  */
-         warn_ctor_dtor_privacy = on;
          warn_nonvdtor = on;
          warn_reorder = on;
          warn_nontemplate_friend = on;
@@ -578,6 +605,7 @@ c_common_decode_option (argc, argv)
       cpp_opts->warn_trigraphs = on;
       cpp_opts->warn_comments = on;
       cpp_opts->warn_num_sign_change = on;
+      cpp_opts->warn_multichar = on;   /* Was C++ only.  */
       break;
 
     case OPT_Wbad_function_cast:
@@ -607,13 +635,14 @@ c_common_decode_option (argc, argv)
 
     case OPT_Wdeprecated:
       warn_deprecated = on;
+      cpp_opts->warn_deprecated = on;
       break;
 
     case OPT_Wdiv_by_zero:
       warn_div_by_zero = on;
       break;
 
-    case OPT_Weffcxx:
+    case OPT_Weffc__:
       warn_ecpp = on;
       break;
 
@@ -625,11 +654,8 @@ c_common_decode_option (argc, argv)
       cpp_opts->warnings_are_errors = on;
       break;
 
-    case OPT_Werror_implicit_function_decl:
-      if (!on)
-       result = 0;
-      else
-       mesg_implicit_function_declaration = 2;
+    case OPT_Werror_implicit_function_declaration:
+      mesg_implicit_function_declaration = 2;
       break;
 
     case OPT_Wfloat_equal:
@@ -640,7 +666,7 @@ c_common_decode_option (argc, argv)
       set_Wformat (on);
       break;
 
-    case OPT_Wformat_eq:
+    case OPT_Wformat_:
       set_Wformat (atoi (arg));
       break;
 
@@ -668,7 +694,7 @@ c_common_decode_option (argc, argv)
       set_Wimplicit (on);
       break;
 
-    case OPT_Wimplicit_function_decl:
+    case OPT_Wimplicit_function_declaration:
       mesg_implicit_function_declaration = on;
       break;
 
@@ -680,6 +706,14 @@ c_common_decode_option (argc, argv)
       cpp_opts->warn_import = on;
       break;
 
+    case OPT_Winvalid_offsetof:
+      warn_invalid_offsetof = on;
+      break;
+
+    case OPT_Winvalid_pch:
+      cpp_opts->warn_invalid_pch = on;
+      break;
+
     case OPT_Wlong_long:
       warn_long_long = on;
       break;
@@ -708,7 +742,7 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_Wmultichar:
-      warn_multichar = on;
+      cpp_opts->warn_multichar = on;
       break;
 
     case OPT_Wnested_externs:
@@ -780,10 +814,7 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_Wstrict_prototypes:
-      if (!on && c_language == clk_cplusplus)
-       warning ("-Wno-strict-prototypes is not supported in C++");
-      else
-       warn_strict_prototypes = on;
+      warn_strict_prototypes = on;
       break;
 
     case OPT_Wsynth:
@@ -803,6 +834,10 @@ c_common_decode_option (argc, argv)
       cpp_opts->warn_trigraphs = on;
       break;
 
+    case OPT_Wundeclared_selector:
+      warn_undeclared_selector = on;
+      break;
+
     case OPT_Wundef:
       cpp_opts->warn_undef = on;
       break;
@@ -814,7 +849,7 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_Wunused_macros:
-      cpp_opts->warn_unused_macros = on;
+      warn_unused_macros = on;
       break;
 
     case OPT_Wwrite_strings:
@@ -823,6 +858,13 @@ c_common_decode_option (argc, argv)
       else
        warn_write_strings = on;
       break;
+      
+    case OPT_ansi:
+      if (c_language == clk_c)
+       set_std_c89 (false, true);
+      else
+       set_std_cxx98 (true);
+      break;
 
     case OPT_d:
       handle_OPT_d (arg);
@@ -842,7 +884,7 @@ c_common_decode_option (argc, argv)
     case OPT_fhonor_std:
     case OPT_fhuge_objects:
     case OPT_flabels_ok:
-    case OPT_fname_mangling:
+    case OPT_fname_mangling_version_:
     case OPT_fnew_abi:
     case OPT_fnonnull_objects:
     case OPT_fsquangle:
@@ -850,7 +892,11 @@ c_common_decode_option (argc, argv)
     case OPT_fthis_is_variable:
     case OPT_fvtable_thunks:
     case OPT_fxref:
-      warning ("switch \"%s\" is no longer supported", argv[0]);
+      warning ("switch \"%s\" is no longer supported", option->opt_text);
+      break;
+
+    case OPT_fabi_version_:
+      flag_abi_version = read_integral_parameter (arg, option->opt_text, 1);
       break;
 
     case OPT_faccess_control:
@@ -862,7 +908,7 @@ c_common_decode_option (argc, argv)
       if (on)
        flag_external_templates = true;
     cp_deprecated:
-      warning ("switch \"%s\" is deprecated, please see documentation for details", argv[0]);
+      warning ("switch \"%s\" is deprecated, please see documentation for details", option->opt_text);
       break;
 
     case OPT_fasm:
@@ -881,11 +927,11 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_fdollars_in_identifiers:
-      dollars_in_ident = on;
+      cpp_opts->dollars_in_ident = on;
       break;
 
-    case OPT_fdump:
-      if (!on || !dump_switch_p (argv[0] + strlen ("-f")))
+    case OPT_fdump_:
+      if (!dump_switch_p (option->opt_text + strlen ("f")))
        result = 0;
       break;
 
@@ -942,7 +988,7 @@ c_common_decode_option (argc, argv)
       flag_const_strings = on;
       break;
 
-    case OPT_fconstant_string_class:
+    case OPT_fconstant_string_class_:
       constant_string_class_name = arg;
       break;
 
@@ -962,6 +1008,13 @@ c_common_decode_option (argc, argv)
       flag_external_templates = on;
       goto cp_deprecated;
 
+    case OPT_ffixed_form:
+    case OPT_ffixed_line_length_:
+      /* Fortran front end options ignored when preprocessing only.  */
+      if (flag_preprocess_only)
+        result = -1;
+      break;
+
     case OPT_ffor_scope:
       flag_new_for_scope = on;
       break;
@@ -975,7 +1028,7 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_fhandle_exceptions:
-      warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
+      warning ("-fhandle-exceptions has been renamed -fexceptions (and is now on by default)");
       flag_exceptions = on;
       break;
 
@@ -1011,6 +1064,10 @@ c_common_decode_option (argc, argv)
       flag_optional_diags = on;
       break;
 
+    case OPT_fpch_deps:
+      cpp_opts->restore_pch_deps = on;
+      break;
+
     case OPT_fpermissive:
       flag_permissive = on;
       break;
@@ -1037,11 +1094,7 @@ c_common_decode_option (argc, argv)
       flag_detailed_statistics = on;
       break;
 
-    case OPT_ftabstop:
-      /* Don't recognise -fno-tabstop=.  */
-      if (!on)
-       return 0;
-
+    case OPT_ftabstop_:
       /* It is documented that we silently ignore silly values.  */
        {
          char *endptr;
@@ -1051,8 +1104,8 @@ c_common_decode_option (argc, argv)
        }
       break;
 
-    case OPT_ftemplate_depth:
-      max_tinst_depth = read_integral_parameter (arg, argv[0], 0);
+    case OPT_ftemplate_depth_:
+      max_tinst_depth = read_integral_parameter (arg, option->opt_text, 0);
       break;
 
     case OPT_fvtable_gc:
@@ -1071,15 +1124,57 @@ c_common_decode_option (argc, argv)
       flag_gen_declaration = 1;
       break;
 
+    case OPT_idirafter:
+      add_path (xstrdup (arg), AFTER, 0);
+      break;
+
+    case OPT_imacros:
+    case OPT_include:
+      defer_opt (code, arg);
+      break;
+
+    case OPT_iprefix:
+      iprefix = arg;
+      break;
+
+    case OPT_isysroot:
+      sysroot = arg;
+      break;
+
+    case OPT_isystem:
+      add_path (xstrdup (arg), SYSTEM, 0);
+      break;
+
+    case OPT_iwithprefix:
+      add_prefixed_path (arg, SYSTEM);
+      break;
+
+    case OPT_iwithprefixbefore:
+      add_prefixed_path (arg, BRACKET);
+      break;
+
+    case OPT_lang_asm:
+      cpp_set_lang (parse_in, CLK_ASM);
+      cpp_opts->dollars_in_ident = false;
+      break;
+
+    case OPT_lang_objc:
+      cpp_opts->objc = 1;
+      break;
+
     case OPT_nostdinc:
-      /* No default include directories.  You must specify all
-        include-file directories with -I.  */
-      cpp_opts->no_standard_includes = 1;
+      std_inc = false;
       break;
 
-    case OPT_nostdincplusplus:
-      /* No default C++-specific include directories.  */
-      cpp_opts->no_standard_cplusplus_includes = 1;
+    case OPT_nostdinc__:
+      std_cxx_inc = false;
+      break;
+
+    case OPT_o:
+      if (!out_fname)
+       out_fname = arg;
+      else
+       error ("output filename specified twice");
       break;
 
       /* We need to handle the -pedantic switches here, rather than in
@@ -1097,71 +1192,35 @@ c_common_decode_option (argc, argv)
       print_struct_values = 1;
       break;
 
-    case OPT_std_bad:
-      error ("unknown standard \"%s\"", arg);
+    case OPT_remap:
+      cpp_opts->remap = 1;
       break;
 
-      /* Language standards.  We currently recognize:
-        -std=iso9899:1990      same as -ansi
-        -std=iso9899:199409    ISO C as modified in amend. 1
-        -std=iso9899:1999      ISO C 99
-        -std=c89               same as -std=iso9899:1990
-        -std=c99               same as -std=iso9899:1999
-        -std=gnu89             default, iso9899:1990 + gnu extensions
-        -std=gnu99             iso9899:1999 + gnu extensions
-      */
-
-    case OPT_std_cplusplus98:
+    case OPT_std_c__98:
+    case OPT_std_gnu__98:
+      set_std_cxx98 (code == OPT_std_c__98 /* ISO */);
       break;
 
     case OPT_std_c89:
     case OPT_std_iso9899_1990:
     case OPT_std_iso9899_199409:
-    case OPT_ansi:
-      /* Note: -ansi is used by both the C and C++ front ends.  */
-      if (c_language == clk_c)
-       {
-         flag_no_asm = 1;
-         flag_writable_strings = 0;
-       }
-      flag_isoc94 = (code == OPT_std_iso9899_199409);
-      flag_no_gnu_keywords = 1;
-      flag_no_nonansi_builtin = 1;
-      flag_noniso_default_format_attributes = 0;
-      flag_isoc99 = 0;
-      flag_iso = 1;
+      set_std_c89 (code == OPT_std_iso9899_199409 /* c94 */, true /* ISO */);
+      break;
+
+    case OPT_std_gnu89:
+      set_std_c89 (false /* c94 */, false /* ISO */);
       break;
 
     case OPT_std_c99:
     case OPT_std_c9x:
     case OPT_std_iso9899_1999:
     case OPT_std_iso9899_199x:
-      flag_writable_strings = 0;
-      flag_no_asm = 1;
-      flag_no_nonansi_builtin = 1;
-      flag_noniso_default_format_attributes = 0;
-      flag_isoc99 = 1;
-      flag_isoc94 = 1;
-      flag_iso = 1;
-      break;
-
-    case OPT_std_gnu89:
-      flag_writable_strings = 0;
-      flag_no_asm = 0;
-      flag_no_nonansi_builtin = 0;
-      flag_noniso_default_format_attributes = 1;
-      flag_isoc99 = 0;
-      flag_isoc94 = 0;
+      set_std_c99 (true /* ISO */);
       break;
 
     case OPT_std_gnu99:
     case OPT_std_gnu9x:
-      flag_writable_strings = 0;
-      flag_no_asm = 0;
-      flag_no_nonansi_builtin = 0;
-      flag_noniso_default_format_attributes = 1;
-      flag_isoc99 = 1;
-      flag_isoc94 = 1;
+      set_std_c99 (false /* ISO */);
       break;
 
     case OPT_trigraphs:
@@ -1181,21 +1240,35 @@ c_common_decode_option (argc, argv)
       break;
 
     case OPT_v:
-      cpp_opts->verbose = 1;
+      verbose = true;
       break;
     }
 
- done:
-  if (dup)
-    free (dup);
   return result;
 }
 
 /* Post-switch processing.  */
 bool
-c_common_post_options ()
+c_common_post_options (pfilename)
+     const char **pfilename;
 {
-  cpp_post_options (parse_in);
+  /* Canonicalize the input and output filenames.  */
+  if (in_fname == NULL || !strcmp (in_fname, "-"))
+    in_fname = "";
+
+  if (out_fname == NULL || !strcmp (out_fname, "-"))
+    out_fname = "";
+
+  if (cpp_opts->deps.style == DEPS_NONE)
+    check_deps_environment_vars ();
+
+  handle_deferred_opts ();
+
+  sanitize_cpp_opts ();
+
+  register_include_chains (parse_in, sysroot, iprefix,
+                          std_inc, std_cxx_inc && c_language == clk_cplusplus,
+                          verbose);
 
   flag_inline_trees = 1;
 
@@ -1212,9 +1285,10 @@ c_common_post_options ()
        }
     }
 
-  /* If still "unspecified", make it match -fbounded-pointers.  */
-  if (flag_bounds_check == -1)
-    flag_bounds_check = flag_bounded_pointers;
+  /* -Wextra implies -Wsign-compare, but not if explicitly
+      overridden.  */
+  if (warn_sign_compare == -1)
+    warn_sign_compare = extra_warnings;
 
   /* Special format checking options don't work without -Wformat; warn if
      they are used.  */
@@ -1231,6 +1305,40 @@ c_common_post_options ()
   if (warn_missing_format_attribute && !warn_format)
     warning ("-Wmissing-format-attribute ignored without -Wformat");
 
+  if (flag_preprocess_only)
+    {
+      /* Open the output now.  We must do so even if flag_no_output is
+        on, because there may be other output than from the actual
+        preprocessing (e.g. from -dM).  */
+      if (out_fname[0] == '\0')
+       out_stream = stdout;
+      else
+       out_stream = fopen (out_fname, "w");
+
+      if (out_stream == NULL)
+       {
+         fatal_error ("opening output file %s: %m", out_fname);
+         return false;
+       }
+
+      init_pp_output (out_stream);
+    }
+  else
+    {
+      init_c_lex ();
+
+      /* Yuk.  WTF is this?  I do know ObjC relies on it somewhere.  */
+      input_line = 0;
+    }
+
+  cpp_get_callbacks (parse_in)->file_change = cb_file_change;
+
+  /* NOTE: we use in_fname here, not the one supplied.  */
+  *pfilename = cpp_read_main_file (parse_in, in_fname);
+
+  saved_lineno = input_line;
+  input_line = 0;
+
   /* If an error has occurred in cpplib, note it so we fail
      immediately.  */
   errorcount += cpp_errors (parse_in);
@@ -1238,6 +1346,328 @@ c_common_post_options ()
   return flag_preprocess_only;
 }
 
+/* Front end initialization common to C, ObjC and C++.  */
+bool
+c_common_init ()
+{
+  input_line = saved_lineno;
+
+  /* Set up preprocessor arithmetic.  Must be done after call to
+     c_common_nodes_and_builtins for type nodes to be good.  */
+  cpp_opts->precision = TYPE_PRECISION (intmax_type_node);
+  cpp_opts->char_precision = TYPE_PRECISION (char_type_node);
+  cpp_opts->int_precision = TYPE_PRECISION (integer_type_node);
+  cpp_opts->wchar_precision = TYPE_PRECISION (wchar_type_node);
+  cpp_opts->unsigned_wchar = TREE_UNSIGNED (wchar_type_node);
+  cpp_opts->EBCDIC = TARGET_EBCDIC;
+
+  if (flag_preprocess_only)
+    {
+      finish_options ();
+      preprocess_file (parse_in);
+      return false;
+    }
+
+  /* Has to wait until now so that cpplib has its hash table.  */
+  init_pragma ();
+
+  return true;
+}
+
+/* A thin wrapper around the real parser that initializes the 
+   integrated preprocessor after debug output has been initialized.
+   Also, make sure the start_source_file debug hook gets called for
+   the primary source file.  */
+void
+c_common_parse_file (set_yydebug)
+     int set_yydebug ATTRIBUTE_UNUSED;
+{
+#if YYDEBUG != 0
+  yydebug = set_yydebug;
+#else
+  warning ("YYDEBUG not defined");
+#endif
+
+  (*debug_hooks->start_source_file) (input_line, input_filename);
+  finish_options();
+  pch_init();
+  yyparse ();
+  free_parser_stacks ();
+}
+
+/* Common finish hook for the C, ObjC and C++ front ends.  */
+void
+c_common_finish ()
+{
+  FILE *deps_stream = NULL;
+
+  if (cpp_opts->deps.style != DEPS_NONE)
+    {
+      /* If -M or -MM was seen without -MF, default output to the
+        output stream.  */
+      if (!deps_file)
+       deps_stream = out_stream;
+      else
+       {
+         deps_stream = fopen (deps_file, deps_append ? "a": "w");
+         if (!deps_stream)
+           fatal_error ("opening dependency file %s: %m", deps_file);
+       }
+    }
+
+  /* For performance, avoid tearing down cpplib's internal structures
+     with cpp_destroy ().  */
+  errorcount += cpp_finish (parse_in, deps_stream);
+
+  if (deps_stream && deps_stream != out_stream
+      && (ferror (deps_stream) || fclose (deps_stream)))
+    fatal_error ("closing dependency file %s: %m", deps_file);
+
+  if (out_stream && (ferror (out_stream) || fclose (out_stream)))
+    fatal_error ("when writing output to %s: %m", out_fname);
+}
+
+/* Either of two environment variables can specify output of
+   dependencies.  Their value is either "OUTPUT_FILE" or "OUTPUT_FILE
+   DEPS_TARGET", where OUTPUT_FILE is the file to write deps info to
+   and DEPS_TARGET is the target to mention in the deps.  They also
+   result in dependency information being appended to the output file
+   rather than overwriting it, and like Sun's compiler
+   SUNPRO_DEPENDENCIES suppresses the dependency on the main file.  */
+static void
+check_deps_environment_vars ()
+{
+  char *spec;
+
+  GET_ENVIRONMENT (spec, "DEPENDENCIES_OUTPUT");
+  if (spec)
+    cpp_opts->deps.style = DEPS_USER;
+  else
+    {
+      GET_ENVIRONMENT (spec, "SUNPRO_DEPENDENCIES");
+      if (spec)
+       {
+         cpp_opts->deps.style = DEPS_SYSTEM;
+         cpp_opts->deps.ignore_main_file = true;
+       }
+    }
+
+  if (spec)
+    {
+      /* Find the space before the DEPS_TARGET, if there is one.  */
+      char *s = strchr (spec, ' ');
+      if (s)
+       {
+         /* Let the caller perform MAKE quoting.  */
+         defer_opt (OPT_MT, s + 1);
+         *s = '\0';
+       }
+
+      /* Command line -MF overrides environment variables and default.  */
+      if (!deps_file)
+       deps_file = spec;
+
+      deps_append = 1;
+    }
+}
+
+/* Handle deferred command line switches.  */
+static void
+handle_deferred_opts ()
+{
+  size_t i;
+
+  for (i = 0; i < deferred_count; i++)
+    {
+      struct deferred_opt *opt = &deferred_opts[i];
+
+      if (opt->code == OPT_MT || opt->code == OPT_MQ)
+       cpp_add_dependency_target (parse_in, opt->arg, opt->code == OPT_MQ);
+    }
+}
+
+/* These settings are appropriate for GCC, but not necessarily so for
+   cpplib as a library.  */
+static void
+sanitize_cpp_opts ()
+{
+  /* If we don't know what style of dependencies to output, complain
+     if any other dependency switches have been given.  */
+  if (deps_seen && cpp_opts->deps.style == DEPS_NONE)
+    error ("to generate dependencies you must specify either -M or -MM");
+
+  /* -dM and dependencies suppress normal output; do it here so that
+     the last -d[MDN] switch overrides earlier ones.  */
+  if (flag_dump_macros == 'M')
+    flag_no_output = 1;
+
+  /* Disable -dD, -dN and -dI if normal output is suppressed.  Allow
+     -dM since at least glibc relies on -M -dM to work.  */
+  if (flag_no_output)
+    {
+      if (flag_dump_macros != 'M')
+       flag_dump_macros = 0;
+      flag_dump_includes = 0;
+    }
+
+  cpp_opts->unsigned_char = !flag_signed_char;
+  cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
+
+  /* We want -Wno-long-long to override -pedantic -std=non-c99
+     and/or -Wtraditional, whatever the ordering.  */
+  cpp_opts->warn_long_long
+    = warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);
+}
+
+/* Add include path with a prefix at the front of its name.  */
+static void
+add_prefixed_path (suffix, chain)
+     const char *suffix;
+     size_t chain;
+{
+  char *path;
+  const char *prefix;
+  size_t prefix_len, suffix_len;
+
+  suffix_len = strlen (suffix);
+  prefix     = iprefix ? iprefix : cpp_GCC_INCLUDE_DIR;
+  prefix_len = iprefix ? strlen (iprefix) : cpp_GCC_INCLUDE_DIR_len;
+
+  path = xmalloc (prefix_len + suffix_len + 1);
+  memcpy (path, prefix, prefix_len);
+  memcpy (path + prefix_len, suffix, suffix_len);
+  path[prefix_len + suffix_len] = '\0';
+
+  add_path (path, chain, 0);
+}
+
+/* Handle -D, -U, -A, -imacros, and the first -include.  */
+static void
+finish_options ()
+{
+  if (!cpp_opts->preprocessed)
+    {
+      size_t i;
+
+      cpp_change_file (parse_in, LC_RENAME, _("<built-in>"));
+      cpp_init_builtins (parse_in, flag_hosted);
+      c_cpp_builtins (parse_in);
+      cpp_change_file (parse_in, LC_RENAME, _("<command line>"));
+      for (i = 0; i < deferred_count; i++)
+       {
+         struct deferred_opt *opt = &deferred_opts[i];
+
+         if (opt->code == OPT_D)
+           cpp_define (parse_in, opt->arg);
+         else if (opt->code == OPT_U)
+           cpp_undef (parse_in, opt->arg);
+         else if (opt->code == OPT_A)
+           {
+             if (opt->arg[0] == '-')
+               cpp_unassert (parse_in, opt->arg + 1);
+             else
+               cpp_assert (parse_in, opt->arg);
+           }
+       }
+
+      /* Handle -imacros after -D and -U.  */
+      for (i = 0; i < deferred_count; i++)
+       {
+         struct deferred_opt *opt = &deferred_opts[i];
+
+         if (opt->code == OPT_imacros
+             && cpp_push_include (parse_in, opt->arg))
+           cpp_scan_nooutput (parse_in);
+       }
+    }
+
+  push_command_line_include ();
+}
+
+/* Give CPP the next file given by -include, if any.  */
+static void
+push_command_line_include ()
+{
+  if (cpp_opts->preprocessed)
+    return;
+    
+  while (include_cursor < deferred_count)
+    {
+      struct deferred_opt *opt = &deferred_opts[include_cursor++];
+      
+      if (opt->code == OPT_include && cpp_push_include (parse_in, opt->arg))
+       return;
+    }
+
+  if (include_cursor == deferred_count)
+    {
+      /* Restore the line map from <command line>.  */
+      cpp_change_file (parse_in, LC_RENAME, main_input_filename);
+      /* -Wunused-macros should only warn about macros defined hereafter.  */
+      cpp_opts->warn_unused_macros = warn_unused_macros;
+      include_cursor++;
+    }
+}
+
+/* File change callback.  Has to handle -include files.  */
+static void
+cb_file_change (pfile, new_map)
+     cpp_reader *pfile ATTRIBUTE_UNUSED;
+     const struct line_map *new_map;
+{
+  if (flag_preprocess_only)
+    pp_file_change (new_map);
+  else
+    fe_file_change (new_map);
+
+  if (new_map->reason == LC_LEAVE && MAIN_FILE_P (new_map))
+    push_command_line_include ();
+}
+
+/* Set the C 89 standard (with 1994 amendments if C94, without GNU
+   extensions if ISO).  There is no concept of gnu94.  */
+static void
+set_std_c89 (c94, iso)
+     int c94, iso;
+{
+  cpp_set_lang (parse_in, c94 ? CLK_STDC94: iso ? CLK_STDC89: CLK_GNUC89);
+  flag_iso = iso;
+  flag_no_asm = iso;
+  flag_no_gnu_keywords = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_noniso_default_format_attributes = !iso;
+  flag_isoc94 = c94;
+  flag_isoc99 = 0;
+  flag_writable_strings = 0;
+}
+
+/* Set the C 99 standard (without GNU extensions if ISO).  */
+static void
+set_std_c99 (iso)
+     int iso;
+{
+  cpp_set_lang (parse_in, iso ? CLK_STDC99: CLK_GNUC99);
+  flag_no_asm = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_noniso_default_format_attributes = !iso;
+  flag_iso = iso;
+  flag_isoc99 = 1;
+  flag_isoc94 = 1;
+  flag_writable_strings = 0;
+}
+
+/* Set the C++ 98 standard (without GNU extensions if ISO).  */
+static void
+set_std_cxx98 (iso)
+     int iso;
+{
+  cpp_set_lang (parse_in, iso ? CLK_CXX98: CLK_GNUCXX);
+  flag_no_gnu_keywords = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_noniso_default_format_attributes = !iso;
+  flag_iso = iso;
+}
+
 /* Handle setting implicit to ON.  */
 static void
 set_Wimplicit (on)
@@ -1255,7 +1685,7 @@ set_Wimplicit (on)
 }
 
 /* Args to -d specify what to dump.  Silently ignore
-   unrecognised options; they may be aimed at toplev.c.  */
+   unrecognized options; they may be aimed at toplev.c.  */
 static void
 handle_OPT_d (arg)
      const char *arg;
@@ -1265,20 +1695,14 @@ handle_OPT_d (arg)
   while ((c = *arg++) != '\0')
     switch (c)
       {
-      case 'M':
-       cpp_opts->dump_macros = dump_only;
-       break;
-
-      case 'N':
-       cpp_opts->dump_macros = dump_names;
-       break;
-
-      case 'D':
-       cpp_opts->dump_macros = dump_definitions;
+      case 'M':                        /* Dump macros only.  */
+      case 'N':                        /* Dump names.  */
+      case 'D':                        /* Dump definitions.  */
+       flag_dump_macros = c;
        break;
 
       case 'I':
-       cpp_opts->dump_includes = 1;
+       flag_dump_includes = 1;
        break;
       }
 }
@@ -1290,15 +1714,15 @@ write_langs (buf, flags)
      int flags;
 {
   *buf = '\0';
-  if (flags & CL_C_ONLY)
+  if (flags & CL_C)
     strcat (buf, "C");
-  if (flags & CL_OBJC_ONLY)
+  if (flags & CL_OBJC)
     {
       if (*buf)
        strcat (buf, "/");
       strcat (buf, "ObjC");
     }
-  if (flags & CL_CXX_ONLY)
+  if (flags & CL_CXX)
     {
       if (*buf)
        strcat (buf, "/");
@@ -1395,6 +1819,7 @@ Switches:\n\
   fputs (_("\
   -f[no-]preprocessed       Treat the input file as already preprocessed\n\
   -ftabstop=<number>        Distance between tab stops for column reporting\n\
+  -isysroot <dir>           Set <dir> to be the system root directory\n\
   -P                        Do not generate #line directives\n\
   -remap                    Remap file names when including files\n\
   --help                    Display this information\n\