OSDN Git Service

cp:
[pf3gnuchains/gcc-fork.git] / gcc / cpplib.c
index 3138b7e..b6c3805 100644 (file)
@@ -1,6 +1,6 @@
 /* CPP Library. (Directive handling.)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994-95.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -36,7 +36,6 @@ struct answer
 
 /* Stack of conditionals currently in progress
    (including both successful and failing conditionals).  */
-
 struct if_stack
 {
   struct if_stack *next;
@@ -47,6 +46,19 @@ struct if_stack
   int type;                    /* Most recent conditional, for diagnostics.  */
 };
 
+/* Contains a registered pragma or pragma namespace.  */
+typedef void (*pragma_cb) PARAMS ((cpp_reader *));
+struct pragma_entry
+{
+  struct pragma_entry *next;
+  const cpp_hashnode *pragma;  /* Name and length.  */
+  int is_nspace;
+  union {
+    pragma_cb handler;
+    struct pragma_entry *space;
+  } u;
+};
+
 /* Values for the origin field of struct directive.  KANDR directives
    come from traditional (K&R) C.  STDC89 directives come from the
    1989 C standard.  EXTENSION directives are extensions.  */
@@ -96,14 +108,18 @@ static int  strtoul_for_line       PARAMS ((const U_CHAR *, unsigned int,
 static void do_diagnostic      PARAMS ((cpp_reader *, enum error_type, int));
 static cpp_hashnode *lex_macro_node    PARAMS ((cpp_reader *));
 static void do_include_common  PARAMS ((cpp_reader *, enum include_type));
+static struct pragma_entry *lookup_pragma_entry
+  PARAMS ((struct pragma_entry *, const cpp_hashnode *pragma));
+static struct pragma_entry *insert_pragma_entry
+  PARAMS ((cpp_reader *, struct pragma_entry **, const cpp_hashnode *,
+          pragma_cb));
 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 *));
 static void do_pragma_dependency       PARAMS ((cpp_reader *));
 static const cpp_token *get_token_no_padding PARAMS ((cpp_reader *));
 static const cpp_token *get__Pragma_string PARAMS ((cpp_reader *));
-static unsigned char *destringize      PARAMS ((const cpp_string *,
-                                                unsigned int *));
+static void destringize_and_run PARAMS ((cpp_reader *, const cpp_string *));
 static int parse_answer PARAMS ((cpp_reader *, struct answer **, int));
 static cpp_hashnode *parse_assertion PARAMS ((cpp_reader *, struct answer **,
                                              int));
@@ -246,7 +262,6 @@ end_directive (pfile, skip_line)
 
 /* Output diagnostics for a directive DIR.  INDENTED is non-zero if
    the '#' was indented.  */
-
 static void
 directive_diagnostics (pfile, dir, indented)
      cpp_reader *pfile;
@@ -272,7 +287,7 @@ directive_diagnostics (pfile, dir, indented)
         compilers, directives added by C89 must have their #
         indented, and directives present in traditional C must not.
         This is true even of directives in skipped conditional
