OSDN Git Service

* tree-inline.c (find_builtin_longjmp_call): Save and restore
[pf3gnuchains/gcc-fork.git] / gcc / cpplib.c
index 712b9df..ed2bc95 100644 (file)
@@ -21,6 +21,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "cpplib.h"
 #include "cpphash.h"
@@ -70,11 +72,14 @@ struct pragma_entry
    conditional; IF_COND an opening conditional.  INCL means to treat
    "..." and <...> as q-char and h-char sequences respectively.  IN_I
    means this directive should be handled even if -fpreprocessed is in
-   effect (these are the directives with callback hooks).  */
+   effect (these are the directives with callback hooks).
+
+   EXPAND is set on directives that are always macro-expanded.  */
 #define COND           (1 << 0)
 #define IF_COND                (1 << 1)
 #define INCL           (1 << 2)
 #define IN_I           (1 << 3)
+#define EXPAND         (1 << 4)
 
 /* Defines one #-directive, including how to handle it.  */
 typedef void (*directive_handler) PARAMS ((cpp_reader *));
@@ -93,6 +98,7 @@ struct directive
 static void skip_rest_of_line  PARAMS ((cpp_reader *));
 static void check_eol          PARAMS ((cpp_reader *));
 static void start_directive    PARAMS ((cpp_reader *));
+static void prepare_directive_trad PARAMS ((cpp_reader *));
 static void end_directive      PARAMS ((cpp_reader *, int));
 static void directive_diagnostics
        PARAMS ((cpp_reader *, const directive *, int));
@@ -115,6 +121,11 @@ static struct pragma_entry *lookup_pragma_entry
 static struct pragma_entry *insert_pragma_entry
   PARAMS ((cpp_reader *, struct pragma_entry **, const cpp_hashnode *,
           pragma_cb));
+static int count_registered_pragmas    PARAMS ((struct pragma_entry *));
+static char ** save_registered_pragmas 
+  PARAMS ((struct pragma_entry *, char **));
+static char ** restore_registered_pragmas 
+  PARAMS ((cpp_reader *, struct pragma_entry *, char **));
 static void do_pragma_once     PARAMS ((cpp_reader *));
 static void do_pragma_poison   PARAMS ((cpp_reader *));
 static void do_pragma_system_header    PARAMS ((cpp_reader *));
@@ -141,31 +152,24 @@ static void handle_assertion      PARAMS ((cpp_reader *, const char *, int));
 
 #define DIRECTIVE_TABLE                                                        \
 D(define,      T_DEFINE = 0,   KANDR,     IN_I)           /* 270554 */ \
-D(include,     T_INCLUDE,      KANDR,     INCL)           /*  52262 */ \
+D(include,     T_INCLUDE,      KANDR,     INCL | EXPAND)  /*  52262 */ \
 D(endif,       T_ENDIF,        KANDR,     COND)           /*  45855 */ \
 D(ifdef,       T_IFDEF,        KANDR,     COND | IF_COND) /*  22000 */ \
-D(if,          T_IF,           KANDR,     COND | IF_COND) /*  18162 */ \
+D(if,          T_IF,           KANDR, COND | IF_COND | EXPAND) /*  18162 */ \
 D(else,                T_ELSE,         KANDR,     COND)           /*   9863 */ \
 D(ifndef,      T_IFNDEF,       KANDR,     COND | IF_COND) /*   9675 */ \
 D(undef,       T_UNDEF,        KANDR,     IN_I)           /*   4837 */ \
-D(line,                T_LINE,         KANDR,     0)              /*   2465 */ \
-D(elif,                T_ELIF,         STDC89,    COND)           /*    610 */ \
+D(line,                T_LINE,         KANDR,     EXPAND)         /*   2465 */ \
+D(elif,                T_ELIF,         STDC89,    COND | EXPAND)  /*    610 */ \
 D(error,       T_ERROR,        STDC89,    0)              /*    475 */ \
 D(pragma,      T_PRAGMA,       STDC89,    IN_I)           /*    195 */ \
 D(warning,     T_WARNING,      EXTENSION, 0)              /*     22 */ \
