OSDN Git Service

* java/util/Hashtable.java (Enumerator): Ensure that if
[pf3gnuchains/gcc-fork.git] / gcc / cppinit.c
index 61f72b4..2cf7461 100644 (file)
@@ -38,7 +38,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* Windows does not natively support inodes, and neither does MSDOS.
    Cygwin's emulation can generate non-unique inodes, so don't use it.
-   VMS has non-numeric inodes. */
+   VMS has non-numeric inodes.  */
 #ifdef VMS
 # define INO_T_EQ(a, b) (!memcmp (&(a), &(b), sizeof (a)))
 #else
@@ -100,14 +100,14 @@ static void init_library          PARAMS ((void));
 static void init_builtins              PARAMS ((cpp_reader *));
 static void append_include_chain       PARAMS ((cpp_reader *,
                                                 char *, int, int));
-struct search_path * remove_dup_dir    PARAMS ((cpp_reader *,
+static struct search_path * remove_dup_dir     PARAMS ((cpp_reader *,
                                                 struct search_path *));
-struct search_path * remove_dup_dirs PARAMS ((cpp_reader *,
+static struct search_path * remove_dup_dirs PARAMS ((cpp_reader *,
                                                 struct search_path *));
 static void merge_include_chains       PARAMS ((cpp_reader *));
-static void do_includes                        PARAMS ((cpp_reader *,
-                                                struct pending_option *,
-                                                int));
+static bool push_include               PARAMS ((cpp_reader *,
+                                                struct pending_option *));
+static void free_chain                 PARAMS ((struct pending_option *));
 static void set_lang                   PARAMS ((cpp_reader *, enum c_lang));
 static void init_dependency_output     PARAMS ((cpp_reader *));
 static void init_standard_includes     PARAMS ((cpp_reader *));
@@ -197,8 +197,8 @@ path_include (pfile, list, path)
   while (1);
 }
 
-/* Append DIR to include path PATH.  DIR must be permanently allocated
-   and writable. */
+/* Append DIR to include path PATH.  DIR must be allocated on the
+   heap; this routine takes responsibility for freeing it.  */
 static void
 append_include_chain (pfile, dir, path, cxx_aware)
      cpp_reader *pfile;
@@ -211,20 +211,28 @@ append_include_chain (pfile, dir, path, cxx_aware)
   struct stat st;
   unsigned int len;
 
+  if (*dir == '\0')
+    {
+      free (dir);
+      dir = xstrdup (".");
+    }
   _cpp_simplify_pathname (dir);
+
   if (stat (dir, &st))
     {
-      /* Dirs that don't exist are silently ignored. */
+      /* Dirs that don't exist are silently ignored.  */
       if (errno != ENOENT)
        cpp_notice_from_errno (pfile, dir);
       else if (CPP_OPTION (pfile, verbose))
        fprintf (stderr, _("ignoring nonexistent directory \"%s\"\n"), dir);
+      free (dir);
       return;
     }
 
   if (!S_ISDIR (st.st_mode))
     {
       cpp_notice (pfile, "%s: Not a directory", dir);
+      free (dir);
       return;
     }
 
@@ -239,7 +247,7 @@ append_include_chain (pfile, dir, path, cxx_aware)
   new->dev  = st.st_dev;
   /* Both systm and after include file lists should be treated as system
      include files since these two lists are really just a concatenation
-     of one "system" list. */
+     of one "system" list.  */
   if (path == SYSTEM || path == AFTER)
 #ifdef NO_IMPLICIT_EXTERN_C
     new->sysp = 1;
@@ -262,7 +270,7 @@ append_include_chain (pfile, dir, path, cxx_aware)
 /* Handle a duplicated include path.  PREV is the link in the chain
    before the duplicate.  The duplicate is removed from the chain and
    freed.  Returns PREV.  */
-struct search_path *
+static struct search_path *
 remove_dup_dir (pfile, prev)
      cpp_reader *pfile;
      struct search_path *prev;
@@ -283,7 +291,7 @@ remove_dup_dir (pfile, prev)
    chain, or NULL if the chain is empty.  This algorithm is quadratic
    in the number of -I switches, which is acceptable since there
    aren't usually that many of them.  */
-struct search_path *
+static struct search_path *
 remove_dup_dirs (pfile, head)
      cpp_reader *pfile;
      struct search_path *head;
@@ -295,6 +303,19 @@ remove_dup_dirs (pfile, head)
       for (other = head; other != cur; other = other->next)
         if (INO_T_EQ (cur->ino, other->ino) && cur->dev == other->dev)
          {
+           if (cur->sysp && !other->sysp)
+             {
+               cpp_warning (pfile,
+                            "changing search order for system directory \"%s\"",
+                            cur->name);
+               if (strcmp (cur->name, other->name))
+                 cpp_warning (pfile, 
+                              "  as it is the same as non-system directory \"%s\"",
+                              other->name);
+               else
+                 cpp_warning (pfile, 
+                              "  as it has already been specified as a non-system directory");
+             }
            cur = remove_dup_dir (pfile, prev);
            break;
          }
@@ -360,7 +381,7 @@ merge_include_chains (pfile)
        brack = remove_dup_dir (pfile, qtail);
     }
   else
-      quote = brack;
+    quote = brack;
 
   CPP_OPTION (pfile, quote_include) = quote;
   CPP_OPTION (pfile, bracket_include) = brack;
@@ -368,85 +389,51 @@ merge_include_chains (pfile)
 
 /* Sets internal flags correctly for a given language, and defines
    macros if necessary.  */
+
+struct lang_flags
+{
+  char c99;
+  char objc;
+  char cplusplus;
+  char extended_numbers;
+  char trigraphs;
+  char dollars_in_ident;
+  char cplusplus_comments;
+  char digraphs;
+};
+
+/* ??? Enable $ in identifiers in assembly? */
+static const struct lang_flags lang_defaults[] =
+{ /*              c99 objc c++ xnum trig dollar c++comm digr  */
+  /* GNUC89 */  { 0,  0,   0,  1,   0,   1,     1,      1     },
+  /* GNUC99 */  { 1,  0,   0,  1,   0,   1,     1,      1     },
+  /* STDC89 */  { 0,  0,   0,  0,   1,   0,     0,      0     },
+  /* STDC94 */  { 0,  0,   0,  0,   1,   0,     0,      1     },
+  /* STDC99 */  { 1,  0,   0,  1,   1,   0,     1,      1     },
+  /* GNUCXX */  { 0,  0,   1,  1,   0,   1,     1,      1     },
+  /* CXX98  */  { 0,  0,   1,  1,   1,   0,     1,      1     },
+  /* OBJC   */  { 0,  1,   0,  1,   0,   1,     1,      1     },
+  /* OBJCXX */  { 0,  1,   1,  1,   0,   1,     1,      1     },
+  /* ASM    */  { 0,  0,   0,  1,   0,   0,     1,      0     }
+};
+
 static void
 set_lang (pfile, lang)
      cpp_reader *pfile;
      enum c_lang lang;
 {
-  /* Defaults.  */
+  const struct lang_flags *l = &lang_defaults[(int) lang];
+  
   CPP_OPTION (pfile, lang) = lang;
-  CPP_OPTION (pfile, objc) = 0;
-  CPP_OPTION (pfile, cplusplus) = 0;
-  CPP_OPTION (pfile, extended_numbers) = 1; /* Allowed in GNU C and C99.  */
-
-  switch (lang)
-    {
-      /* GNU C.  */
-    case CLK_GNUC99:
-      CPP_OPTION (pfile, trigraphs) = 0;
-      CPP_OPTION (pfile, dollars_in_ident) = 1;
-      CPP_OPTION (pfile, cplusplus_comments) = 1;
-      CPP_OPTION (pfile, digraphs) = 1;
-      CPP_OPTION (pfile, c99) = 1;
-      break;
-    case CLK_GNUC89:
-      CPP_OPTION (pfile, trigraphs) = 0;
-      CPP_OPTION (pfile, dollars_in_ident) = 1;
-      CPP_OPTION (pfile, cplusplus_comments) = 1;
-      CPP_OPTION (pfile, digraphs) = 1;
-      CPP_OPTION (pfile, c99) = 0;
-      break;
-
-      /* ISO C.  */
-    case CLK_STDC94:
-    case CLK_STDC89:
-      CPP_OPTION (pfile, trigraphs) = 1;
-      CPP_OPTION (pfile, dollars_in_ident) = 0;
-      CPP_OPTION (pfile, cplusplus_comments) = 0;
-      CPP_OPTION (pfile, digraphs) = lang == CLK_STDC94;
-      CPP_OPTION (pfile, c99) = 0;
-      CPP_OPTION (pfile, extended_numbers) = 0;
-      break;
-    case CLK_STDC99:
-      CPP_OPTION (pfile, trigraphs) = 1;
-      CPP_OPTION (pfile, dollars_in_ident) = 0;
-      CPP_OPTION (pfile, cplusplus_comments) = 1;
-      CPP_OPTION (pfile, digraphs) = 1;
-      CPP_OPTION (pfile, c99) = 1;
-      break;
-
-      /* Objective C.  */
-    case CLK_OBJCXX:
-      CPP_OPTION (pfile, cplusplus) = 1;
-    case CLK_OBJC:
-      CPP_OPTION (pfile, trigraphs) = 0;
-      CPP_OPTION (pfile, dollars_in_ident) = 1;
-      CPP_OPTION (pfile, cplusplus_comments) = 1;
-      CPP_OPTION (pfile, digraphs) = 1;
-      CPP_OPTION (pfile, c99) = 0;
-      CPP_OPTION (pfile, objc) = 1;
-      break;
-
-      /* C++.  */
-    case CLK_GNUCXX:
-    case CLK_CXX98:
-      CPP_OPTION (pfile, cplusplus) = 1;
-      CPP_OPTION (pfile, trigraphs) = lang == CLK_CXX98;
-      CPP_OPTION (pfile, dollars_in_ident) = lang == CLK_GNUCXX;
-      CPP_OPTION (pfile, cplusplus_comments) = 1;
-      CPP_OPTION (pfile, digraphs) = 1;
-      CPP_OPTION (pfile, c99) = 0;
-      break;
 
-      /* Assembler.  */
-    case CLK_ASM:
-      CPP_OPTION (pfile, trigraphs) = 0;
-      CPP_OPTION (pfile, dollars_in_ident) = 0;        /* Maybe not?  */
-      CPP_OPTION (pfile, cplusplus_comments) = 1;
-      CPP_OPTION (pfile, digraphs) = 0; 
-      CPP_OPTION (pfile, c99) = 0;
-      break;
-    }
+  CPP_OPTION (pfile, c99)               = l->c99;
+  CPP_OPTION (pfile, objc)              = l->objc;
+  CPP_OPTION (pfile, cplusplus)                 = l->cplusplus;
+  CPP_OPTION (pfile, extended_numbers)  = l->extended_numbers;
+  CPP_OPTION (pfile, trigraphs)                 = l->trigraphs;
+  CPP_OPTION (pfile, dollars_in_ident)  = l->dollars_in_ident;
+  CPP_OPTION (pfile, cplusplus_comments) = l->cplusplus_comments;
+  CPP_OPTION (pfile, digraphs)          = l->digraphs;
 }
 
 #ifdef HOST_EBCDIC
@@ -487,9 +474,10 @@ init_library ()
     }
 }
 