-        blocks.  */
+        blocks.  #elif cannot be used at all.  */
       if (CPP_WTRADITIONAL (pfile))
        {
          if (dir == &dtable[T_ELIF])
@@ -294,7 +309,6 @@ directive_diagnostics (pfile, dir, indented)
    to save unnecessarily exporting dtable etc. to cpplex.c.  Returns
    non-zero if the line of tokens has been handled, zero if we should
    continue processing the line.  */
-
 int
 _cpp_handle_directive (pfile, indented)
      cpp_reader *pfile;
@@ -302,8 +316,17 @@ _cpp_handle_directive (pfile, indented)
 {
   const directive *dir = 0;
   const cpp_token *dname;
+  bool was_parsing_args = pfile->state.parsing_args;
   int skip = 1;
 
+  if (was_parsing_args)
+    {
+      if (CPP_OPTION (pfile, pedantic))
+       cpp_pedwarn (pfile,
+            "embedding a directive within macro arguments is not portable");
+      pfile->state.parsing_args = 0;
+      pfile->state.prevent_expansion = 0;
+    }
   start_directive (pfile);
   dname = _cpp_lex_token (pfile);
 
@@ -335,7 +358,7 @@ _cpp_handle_directive (pfile, indented)
         does not cause '#define foo bar' to get executed when
         compiled with -save-temps, we recognize directives in
         -fpreprocessed mode only if the # is in column 1.  cppmacro.c
-        puts a space in fron of any '#' at the start of a macro.  */
+        puts a space in front of any '#' at the start of a macro.  */
       if (CPP_OPTION (pfile, preprocessed)
          && (indented || !(dir->flags & IN_I)))
        {
@@ -379,6 +402,13 @@ _cpp_handle_directive (pfile, indented)
     _cpp_backup_tokens (pfile, 1);
 
   end_directive (pfile, skip);
+  if (was_parsing_args)
+    {
+      /* Restore state when within macro args.  */
+      pfile->state.parsing_args = 2;
+      pfile->state.prevent_expansion = 1;
+      pfile->buffer->saved_flags |= PREV_WHITE;
+    }
   return skip;
 }
 
@@ -462,7 +492,7 @@ do_define (pfile)
     }
 }
 
-/* Handle #undef.  Marks the identifier NT_VOID in the hash table.  */
+/* Handle #undef.  Mark the identifier NT_VOID in the hash table.  */
 static void
 do_undef (pfile)
      cpp_reader *pfile;
@@ -493,13 +523,12 @@ glue_header_name (pfile)
 {
   cpp_token *header = NULL;
   const cpp_token *token;
-  unsigned char *dest;
-  size_t len;
+  unsigned char *buffer;
+  size_t len, total_len = 0, capacity = 1024;
 
   /* To avoid lexed tokens overwriting our glued name, we can only
      allocate from the string pool once we've lexed everything.  */
-
-  dest = BUFF_FRONT (pfile->u_buff);
+  buffer = (unsigned char *) xmalloc (capacity);
   for (;;)
     {
       token = cpp_get_token (pfile);
@@ -507,34 +536,35 @@ glue_header_name (pfile)
       if (token->type == CPP_GREATER || token->type == CPP_EOF)
        break;
 
-      /* + 1 for terminating NUL.  */
-      len = cpp_token_len (token) + 1;
-      if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < len)
+      len = cpp_token_len (token);
+      if (total_len + len > capacity)
        {
-         size_t len_so_far = dest - BUFF_FRONT (pfile->u_buff);
-         _cpp_extend_buff (pfile, &pfile->u_buff, len);
-         dest = BUFF_FRONT (pfile->u_buff) + len_so_far;
+         capacity = (capacity + len) * 2;
+         buffer = (unsigned char *) xrealloc (buffer, capacity);
        }
 
       if (token->flags & PREV_WHITE)
-       *dest++ = ' ';
+       buffer[total_len++] = ' ';
 
-      dest = cpp_spell_token (pfile, token, dest);
+      total_len = cpp_spell_token (pfile, token, &buffer[total_len]) - buffer;
     }
 
   if (token->type == CPP_EOF)
     cpp_error (pfile, "missing terminating > character");
   else
     {
+      unsigned char *token_mem = _cpp_unaligned_alloc (pfile, total_len + 1);
+      memcpy (token_mem, buffer, total_len);
+      token_mem[total_len] = '\0';
+
       header = _cpp_temp_token (pfile);
       header->type = CPP_HEADER_NAME;
       header->flags = 0;
-      header->val.str.len = dest - BUFF_FRONT (pfile->u_buff);
-      header->val.str.text = BUFF_FRONT (pfile->u_buff);
-      *dest++ = '\0';
-      BUFF_FRONT (pfile->u_buff) = dest;
+      header->val.str.len = total_len;
+      header->val.str.text = token_mem;
     }
 
+  free ((PTR) buffer);
   return header;
 }
 