-D(include_next,        T_INCLUDE_NEXT, EXTENSION, INCL)           /*     19 */ \
+D(include_next,        T_INCLUDE_NEXT, EXTENSION, INCL | EXPAND)  /*     19 */ \
 D(ident,       T_IDENT,        EXTENSION, IN_I)           /*     11 */ \
-D(import,      T_IMPORT,       EXTENSION, INCL)           /* 0 ObjC */ \
+D(import,      T_IMPORT,       EXTENSION, INCL | EXPAND)  /* 0 ObjC */ \
 D(assert,      T_ASSERT,       EXTENSION, 0)              /* 0 SVR4 */ \
 D(unassert,    T_UNASSERT,     EXTENSION, 0)              /* 0 SVR4 */ \
-SCCS_ENTRY                                                /* 0 SVR4? */
-
-/* #sccs is not always recognized.  */
-#ifdef SCCS_DIRECTIVE
-# define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION, 0)
-#else
-# define SCCS_ENTRY /* nothing */
-#endif
+D(sccs,                T_SCCS,         EXTENSION, 0)              /* 0 SVR4? */
 
 /* Use the table to generate a series of prototypes, an enum for the
    directive names, and an array of directive handlers.  */
@@ -210,7 +214,7 @@ skip_rest_of_line (pfile)
      cpp_reader *pfile;
 {
   /* Discard all stacked contexts.  */
-  while (pfile->context != &pfile->base_context)
+  while (pfile->context->prev)
     _cpp_pop_context (pfile);
 
   /* Sweep up all tokens remaining on the line.  */
@@ -248,8 +252,16 @@ end_directive (pfile, skip_line)
      cpp_reader *pfile;
      int skip_line;
 {
+  if (CPP_OPTION (pfile, traditional))
+    {
+      /* Revert change of prepare_directive_trad.  */
+      pfile->state.prevent_expansion--;
+
+      if (pfile->directive != &dtable[T_DEFINE])
+       _cpp_remove_overlay (pfile);
+    }
   /* We don't skip for an assembler #.  */
-  if (skip_line)
+  else if (skip_line)
     {
       skip_rest_of_line (pfile);
       if (!pfile->keep_tokens)
@@ -262,11 +274,40 @@ end_directive (pfile, skip_line)
   /* Restore state.  */
   pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
   pfile->state.in_directive = 0;
+  pfile->state.in_expression = 0;
   pfile->state.angled_headers = 0;
   pfile->directive = 0;
 }
 
-/* Output diagnostics for a directive DIR.  INDENTED is non-zero if
+/* Prepare to handle the directive in pfile->directive.  */
+static void
+prepare_directive_trad (pfile)
+     cpp_reader *pfile;
+{
+  if (pfile->directive != &dtable[T_DEFINE])
+    {
+      bool no_expand = (pfile->directive
+                       && ! (pfile->directive->flags & EXPAND));
+      bool was_skipping = pfile->state.skipping;
+
+      pfile->state.skipping = false;
+      pfile->state.in_expression = (pfile->directive == &dtable[T_IF]
+                                   || pfile->directive == &dtable[T_ELIF]);
+      if (no_expand)
+       pfile->state.prevent_expansion++;
+      _cpp_read_logical_line_trad (pfile);
+      if (no_expand)
+       pfile->state.prevent_expansion--;
+      pfile->state.skipping = was_skipping;
+      _cpp_overlay_buffer (pfile, pfile->out.base,
+                          pfile->out.cur - pfile->out.base);
+    }
+
+  /* Stop ISO C from expanding anything.  */
+  pfile->state.prevent_expansion++;
+}
+
+/* Output diagnostics for a directive DIR.  INDENTED is nonzero if
    the '#' was indented.  */
 static void
 directive_diagnostics (pfile, dir, indented)
@@ -302,10 +343,10 @@ directive_diagnostics (pfile, dir, indented)
     }
 }
 