-/* Initialize a cpp_reader structure. */
+/* Initialize a cpp_reader structure.  */
 cpp_reader *
-cpp_create_reader (lang)
+cpp_create_reader (table, lang)
+     hash_table *table;
      enum c_lang lang;
 {
   struct spec_nodes *s;
@@ -514,12 +502,20 @@ cpp_create_reader (lang)
      be needed.  */
   pfile->deps = deps_init ();
 
+  /* Initialise the line map.  */
+  init_line_maps (&pfile->line_maps);
+
   /* Initialize lexer state.  */
   pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
 
   /* Indicate date and time not yet calculated.  */
   pfile->date.type = CPP_EOF;
 
+  /* Create a token buffer for the lexer.  */
+  _cpp_init_tokenrun (&pfile->base_run, 250);
+  pfile->cur_run = &pfile->base_run;
+  pfile->cur_token = pfile->base_run.base;
+
   /* Initialise the base context.  */
   pfile->context = &pfile->base_context;
   pfile->base_context.macro = 0;
@@ -534,8 +530,13 @@ cpp_create_reader (lang)
   /* Macro pool initially 8K.  Aligned, permanent pool.  */
   _cpp_init_pool (&pfile->macro_pool, 8 * 1024, 0, 0);
 
-  _cpp_init_hashtable (pfile);
-  _cpp_init_stacks (pfile);
+  /* Initialise the buffer obstack.  */
+  gcc_obstack_init (&pfile->buffer_ob);
+
+  /* Initialise the hashtable.  */
+  _cpp_init_hashtable (pfile, table);
+
+  _cpp_init_directives (pfile);
   _cpp_init_includes (pfile);
   _cpp_init_internal_pragmas (pfile);
 
@@ -565,7 +566,7 @@ cpp_destroy (pfile)
   cpp_context *context, *contextn;
 
   while (CPP_BUFFER (pfile) != NULL)
-    cpp_pop_buffer (pfile);
+    _cpp_pop_buffer (pfile);
 
   if (pfile->macro_buffer)
     {
@@ -575,12 +576,10 @@ cpp_destroy (pfile)
     }
 
   deps_free (pfile->deps);
+  obstack_free (&pfile->buffer_ob, 0);
 
+  _cpp_destroy_hashtable (pfile);
   _cpp_cleanup_includes (pfile);
-  _cpp_cleanup_stacks (pfile);
-  _cpp_cleanup_hashtable (pfile);
-
-  _cpp_free_lookaheads (pfile);
 
   _cpp_free_pool (&pfile->ident_pool);
   _cpp_free_pool (&pfile->macro_pool);
@@ -599,6 +598,8 @@ cpp_destroy (pfile)
       free (context);
     }
 