@@ -642,7 +672,6 @@ do_include_next (pfile)
 /* Subroutine of do_line.  Read possible flags after file name.  LAST
    is the last flag seen; 0 if this is the first flag. Return the flag
    if it is valid, 0 at the end of the directive. Otherwise complain.  */
-
 static unsigned int
 read_flag (pfile, last)
      cpp_reader *pfile;
@@ -692,7 +721,6 @@ strtoul_for_line (str, len, nump)
 /* Interpret #line command.
    Note that the filename string (if any) is treated as if it were an
    include filename.  That means no escape handling.  */
-
 static void
 do_line (pfile)
      cpp_reader *pfile;
@@ -773,7 +801,7 @@ do_line (pfile)
 
 /* Arrange the file_change callback.  pfile->line has changed to
    FILE_LINE of TO_FILE, for reason REASON.  SYSP is 1 for a system
-   header, 2 for a sytem header that needs to be extern "C" protected,
+   header, 2 for a system header that needs to be extern "C" protected,
    and zero otherwise.  */
 void
 _cpp_do_file_change (pfile, reason, to_file, file_line, sysp)
@@ -790,11 +818,8 @@ _cpp_do_file_change (pfile, reason, to_file, file_line, sysp)
     (*pfile->cb.file_change) (pfile, pfile->map);
 }
 
-/*
- * Report a warning or error detected by the program we are
- * processing.  Use the directive's tokens in the error message.
- */
-
+/* Report a warning or error detected by the program we are
+   processing.  Use the directive's tokens in the error message.  */
 static void
 do_diagnostic (pfile, code, print_dir)
      cpp_reader *pfile;
@@ -827,7 +852,6 @@ do_warning (pfile)
 }
 
 /* Report program identification.  */
-
 static void
 do_ident (pfile)
      cpp_reader *pfile;
@@ -842,149 +866,140 @@ do_ident (pfile)
   check_eol (pfile);
 }
 
-/* Pragmata handling.  We handle some of these, 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
-   expansion happens for other pragmas is implementation defined.
-   This implementation never macro-expands the text after #pragma.  */
-
-/* Sub-handlers for the pragmas needing treatment here.
-   They return 1 if the token buffer is to be popped, 0 if not.  */
-typedef void (*pragma_cb) PARAMS ((cpp_reader *));
-struct pragma_entry
+/* Lookup a PRAGMA name in a singly-linked CHAIN.  Returns the
+   matching entry, or NULL if none is found.  The returned entry could
+   be the start of a namespace chain, or a pragma.  */
+static struct pragma_entry *
+lookup_pragma_entry (chain, pragma)
+     struct pragma_entry *chain;
+     const cpp_hashnode *pragma;
 {
-  struct pragma_entry *next;
-  const char *name;
-  size_t len;
-  int isnspace;
-  union {
-    pragma_cb handler;
-    struct pragma_entry *space;
-  } u;
-};
+  while (chain && chain->pragma != pragma)
+    chain = chain->next;
 
-void
-cpp_register_pragma (pfile, space, name, handler)
+  return chain;
+}
+
+/* Create and insert a pragma entry for NAME at the beginning of a
+   singly-linked CHAIN.  If handler is NULL, it is a namespace,
+   otherwise it is a pragma and its handler.  */
+static struct pragma_entry *
+insert_pragma_entry (pfile, chain, pragma, handler)
      cpp_reader *pfile;