-/* Check if we have a known directive.  INDENTED is non-zero if the
+/* Check if we have a known directive.  INDENTED is nonzero if the
    '#' of the directive was indented.  This function is in this file
    to save unnecessarily exporting dtable etc. to cpplex.c.  Returns
-   non-zero if the line of tokens has been handled, zero if we should
+   nonzero if the line of tokens has been handled, zero if we should
    continue processing the line.  */
 int
 _cpp_handle_directive (pfile, indented)
@@ -330,10 +371,10 @@ _cpp_handle_directive (pfile, indented)
 
   if (dname->type == CPP_NAME)
     {
-      if (dname->val.node->directive_index)
-       dir = &dtable[dname->val.node->directive_index - 1];
+      if (dname->val.node->is_directive)
+       dir = &dtable[dname->val.node->directive_index];
     }
-  /* We do not recognise the # followed by a number extension in
+  /* We do not recognize the # followed by a number extension in
      assembler code.  */
   else if (dname->type == CPP_NUMBER && CPP_OPTION (pfile, lang) != CLK_ASM)
     {
@@ -373,6 +414,7 @@ _cpp_handle_directive (pfile, indented)
             skipping or not, we should lex angle-bracketed headers
             correctly, and maybe output some diagnostics.  */
          pfile->state.angled_headers = dir->flags & INCL;
+         pfile->state.directive_wants_padding = dir->flags & INCL;
          if (! CPP_OPTION (pfile, preprocessed))
            directive_diagnostics (pfile, dir, indented);
          if (pfile->state.skipping && !(dir->flags & COND))
@@ -394,18 +436,12 @@ _cpp_handle_directive (pfile, indented)
                   cpp_token_as_text (pfile, dname));
     }
 
+  pfile->directive = dir;
+  if (CPP_OPTION (pfile, traditional))
+    prepare_directive_trad (pfile);
+
   if (dir)
-    {
-      /* If we are processing a `#define' directive and we have been
-        requested to expand comments into macros, then re-enable
-        saving of comments.  */
-      if (dir == &dtable[T_DEFINE])
-        pfile->state.save_comments =
-          ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
-
-      pfile->directive = dir;
-      (*pfile->directive->handler) (pfile);
-    }
+    (*pfile->directive->handler) (pfile);
   else if (skip == 0)
     _cpp_backup_tokens (pfile, 1);
 
@@ -431,12 +467,19 @@ run_directive (pfile, dir_no, buf, count)
 {
   cpp_push_buffer (pfile, (const uchar *) buf, count,
                   /* from_stage3 */ true, 1);
+  /* Disgusting hack.  */
+  if (dir_no == T_PRAGMA)
+    pfile->buffer->inc = pfile->buffer->prev->inc;
   start_directive (pfile);
   /* We don't want a leading # to be interpreted as a directive.  */
   pfile->buffer->saved_flags = 0;
   pfile->directive = &dtable[dir_no];
+  if (CPP_OPTION (pfile, traditional))
+    prepare_directive_trad (pfile);
   (void) (*pfile->directive->handler) (pfile);
   end_directive (pfile, 1);
+  if (dir_no == T_PRAGMA)
+    pfile->buffer->inc = NULL;
   _cpp_pop_buffer (pfile);
 }
 
@@ -446,7 +489,6 @@ static cpp_hashnode *
 lex_macro_node (pfile)
      cpp_reader *pfile;
 {
-  cpp_hashnode *node;
   const cpp_token *token = _cpp_lex_token (pfile);
 
   /* The token immediately after #define must be an identifier.  That
@@ -454,44 +496,29 @@ lex_macro_node (pfile)
      In C++, it may not be any of the "named operators" either,
      per C++98 [lex.digraph], [lex.key].
      Finally, the identifier may not have been poisoned.  (In that case
-     the lexer has issued the error message for us.)
-
-     Note that if we're copying comments into macro expansions, we
-     could encounter comment tokens here, so eat them all up first.  */
+     the lexer has issued the error message for us.)  */
 
-  if (! CPP_OPTION (pfile, discard_comments_in_macro_exp))
+  if (token->type == CPP_NAME)
     {
-      while (token->type == CPP_COMMENT)
-       token = _cpp_lex_token (pfile);
-    }
+      cpp_hashnode *node = token->val.node;
 