+  free_line_maps (&pfile->line_maps);
+
   result = pfile->errors;
   free (pfile);
 
@@ -823,7 +824,7 @@ init_standard_includes (pfile)
   if (specd_prefix != 0 && cpp_GCC_INCLUDE_DIR_len)
     {
       /* Remove the `include' from /usr/local/lib/gcc.../include.
-        GCC_INCLUDE_DIR will always end in /include. */
+        GCC_INCLUDE_DIR will always end in /include.  */
       int default_len = cpp_GCC_INCLUDE_DIR_len;
       char *default_prefix = (char *) alloca (default_len + 1);
       int specd_len = strlen (specd_prefix);
@@ -864,32 +865,44 @@ init_standard_includes (pfile)
          || (CPP_OPTION (pfile, cplusplus)
              && !CPP_OPTION (pfile, no_standard_cplusplus_includes)))
        {
-         char *str = xstrdup (update_path (p->fname, p->component));
+         char *str = update_path (p->fname, p->component);
          append_include_chain (pfile, str, SYSTEM, p->cxx_aware);
        }
     }
 }
 
-/* Handles -imacro and -include from the command line.  */
-static void
-do_includes (pfile, p, scan)
+/* Pushes a -imacro and -include file given on the command line onto
+   the buffer stack.  Returns non-zero if successful.  */
+static bool
+push_include (pfile, p)
      cpp_reader *pfile;
      struct pending_option *p;