-     const char *space;
-     const char *name;
+     struct pragma_entry **chain;
+     const cpp_hashnode *pragma;
      pragma_cb handler;
 {
-  struct pragma_entry **x, *new;
-  size_t len;
-
-  x = &pfile->pragmas;
-  if (space)
-    {
-      struct pragma_entry *p = pfile->pragmas;
-      len = strlen (space);
-      while (p)
-       {
-         if (p->isnspace && p->len == len && !memcmp (p->name, space, len))
-           {
-             x = &p->u.space;
-             goto found;
-           }
-         p = p->next;
-       }
-      cpp_ice (pfile, "unknown #pragma namespace %s", space);
-      return;
-    }
+  struct pragma_entry *new;
 
- found:
   new = (struct pragma_entry *)
     _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
-  new->name = name;
-  new->len = strlen (name);
-  new->isnspace = 0;
-  new->u.handler = handler;
+  new->pragma = pragma;
+  if (handler)
+    {
+      new->is_nspace = 0;
+      new->u.handler = handler;
+    }
+  else
+    {
+      new->is_nspace = 1;
+      new->u.space = NULL;
+    }
 
-  new->next = *x;
-  *x = new;
+  new->next = *chain;
+  *chain = new;
+  return new;
 }
 
+/* Register a pragma NAME in namespace SPACE.  If SPACE is null, it
+   goes in the global namespace.  HANDLER is the handler it will call,
+   which must be non-NULL.  */
 void
-cpp_register_pragma_space (pfile, space)
+cpp_register_pragma (pfile, space, name, handler)
      cpp_reader *pfile;
      const char *space;
+     const char *name;
+     pragma_cb handler;
 {
-  struct pragma_entry *new;
-  const struct pragma_entry *p = pfile->pragmas;
-  size_t len = strlen (space);
+  struct pragma_entry **chain = &pfile->pragmas;
+  struct pragma_entry *entry;
+  const cpp_hashnode *node;
+
+  if (!handler)
+    abort ();
 
-  while (p)
+  if (space)
     {
-      if (p->isnspace && p->len == len && !memcmp (p->name, space, len))
-       /* Multiple different callers are allowed to register the same
-          namespace.  */
-       return;
-      p = p->next;
+      node = cpp_lookup (pfile, U space, strlen (space));
+      entry = lookup_pragma_entry (*chain, node);
+      if (!entry)
+       entry = insert_pragma_entry (pfile, chain, node, NULL);
+      else if (!entry->is_nspace)
+       goto clash;
+      chain = &entry->u.space;
     }
 
-  new = (struct pragma_entry *)
-    _cpp_aligned_alloc (pfile, sizeof (struct pragma_entry));
-  new->name = space;
-  new->len = len;
-  new->isnspace = 1;
-  new->u.space = 0;
-
-  new->next = pfile->pragmas;
-  pfile->pragmas = new;
+  /* Check for duplicates.  */
+  node = cpp_lookup (pfile, U name, strlen (name));
+  entry = lookup_pragma_entry (*chain, node);
+  if (entry)
+    {
+      if (entry->is_nspace)
+       clash:
+       cpp_ice (pfile,
+                "registering \"%s\" as both a pragma and a pragma namespace",
+                NODE_NAME (node));
+      else if (space)
+       cpp_ice (pfile, "#pragma %s %s is already registered", space, name);
+      else
+       cpp_ice (pfile, "#pragma %s is already registered", name);
+    }
+  else
+    insert_pragma_entry (pfile, chain, node, handler);
 }
-  
+
+/* Register the pragmas the preprocessor itself handles.  */
 void
 _cpp_init_internal_pragmas (pfile)
      cpp_reader *pfile;
 {
-  /* top level */
+  /* Pragmas in the global namespace.  */
   cpp_register_pragma (pfile, 0, "poison", do_pragma_poison);
   cpp_register_pragma (pfile, 0, "once", do_pragma_once);
 
-  /* GCC namespace */
-  cpp_register_pragma_space (pfile, "GCC");
-
+  /* New GCC-specific pragmas should be put in the GCC namespace.  */
   cpp_register_pragma (pfile, "GCC", "poison", do_pragma_poison);
   cpp_register_pragma (pfile, "GCC", "system_header", do_pragma_system_header);
   cpp_register_pragma (pfile, "GCC", "dependency", do_pragma_dependency);
 }
 