-  if (token->type != CPP_NAME)
-    {
-      if (token->type == CPP_EOF)
-       cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
-                  pfile->directive->name);
-      else if (token->flags & NAMED_OP)
+      if (node == pfile->spec_nodes.n_defined)
        cpp_error (pfile, DL_ERROR,
-          "\"%s\" cannot be used as a macro name as it is an operator in C++",
-                  NODE_NAME (token->val.node));
-      else
-       cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
-
-      return 0;
-    }
-
-  node = token->val.node;
-  if (node->flags & NODE_POISONED)
-    return 0;
-
-  if (node == pfile->spec_nodes.n_defined)
-    {
-      cpp_error (pfile, DL_ERROR, "\"%s\" cannot be used as a macro name",
-                NODE_NAME (node));
-      return 0;
+                  "\"defined\" cannot be used as a macro name");
+      else if (! (node->flags & NODE_POISONED))
+       return node;
     }
+  else if (token->flags & NAMED_OP)
+    cpp_error (pfile, DL_ERROR,
+       "\"%s\" cannot be used as a macro name as it is an operator in C++",
+              NODE_NAME (token->val.node));
+  else if (token->type == CPP_EOF)
+    cpp_error (pfile, DL_ERROR, "no macro name given in #%s directive",
+              pfile->directive->name);
+  else
+    cpp_error (pfile, DL_ERROR, "macro names must be identifiers");
 
-  return node;
+  return NULL;
 }
 
 /* Process a #define directive.  Most work is done in cppmacro.c.  */