-     int scan;
 {
-  while (p)
+  cpp_token header;
+
+  /* Later: maybe update this to use the #include "" search path
+     if cpp_read_file fails.  */
+  header.type = CPP_STRING;
+  header.val.str.text = (const unsigned char *) p->arg;
+  header.val.str.len = strlen (p->arg);
+  /* Make the command line directive take up a line.  */
+  pfile->lexer_pos.line = pfile->lexer_pos.output_line = ++pfile->line;
+
+  return _cpp_execute_include (pfile, &header, IT_CMDLINE);
+}
+
+/* Frees a pending_option chain.  */
+static void
+free_chain (head)
+     struct pending_option *head;
+{
+  struct pending_option *next;
+
+  while (head)
     {
-      struct pending_option *q;
-
-      /* Don't handle if -fpreprocessed.  Later: maybe update this to
-        use the #include "" search path if cpp_read_file fails.  */
-      if (CPP_OPTION (pfile, preprocessed))
-       cpp_error (pfile, "-include and -imacros cannot be used with -fpreprocessed");
-      else if (_cpp_read_file (pfile, p->arg) && scan)
-       cpp_scan_buffer_nooutput (pfile, 0);
-      q = p->next;
-      free (p);
-      p = q;
+      next = head->next;
+      free (head);
+      head = next;
     }
 }
 