+/* 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
+   expansion happens for other pragmas is implementation defined.
+   This implementation never macro-expands the text after #pragma.  */
 static void
 do_pragma (pfile)
      cpp_reader *pfile;
 {
-  pragma_cb handler = NULL;
-  const struct pragma_entry *p;
+  const struct pragma_entry *p = NULL;
   const cpp_token *token;
-  unsigned int count = 0;
+  unsigned int count = 1;
 
-  p = pfile->pragmas;
   pfile->state.prevent_expansion++;
 
- new_space:
-  count++;
   token = cpp_get_token (pfile);
   if (token->type == CPP_NAME)
     {
-      const cpp_hashnode *node = token->val.node;
-      size_t len = NODE_LEN (node);
-
-      while (p)
+      p = lookup_pragma_entry (pfile->pragmas, token->val.node);
+      if (p && p->is_nspace)
        {
-         if (strlen (p->name) == len
-             && !memcmp (p->name, NODE_NAME (node), len))
-           {
-             if (p->isnspace)
-               {
-                 p = p->u.space;
-                 goto new_space;
-               }
-             else
-               {
-                 handler = p->u.handler;
-                 break;
-               }
-           }
-         p = p->next;
+         count = 2;
+         token = cpp_get_token (pfile);
+         if (token->type == CPP_NAME)
+           p = lookup_pragma_entry (p->u.space, token->val.node);
+         else
+           p = NULL;
        }
     }
 
@@ -996,16 +1011,18 @@ do_pragma (pfile)
   if (pfile->cb.line_change)
     (*pfile->cb.line_change)(pfile, token, 1);
 
-  if (handler)
-    (*handler) (pfile);
+  if (p)
+    (*p->u.handler) (pfile);
   else if (pfile->cb.def_pragma)
     {
       _cpp_backup_tokens (pfile, count);
       (*pfile->cb.def_pragma) (pfile, pfile->directive_line);
     }
+
   pfile->state.prevent_expansion--;
 }
 
+/* Handle #pragma once.  */
 static void
 do_pragma_once (pfile)
      cpp_reader *pfile;
@@ -1020,12 +1037,12 @@ 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.  */
 static void
 do_pragma_poison (pfile)
      cpp_reader *pfile;
 {
-  /* Poison these symbols so that all subsequent usage produces an
-     error message.  */
   const cpp_token *tok;
   cpp_hashnode *hp;
 
@@ -1139,17 +1156,17 @@ get__Pragma_string (pfile)
   return string;
 }
 
-/* Returns a malloced buffer containing a destringized cpp_string by
-   removing the first \ of \" and \\ sequences.  */
-static unsigned char *
-destringize (in, len)
+/* Destringize IN into a temporary buffer, by removing the first \ of
+   \" and \\ sequences, and process the result as a #pragma directive.  */
+static void
+destringize_and_run (pfile, in)
+     cpp_reader *pfile;
      const cpp_string *in;
-     unsigned int *len;
 {
   const unsigned char *src, *limit;
-  unsigned char *dest, *result;
+  char *dest, *result;
 
-  dest = result = (unsigned char *) xmalloc (in->len);
+  dest = result = alloca (in->len + 1);
   for (src = in->text, limit = src + in->len; src < limit;)
     {
       /* We know there is a character following the backslash.  */
@@ -1157,18 +1174,17 @@ destringize (in, len)
        src++;
       *dest++ = *src++;
     }
+  *dest = '\0';
 
-  *len = dest - result;
-  return result;
+  run_directive (pfile, T_PRAGMA, result, dest - result);
 }
 
+/* Handle the _Pragma operator.  */
 void
 _cpp_do__Pragma (pfile)
      cpp_reader *pfile;
 {
   const cpp_token *string = get__Pragma_string (pfile);
-  unsigned char *buffer;
-  unsigned int len;
 
   if (!string)
     cpp_error (pfile, "_Pragma takes a parenthesized string literal");
@@ -1185,9 +1201,7 @@ _cpp_do__Pragma (pfile)
         Getting these correct line markers is a little tricky.  */
 
       unsigned int orig_line = pfile->line;
-      buffer = destringize (&string->val.str, &len);
-      run_directive (pfile, T_PRAGMA, (char *) buffer, len);
-      free ((PTR) buffer);
+      destringize_and_run (pfile, &string->val.str);
       pfile->line = orig_line;
       pfile->buffer->saved_flags = BOL;
     }