@@ -503,6 +530,11 @@ do_define (pfile)
 
   if (node)
     {
+      /* If we have been requested to expand comments into macros,
+        then re-enable saving of comments.  */
+      pfile->state.save_comments =
+       ! CPP_OPTION (pfile, discard_comments_in_macro_exp);
+
       if (_cpp_create_definition (pfile, node))
        if (pfile->cb.define)
          (*pfile->cb.define) (pfile, pfile->directive_line, node);
@@ -514,7 +546,7 @@ static void
 do_undef (pfile)
      cpp_reader *pfile;
 {
-  cpp_hashnode *node = lex_macro_node (pfile);  
+  cpp_hashnode *node = lex_macro_node (pfile);
 
   /* 6.10.3.5 paragraph 2: [#undef] is ignored if the specified identifier
      is not currently defined as a macro name.  */
@@ -526,6 +558,9 @@ do_undef (pfile)
       if (node->flags & NODE_WARN)
        cpp_error (pfile, DL_WARNING, "undefining \"%s\"", NODE_NAME (node));
 
+      if (CPP_OPTION (pfile, warn_unused_macros))
+       _cpp_warn_if_unused_macro (pfile, node, NULL);
+
       _cpp_free_definition (node);
     }
   check_eol (pfile);
@@ -548,7 +583,7 @@ glue_header_name (pfile)
   buffer = (unsigned char *) xmalloc (capacity);
   for (;;)
     {
-      token = cpp_get_token (pfile);
+      token = get_token_no_padding (pfile);
 
       if (token->type == CPP_GREATER || token->type == CPP_EOF)
        break;
@@ -600,7 +635,7 @@ parse_include (pfile)
     dir = pfile->directive->name;
 
   /* Allow macro expansion.  */
-  header = cpp_get_token (pfile);
+  header = get_token_no_padding (pfile);
   if (header->type != CPP_STRING && header->type != CPP_HEADER_NAME)
     {
       if (header->type != CPP_LESS)
@@ -621,6 +656,7 @@ parse_include (pfile)
       return NULL;
     }
 
+  check_eol (pfile);
   return header;
 }
 
@@ -630,40 +666,25 @@ do_include_common (pfile, type)
      cpp_reader *pfile;
      enum include_type type;
 {
-  const cpp_token *header;
+  const cpp_token *header = parse_include (pfile);
+  if (!header)
+    return;
 
-  /* For #include_next, if this is the primary source file, warn and
-     use the normal search logic.  */
-  if (type == IT_INCLUDE_NEXT && ! pfile->buffer->prev)
-    {
-      cpp_error (pfile, DL_WARNING, "#include_next in primary source file");
-      type = IT_INCLUDE;
-    }
-  else if (type == IT_IMPORT && CPP_OPTION (pfile, warn_import))
+  /* Prevent #include recursion.  */
+  if (pfile->line_maps.depth >= CPP_STACK_MAX)
     {
-      CPP_OPTION (pfile, warn_import) = 0;
-      cpp_error (pfile, DL_WARNING,
-          "#import is obsolete, use an #ifndef wrapper in the header file");
+      cpp_error (pfile, DL_ERROR, "#include nested too deeply");
+      return;
     }
 
-  header = parse_include (pfile);
-  if (header)
-    {
-      /* Prevent #include recursion.  */
-      if (pfile->line_maps.depth >= CPP_STACK_MAX)
-       cpp_error (pfile, DL_FATAL, "#include nested too deeply");
-      else
-       {
-         check_eol (pfile);
-         /* Get out of macro context, if we are.  */
-         skip_rest_of_line (pfile);
-         if (pfile->cb.include)
-           (*pfile->cb.include) (pfile, pfile->directive_line,
-                                 pfile->directive->name, header);
+  /* Get out of macro context, if we are.  */
+  skip_rest_of_line (pfile);
 
-         _cpp_execute_include (pfile, header, type);
-       }
-    }
+  if (pfile->cb.include)
+    (*pfile->cb.include) (pfile, pfile->directive_line,
+                         pfile->directive->name, header);
+
+  _cpp_execute_include (pfile, header, type);
 }
 
 static void
@@ -677,6 +698,13 @@ static void
 do_import (pfile)
      cpp_reader *pfile;
 {
+  if (CPP_OPTION (pfile, warn_import))
+    {
+      CPP_OPTION (pfile, warn_import) = 0;
+      cpp_error (pfile, DL_WARNING,
+   "#import is obsolete, use an #ifndef wrapper in the header file");
+    }
+
   do_include_common (pfile, IT_IMPORT);
 }
 
@@ -684,7 +712,17 @@ static void
 do_include_next (pfile)
      cpp_reader *pfile;
 {
-  do_include_common (pfile, IT_INCLUDE_NEXT);
+  enum include_type type = IT_INCLUDE_NEXT;
+
+  /* If this is the primary source file, warn and use the normal
+     search logic.  */
+  if (! pfile->buffer->prev)
+    {
+      cpp_error (pfile, DL_WARNING,
+                "#include_next in primary source file");
+      type = IT_INCLUDE;
+    }
+  do_include_common (pfile, type);
 }
 
 /* Subroutine of do_linemarker.  Read possible flags after file name.
@@ -726,23 +764,15 @@ dequote_string (pfile, str, len)
   uchar *result = _cpp_unaligned_alloc (pfile, len + 1);
   uchar *dst = result;
   const uchar *limit = str + len;
-  unsigned int c;
-  unsigned HOST_WIDE_INT mask;
+  cppchar_t c;
 
-  /* We need the mask to match the host's 'unsigned char', not the
-     target's.  */
-  if (CHAR_BIT < HOST_BITS_PER_WIDE_INT)
-    mask = ((unsigned HOST_WIDE_INT) 1 << CHAR_BIT) - 1;
-  else
-    mask = ~(unsigned HOST_WIDE_INT)0;
-  
   while (str < limit)
     {
       c = *str++;
       if (c != '\\')
        *dst++ = c;
       else
-       *dst++ = cpp_parse_escape (pfile, (const uchar **)&str, limit, mask);
+       *dst++ = cpp_parse_escape (pfile, &str, limit, 0);
     }
   *dst++ = '\0';
   return result;
@@ -795,7 +825,7 @@ do_line (pfile)
                 "\"%s\" after #line is not a positive integer",
                 cpp_token_as_text (pfile, token));
       return;
-    }      
+    }
 
   if (CPP_PEDANTIC (pfile) && (new_lineno == 0 || new_lineno > cap))
     cpp_error (pfile, DL_PEDWARN, "line number out of range");