@@ -901,8 +914,6 @@ cpp_start_read (pfile, fname)
      cpp_reader *pfile;
      const char *fname;
 {
-  struct pending_option *p, *q;
-
   /* Set up the include search path now.  */
   if (! CPP_OPTION (pfile, no_standard_includes))
     init_standard_includes (pfile);
@@ -932,36 +943,84 @@ cpp_start_read (pfile, fname)
   if (!_cpp_read_file (pfile, fname))
     return 0;
 
-  /* If already preprocessed, don't install __LINE__, etc., and ignore
-     command line definitions and assertions.  Handle -U's, -D's and
-     -A's in the order they were seen.  */
-  if (! CPP_OPTION (pfile, preprocessed))
-    init_builtins (pfile);
+  /* Set this after cpp_post_options so the client can change the
+     option if it wishes, and after stacking the main file so we don't
+     trace the main file.  */
+  pfile->line_maps.trace_includes = CPP_OPTION (pfile, print_include_names);
 
-  p = CPP_OPTION (pfile, pending)->directive_head;
-  while (p)
+  /* Install builtins and process command line macros etc. in the order
+     they appeared, but only if not already preprocessed.  */
+  if (! CPP_OPTION (pfile, preprocessed))
     {
-      if (! CPP_OPTION (pfile, preprocessed))
+      struct pending_option *p;
+
+      _cpp_do_file_change (pfile, LC_RENAME, _("<builtin>"), 1, 0);
+      init_builtins (pfile);
+      _cpp_do_file_change (pfile, LC_RENAME, _("<command line>"), 1, 0);
+      for (p = CPP_OPTION (pfile, pending)->directive_head; p; p = p->next)
        (*p->handler) (pfile, p->arg);
-      q = p->next;
-      free (p);
-      p = q;
+
+      /* Scan -imacros files after command line defines, but before
+        files given with -include.  */
+      while ((p = CPP_OPTION (pfile, pending)->imacros_head) != NULL)
+       {
+         if (push_include (pfile, p))
+           {
+             pfile->buffer->return_at_eof = true;
+             cpp_scan_nooutput (pfile);
+           }
+         CPP_OPTION (pfile, pending)->imacros_head = p->next;
+         free (p);
+       }
     }
 
-  pfile->done_initializing = 1;
+  free_chain (CPP_OPTION (pfile, pending)->directive_head);
+  _cpp_push_next_buffer (pfile);
 
-  /* The -imacros files can be scanned now, but the -include files
-     have to be pushed onto the buffer stack and processed later,
-     otherwise cppmain.c won't see the tokens.  include_head was built
-     up as a stack, and popping this stack onto the buffer stack means
-     we preserve the order of the command line.  */
-  do_includes (pfile, CPP_OPTION (pfile, pending)->imacros_head, 1);
-  do_includes (pfile, CPP_OPTION (pfile, pending)->include_head, 0);
+  return 1;
+}
 