@@ -1202,6 +1216,7 @@ do_sccs (pfile)
 }
 #endif
 
+/* Handle #ifdef.  */
 static void
 do_ifdef (pfile)
      cpp_reader *pfile;
@@ -1222,6 +1237,7 @@ do_ifdef (pfile)
   push_conditional (pfile, skip, T_IFDEF, 0);
 }
 
+/* Handle #ifndef.  */
 static void
 do_ifndef (pfile)
      cpp_reader *pfile;
@@ -1247,7 +1263,6 @@ do_ifndef (pfile)
    optimisations.  If macro expansion occurs in the expression, we
    cannot treat it as a controlling conditional, since the expansion
    could change in the future.  That is handled by cpp_get_token.  */
-
 static void
 do_if (pfile)
      cpp_reader *pfile;
@@ -1263,7 +1278,6 @@ do_if (pfile)
 /* Flip skipping state if appropriate and continue without changing
    if_stack; this is so that the error message for missing #endif's
    etc. will point to the original #if.  */
-
 static void
 do_else (pfile)
      cpp_reader *pfile;
@@ -1296,9 +1310,8 @@ do_else (pfile)
     }
 }
 
-/* handle a #elif directive by not changing if_stack either.  see the
+/* Handle a #elif directive by not changing if_stack either.  See the
    comment above do_else.  */
-
 static void
 do_elif (pfile)
      cpp_reader *pfile;
@@ -1335,7 +1348,6 @@ do_elif (pfile)
 }
 
 /* #endif pops the if stack and resets pfile->state.skipping.  */
-
 static void
 do_endif (pfile)
      cpp_reader *pfile;
@@ -1364,10 +1376,10 @@ do_endif (pfile)
     }
 }
 
-/* Push an if_stack entry and set pfile->state.skipping accordingly.
-   If this is a #if or #ifndef, CMACRO is a potentially controlling
-   macro - we need to check here that we are at the top of the file.  */
-
+/* Push an if_stack entry for a preprocessor conditional, and set
+   pfile->state.skipping to SKIP.  If TYPE indicates the conditional
+   is #if or #ifndef, CMACRO is a potentially controlling macro, and
+   we need to check here that we are at the top of the file.  */
 static void
 push_conditional (pfile, skip, type, cmacro)
      cpp_reader *pfile;
@@ -1394,10 +1406,10 @@ push_conditional (pfile, skip, type, cmacro)
   buffer->if_stack = ifs;
 }
 
-/* Read the tokens of the answer into the macro pool.  Only commit the
-   memory if we intend it as permanent storage, i.e. the #assert case.
-   Returns 0 on success.  */
-
+/* Read the tokens of the answer into the macro pool, in a directive
+   of type TYPE.  Only commit the memory if we intend it as permanent
+   storage, i.e. the #assert case.  Returns 0 on success, and sets
+   ANSWERP to point to the answer.  */
 static int
 parse_answer (pfile, answerp, type)
      cpp_reader *pfile;
@@ -1474,9 +1486,9 @@ parse_answer (pfile, answerp, type)
   return 0;
 }
 
-/* Parses an assertion, returning a pointer to the hash node of the
-   predicate, or 0 on error.  If an answer was supplied, it is placed
-   in ANSWERP, otherwise it is set to 0.  */
+/* Parses an assertion directive of type TYPE, returning a pointer to
+   the hash node of the predicate, or 0 on error.  If an answer was
+   supplied, it is placed in ANSWERP, otherwise it is set to 0.  */
 static cpp_hashnode *
 parse_assertion (pfile, answerp, type)
      cpp_reader *pfile;