@@ -847,7 +877,7 @@ do_linemarker (pfile)
       cpp_error (pfile, DL_ERROR, "\"%s\" after # is not a positive integer",
                 cpp_token_as_text (pfile, token));
       return;
-    }      
+    }
 
   token = cpp_get_token (pfile);
   if (token->type == CPP_STRING)
@@ -1057,7 +1087,6 @@ _cpp_init_internal_pragmas (pfile)
      cpp_reader *pfile;
 {
   /* Pragmas in the global namespace.  */
-  cpp_register_pragma (pfile, 0, "poison", do_pragma_poison);
   cpp_register_pragma (pfile, 0, "once", do_pragma_once);
 
   /* New GCC-specific pragmas should be put in the GCC namespace.  */
@@ -1066,6 +1095,85 @@ _cpp_init_internal_pragmas (pfile)
   cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency);
 }
 
+/* Return the number of registered pragmas in PE.  */
+
+static int
+count_registered_pragmas (pe)
+     struct pragma_entry *pe;
+{
+  int ct = 0;
+  for (; pe != NULL; pe = pe->next)
+    {
+      if (pe->is_nspace)
+       ct += count_registered_pragmas (pe->u.space);
+      ct++;
+    }
+  return ct;
+}
+
+/* Save into SD the names of the registered pragmas referenced by PE,
+   and return a pointer to the next free space in SD.  */
+
+static char **
+save_registered_pragmas (pe, sd)
+     struct pragma_entry *pe;
+     char **sd;
+{
+  for (; pe != NULL; pe = pe->next)
+    {
+      if (pe->is_nspace)
+       sd = save_registered_pragmas (pe->u.space, sd);
+      *sd++ = xmemdup (HT_STR (&pe->pragma->ident),
+                      HT_LEN (&pe->pragma->ident),
+                      HT_LEN (&pe->pragma->ident) + 1);
+    }
+  return sd;
+}
+
+/* Return a newly-allocated array which saves the names of the
+   registered pragmas.  */
+
+char **
+_cpp_save_pragma_names (pfile)
+     cpp_reader *pfile;
+{
+  int ct = count_registered_pragmas (pfile->pragmas);
+  char **result = xnewvec (char *, ct);
+  (void) save_registered_pragmas (pfile->pragmas, result);
+  return result;
+}
+
+/* Restore from SD the names of the registered pragmas referenced by PE,
+   and return a pointer to the next unused name in SD.  */
+
+static char **
+restore_registered_pragmas (pfile, pe, sd)
+     cpp_reader *pfile;
+     struct pragma_entry *pe;
+     char **sd;
+{
+  for (; pe != NULL; pe = pe->next)
+    {
+      if (pe->is_nspace)
+       sd = restore_registered_pragmas (pfile, pe->u.space, sd);
+      pe->pragma = cpp_lookup (pfile, U *sd, strlen (*sd));
+      free (*sd);
+      sd++;
+    }
+  return sd;
+}
+
+/* Restore the names of the registered pragmas from SAVED.  */
+
+void
+_cpp_restore_pragma_names (pfile, saved)
+     cpp_reader *pfile;
+     char **saved;
+{
+  (void) restore_registered_pragmas (pfile, pfile->pragmas, saved);
+  free (saved);
+}
+
 /* Pragmata handling.  We handle some, and pass the rest on to the
    front end.  C99 defines three pragmas and says that no macro
    expansion is to be performed on them; whether or not macro
@@ -1120,8 +1228,9 @@ static void
 do_pragma_once (pfile)
      cpp_reader *pfile;
 {
-  cpp_error (pfile, DL_WARNING, "#pragma once is obsolete");
+  if (CPP_OPTION (pfile, warn_deprecated))
+    cpp_error (pfile, DL_WARNING, "#pragma once is obsolete");
+
   if (pfile->buffer->prev == NULL)
     cpp_error (pfile, DL_WARNING, "#pragma once in main file");
   else
@@ -1130,8 +1239,8 @@ do_pragma_once (pfile)
   check_eol (pfile);
 }
 
-/* Handle #pragma poison, to poison one or more identifiers so that
-   the lexer produces a hard error for each subsequent usage.  */
+/* Handle #pragma GCC poison, to poison one or more identifiers so
+   that the lexer produces a hard error for each subsequent usage.  */
 static void
 do_pragma_poison (pfile)
      cpp_reader *pfile;