-  free (CPP_OPTION (pfile, pending));
-  CPP_OPTION (pfile, pending) = NULL;
+/* Called to push the next buffer on the stack given by -include.  If
+   there are none, free the pending structure and restore the line map
+   for the main file.  */
+bool
+_cpp_push_next_buffer (pfile)
+     cpp_reader *pfile;
+{
+  bool pushed = false;
+
+  /* This is't pretty; we'd rather not be relying on this as a boolean
+     for reverting the line map.  Further, we only free the chains in
+     this conditional, so an early call to cpp_finish / cpp_destroy
+     will leak that memory.  */
+  if (CPP_OPTION (pfile, pending)
+      && CPP_OPTION (pfile, pending)->imacros_head == NULL)
+    {
+      while (!pushed)
+       {
+         struct pending_option *p = CPP_OPTION (pfile, pending)->include_head;
 
-  return 1;
+         if (p == NULL)
+           break;
+         if (! CPP_OPTION (pfile, preprocessed))
+           pushed = push_include (pfile, p);
+         CPP_OPTION (pfile, pending)->include_head = p->next;
+         free (p);
+       }
+
+      if (!pushed)
+       {
+         free (CPP_OPTION (pfile, pending));
+         CPP_OPTION (pfile, pending) = NULL;
+
+         /* Restore the line map for the main file.  */
+         if (! CPP_OPTION (pfile, preprocessed))
+           _cpp_do_file_change (pfile, LC_RENAME,
+                                pfile->line_maps.maps[0].to_file, 1, 0);
+       }
+    }
+
+  return pushed;
 }
 
 /* Use mkdeps.c to output dependency information.  */