@@ -1510,7 +1522,7 @@ parse_assertion (pfile, answerp, type)
   return result;
 }
 
-/* Returns a pointer to the pointer to the answer in the answer chain,
+/* Returns a pointer to the pointer to CANDIDATE in the answer chain,
    or a pointer to NULL if the answer is not in the chain.  */
 static struct answer **
 find_answer (node, candidate)
@@ -1558,6 +1570,7 @@ _cpp_test_assertion (pfile, value)
   return node == 0;
 }
 
+/* Handle #assert.  */
 static void
 do_assert (pfile)
      cpp_reader *pfile;
@@ -1590,6 +1603,7 @@ do_assert (pfile)
     }
 }
 
+/* Handle #unassert.  */
 static void
 do_unassert (pfile)
      cpp_reader *pfile;
@@ -1629,7 +1643,6 @@ do_unassert (pfile)
    If STR is just an identifier, define it with value 1.
    If STR has anything after the identifier, then it should
    be identifier=definition.  */
-
 void
 cpp_define (pfile, str)
      cpp_reader *pfile;
@@ -1642,9 +1655,8 @@ cpp_define (pfile, str)
      Change the first "=" in the string to a space.  If there is none,
      tack " 1" on the end.  */
 
-  /* Length including the null.  */  
   count = strlen (str);
-  buf = (char *) alloca (count + 2);
+  buf = (char *) alloca (count + 3);
   memcpy (buf, str, count);
 
   p = strchr (str, '=');
@@ -1655,6 +1667,7 @@ cpp_define (pfile, str)
       buf[count++] = ' ';
       buf[count++] = '1';
     }
+  buf[count] = '\0';
 
   run_directive (pfile, T_DEFINE, buf, count);
 }
@@ -1709,11 +1722,12 @@ handle_assertion (pfile, str, type)
     {
       /* Copy the entire option so we can modify it.  Change the first
         "=" in the string to a '(', and tack a ')' on the end.  */
-      char *buf = (char *) alloca (count + 1);
+      char *buf = (char *) alloca (count + 2);
 
       memcpy (buf, str, count);
       buf[p - str] = '(';
       buf[count++] = ')';
+      buf[count] = '\0';
       str = buf;
     }
 
@@ -1779,10 +1793,6 @@ cpp_push_buffer (pfile, buffer, len, from_stage3, return_at_eof)
 
   new->line_base = new->buf = new->cur = buffer;
   new->rlimit = buffer + len;
-
-  /* No read ahead or extra char initially.  */
-  new->read_ahead = EOF;
-  new->extra_char = EOF;
   new->from_stage3 = from_stage3;
   new->prev = pfile->buffer;
   new->return_at_eof = return_at_eof;
@@ -1802,6 +1812,7 @@ _cpp_pop_buffer (pfile)
 {
   cpp_buffer *buffer = pfile->buffer;
   struct if_stack *ifs;
+  bool pushed = false;
 
   /* Walk back up the conditional stack till we reach its level at
      entry to this file, issuing error messages.  */
@@ -1816,11 +1827,13 @@ _cpp_pop_buffer (pfile)
   pfile->buffer = buffer->prev;
 
   if (buffer->inc)
-    _cpp_pop_file_buffer (pfile, buffer->inc);
+    pushed = _cpp_pop_file_buffer (pfile, buffer->inc);
 
-  obstack_free (&pfile->buffer_ob, buffer);
+  if (!pushed)
+    obstack_free (&pfile->buffer_ob, buffer);
 }
 
+/* Enter all recognised directives in the hash table.  */
 void
 _cpp_init_directives (pfile)
      cpp_reader *pfile;
@@ -1828,7 +1841,6 @@ _cpp_init_directives (pfile)
   unsigned int i;
   cpp_hashnode *node;
 
-  /* Register the directives.  */
   for (i = 0; i < (unsigned int) N_DIRECTIVES; i++)
     {
       node = cpp_lookup (pfile, dtable[i].name, dtable[i].length);