@@ -1196,7 +1305,7 @@ do_pragma_dependency (pfile)
 {
   const cpp_token *header;
   int ordering;
+
   header = parse_include (pfile);
   if (!header)
     return;
@@ -1271,7 +1380,45 @@ destringize_and_run (pfile, in)
     }
   *dest = '\0';
 
-  run_directive (pfile, T_PRAGMA, result, dest - result);
+  /* Ugh; an awful kludge.  We are really not set up to be lexing
+     tokens when in the middle of a macro expansion.  Use a new
+     context to force cpp_get_token to lex, and so skip_rest_of_line
+     doesn't go beyond the end of the text.  Also, remember the
+     current lexing position so we can return to it later.
+
+     Something like line-at-a-time lexing should remove the need for
+     this.  */
+  {
+    cpp_context *saved_context = pfile->context;
+    cpp_token *saved_cur_token = pfile->cur_token;
+    tokenrun *saved_cur_run = pfile->cur_run;
+
+    pfile->context = xnew (cpp_context);
+    pfile->context->macro = 0;
+    pfile->context->prev = 0;
+    run_directive (pfile, T_PRAGMA, result, dest - result);
+    free (pfile->context);
+    pfile->context = saved_context;
+    pfile->cur_token = saved_cur_token;
+    pfile->cur_run = saved_cur_run;
+    pfile->line--;
+  }
+
+  /* See above comment.  For the moment, we'd like
+
+     token1 _Pragma ("foo") token2
+
+     to be output as
+
+               token1
+               # 7 "file.c"
+               #pragma foo
+               # 7 "file.c"
+                              token2
+
+      Getting the line markers is a little tricky.  */
+  if (pfile->cb.line_change)
+    (*pfile->cb.line_change) (pfile, pfile->cur_token, false);
 }
 
 /* Handle the _Pragma operator.  */
@@ -1281,36 +1428,19 @@ _cpp_do__Pragma (pfile)
 {
   const cpp_token *string = get__Pragma_string (pfile);
 
-  if (!string)
+  if (string)
+    destringize_and_run (pfile, &string->val.str);
+  else
     cpp_error (pfile, DL_ERROR,
               "_Pragma takes a parenthesized string literal");
-  else
-    {
-      /* Ideally, we'd like
-                       token1 _Pragma ("foo") token2
-        to be output as
-                       token1
-                       # 7 "file.c"
-                       #pragma foo
-                       # 7 "file.c"
-                                              token2
-        Getting these correct line markers is a little tricky.  */
-
-      unsigned int orig_line = pfile->line;
-      destringize_and_run (pfile, &string->val.str);
-      pfile->line = orig_line;
-      pfile->buffer->saved_flags = BOL;
-    }
 }
 
-/* Just ignore #sccs, on systems where we define it at all.  */
-#ifdef SCCS_DIRECTIVE
+/* Just ignore #sccs on all systems.  */
 static void
 do_sccs (pfile)
      cpp_reader *pfile ATTRIBUTE_UNUSED;
 {
 }
-#endif
 
 /* Handle #ifdef.  */
 static void
@@ -1324,10 +1454,11 @@ do_ifdef (pfile)
       const cpp_hashnode *node = lex_macro_node (pfile);
 
       if (node)
-       skip = node->type != NT_MACRO;
-
-      if (node)
-       check_eol (pfile);
+       {
+         skip = node->type != NT_MACRO;
+         _cpp_mark_macro_used (node);
+         check_eol (pfile);
+       }
     }
 
   push_conditional (pfile, skip, T_IFDEF, 0);