@@ -971,7 +1030,8 @@ output_deps (pfile)
 {
   /* Stream on which to print the dependency information.  */
   FILE *deps_stream = 0;
-  const char *deps_mode = CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
+  const char *const deps_mode =
+    CPP_OPTION (pfile, print_deps_append) ? "a" : "w";
 
   if (CPP_OPTION (pfile, deps_file) == 0)
     deps_stream = stdout;
@@ -1006,12 +1066,13 @@ void
 cpp_finish (pfile)
      cpp_reader *pfile;
 {
-  if (CPP_BUFFER (pfile))
-    {
-      cpp_ice (pfile, "buffers still stacked in cpp_finish");
-      while (CPP_BUFFER (pfile))
-       cpp_pop_buffer (pfile);
-    }
+  /* cpplex.c leaves the final buffer on the stack.  This it so that
+     it returns an unending stream of CPP_EOFs to the client.  If we
+     popped the buffer, we'd derefence a NULL buffer pointer and
+     segfault.  It's nice to allow the client to do worry-free excess
+     cpp_get_token calls.  */
+  while (pfile->buffer)
+    _cpp_pop_buffer (pfile);
 
   /* Don't write the deps file if preprocessing has failed.  */
   if (CPP_OPTION (pfile, print_deps) && pfile->errors == 0)
@@ -1408,7 +1469,7 @@ cpp_handle_option (pfile, argc, argv)
          CPP_OPTION (pfile, no_standard_includes) = 1;
          break;
        case OPT_nostdincplusplus:
-         /* -nostdinc++ causes no default C++-specific include directories. */
+         /* -nostdinc++ causes no default C++-specific include directories.  */
          CPP_OPTION (pfile, no_standard_cplusplus_includes) = 1;
          break;
        case OPT_o:
@@ -1496,15 +1557,7 @@ cpp_handle_option (pfile, argc, argv)
 
              if (arg[1] == '\0')
                {
-                 struct pending_option *o1, *o2;
-
-                 o1 = pend->directive_head;
-                 while (o1)
-                   {
-                     o2 = o1->next;
-                     free (o1);
-                     o1 = o2;
-                   }
+                 free_chain (pend->directive_head);
                  pend->directive_head = NULL;
                  pend->directive_tail = NULL;
                }
@@ -1549,18 +1602,6 @@ cpp_handle_option (pfile, argc, argv)
          append_include_chain (pfile, xstrdup (arg), SYSTEM, 0);
          break;
        case OPT_include:
-         {
-           struct pending_option *o = (struct pending_option *)
-             xmalloc (sizeof (struct pending_option));
-           o->arg = arg;
-
-           /* This list has to be built in reverse order so that
-              when cpp_start_read pushes all the -include files onto
-              the buffer stack, they will be scanned in forward order.  */
-           o->next = pend->include_head;
-           pend->include_head = o;
-         }
-         break;
        case OPT_imacros:
          {
            struct pending_option *o = (struct pending_option *)
@@ -1568,7 +1609,10 @@ cpp_handle_option (pfile, argc, argv)
            o->arg = arg;
            o->next = NULL;
 
-           APPEND (pend, imacros, o);
+           if (opt_code == OPT_include)
+             APPEND (pend, include, o);
+           else
+             APPEND (pend, imacros, o);
          }
          break;
        case OPT_iwithprefix:
@@ -1705,10 +1749,15 @@ cpp_post_options (pfile)
   if (CPP_OPTION (pfile, cplusplus))
     CPP_OPTION (pfile, warn_traditional) = 0;
 
-  /* Set this if it hasn't been set already. */
+  /* Set this if it hasn't been set already.  */
   if (CPP_OPTION (pfile, user_label_prefix) == NULL)
     CPP_OPTION (pfile, user_label_prefix) = USER_LABEL_PREFIX;
 
+  /* Permanently disable macro expansion if we are rescanning
+     preprocessed text.  */
+  if (CPP_OPTION (pfile, preprocessed))
+    pfile->state.prevent_expansion = 1;
+
   /* We need to do this after option processing and before
      cpp_start_read, as cppmain.c relies on the options->no_output to
      set its callbacks correctly before calling cpp_start_read.  */
@@ -1769,12 +1818,14 @@ init_dependency_output (pfile)
     }
 
   /* If dependencies go to standard output, or -MG is used, we should
-     suppress output.  The user may be requesting other stuff to
-     stdout, with -dM, -v etc.  We let them shoot themselves in the
-     foot.  */
+     suppress output, including -dM, -dI etc.  */
   if (CPP_OPTION (pfile, deps_file) == 0
       || CPP_OPTION (pfile, print_deps_missing_files))
-    CPP_OPTION (pfile, no_output) = 1;
+    {
+      CPP_OPTION (pfile, no_output) = 1;
+      CPP_OPTION (pfile, dump_macros) = 0;
+      CPP_OPTION (pfile, dump_includes) = 0;
+    }
 }
 
 static void
@@ -1782,7 +1833,7 @@ print_help ()
 {
   fprintf (stderr, _("Usage: %s [switches] input output\n"), progname);
   /* To keep the lines from getting too long for some compilers, limit
-     to about 500 characters (6 lines) per chunk. */
+     to about 500 characters (6 lines) per chunk.  */
   fputs (_("\
 Switches:\n\
   -include <file>           Include the contents of <file> before other files\n\
@@ -1868,6 +1919,7 @@ Switches:\n\
   -dI                       Include #include directives in the output\n\
 "), stdout);
   fputs (_("\
+  -fpreprocessed            Treat the input file as already preprocessed\n\
   -ftabstop=<number>        Distance between tab stops for column reporting\n\
   -P                        Do not generate #line directives\n\
   -$                        Do not allow '$' in identifiers\n\