@@ -1344,11 +1475,13 @@ do_ifndef (pfile)
   if (! pfile->state.skipping)
     {
       node = lex_macro_node (pfile);
-      if (node)
-       skip = node->type == NT_MACRO;
 
       if (node)
-       check_eol (pfile);
+       {
+         skip = node->type == NT_MACRO;
+         _cpp_mark_macro_used (node);
+         check_eol (pfile);
+       }
     }
 
   push_conditional (pfile, skip, T_IFNDEF, node);
@@ -1366,7 +1499,7 @@ do_if (pfile)
   int skip = 1;
 
   if (! pfile->state.skipping)
-    skip = _cpp_parse_expr (pfile) == 0;
+    skip = _cpp_parse_expr (pfile) == false;
 
   push_conditional (pfile, skip, T_IF, pfile->mi_ind_cmacro);
 }
@@ -1647,20 +1780,27 @@ find_answer (node, candidate)
 }
 
 /* Test an assertion within a preprocessor conditional.  Returns
-   non-zero on failure, zero on success.  On success, the result of
-   the test is written into VALUE.  */
+   nonzero on failure, zero on success.  On success, the result of
+   the test is written into VALUE, otherwise the value 0.  */
 int
 _cpp_test_assertion (pfile, value)
      cpp_reader *pfile;
-     int *value;
+     unsigned int *value;
 {
   struct answer *answer;
   cpp_hashnode *node;
 
   node = parse_assertion (pfile, &answer, T_IF);
+
+  /* For recovery, an erroneous assertion expression is handled as a
+     failing assertion.  */
+  *value = 0;
+
   if (node)
     *value = (node->type == NT_ASSERTION &&
              (answer == 0 || *find_answer (node, answer) != 0));
+  else if (pfile->cur_token[-1].type == CPP_EOF)
+    _cpp_backup_tokens (pfile, 1);
 
   /* We don't commit the memory for the answer - it's temporary only.  */
   return node == 0;
@@ -1673,7 +1813,7 @@ do_assert (pfile)
 {
   struct answer *new_answer;
   cpp_hashnode *node;
-  
+
   node = parse_assertion (pfile, &new_answer, T_ASSERT);
   if (node)
     {
@@ -1707,7 +1847,7 @@ do_unassert (pfile)
 {
   cpp_hashnode *node;
   struct answer *answer;
-  
+
   node = parse_assertion (pfile, &answer, T_UNASSERT);
   /* It isn't an error to #unassert something that isn't asserted.  */
   if (node && node->type == NT_ASSERTION)
@@ -1748,7 +1888,7 @@ cpp_define (pfile, str)
   char *buf, *p;
   size_t count;
 
-  /* Copy the entire option so we can modify it. 
+  /* Copy the entire option so we can modify it.
      Change the first "=" in the string to a space.  If there is none,
      tack " 1" on the end.  */
 
@@ -1803,7 +1943,7 @@ cpp_unassert (pfile, str)
      const char *str;
 {
   handle_assertion (pfile, str, T_UNASSERT);
-}  
+}
 
 /* Common code for cpp_assert (-A) and cpp_unassert (-A-).  */
 static void
@@ -1890,7 +2030,7 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof)
 
   new->line_base = new->buf = new->cur = buffer;
   new->rlimit = buffer + len;
-  new->from_stage3 = from_stage3;
+  new->from_stage3 = from_stage3 || CPP_OPTION (pfile, traditional);
   new->prev = pfile->buffer;
   new->return_at_eof = return_at_eof;
   new->saved_flags = BOL;
@@ -1943,7 +2083,7 @@ _cpp_pop_buffer (pfile)
     }
 }
 
-/* Enter all recognised directives in the hash table.  */
+/* Enter all recognized directives in the hash table.  */
 void
 _cpp_init_directives (pfile)
      cpp_reader *pfile;
@@ -1954,6 +2094,7 @@ _cpp_init_directives (pfile)
   for (i = 0; i < (unsigned int) N_DIRECTIVES; i++)
     {
       node = cpp_lookup (pfile, dtable[i].name, dtable[i].length);
-      node->directive_index = i + 1;
+      node->is_directive = 1;
+      node->directive_index = i;
     }
 }