OSDN Git Service

PR c/5420:
[pf3gnuchains/gcc-fork.git] / gcc / cppmacro.c
index ad4cfed..538c689 100644 (file)
@@ -1,6 +1,6 @@
 /* Part of CPP library.  (Macro and #define handling.)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
 /* Part of CPP library.  (Macro and #define handling.)
    Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
    Written by Per Bothner, 1994.
    Based on CCCP program by Paul Rubin, June 1986
    Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -25,20 +25,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
-#include "intl.h"              /* for _("<command line>") below.  */
 #include "cpplib.h"
 #include "cpphash.h"
 
 struct cpp_macro
 {
   cpp_hashnode **params;       /* Parameters, if any.  */
 #include "cpplib.h"
 #include "cpphash.h"
 
 struct cpp_macro
 {
   cpp_hashnode **params;       /* Parameters, if any.  */
-  cpp_token *expansion;                /* First token of replacement list.   */
+  cpp_token *expansion;                /* First token of replacement list.  */
   unsigned int line;           /* Starting line number.  */
   unsigned int count;          /* Number of tokens in expansion.  */
   unsigned short paramc;       /* Number of parameters.  */
   unsigned int fun_like : 1;   /* If a function-like macro.  */
   unsigned int variadic : 1;   /* If a variadic macro.  */
   unsigned int line;           /* Starting line number.  */
   unsigned int count;          /* Number of tokens in expansion.  */
   unsigned short paramc;       /* Number of parameters.  */
   unsigned int fun_like : 1;   /* If a function-like macro.  */
   unsigned int variadic : 1;   /* If a variadic macro.  */
-  unsigned int disabled : 1;   /* If macro is disabled.  */
   unsigned int syshdr   : 1;   /* If macro defined in system header.  */
 };
 
   unsigned int syshdr   : 1;   /* If macro defined in system header.  */
 };
 
@@ -46,7 +44,7 @@ typedef struct macro_arg macro_arg;
 struct macro_arg
 {
   const cpp_token **first;     /* First token in unexpanded argument.  */
 struct macro_arg
 {
   const cpp_token **first;     /* First token in unexpanded argument.  */
-  const cpp_token **expanded;  /* Macro-expanded argument.   */
+  const cpp_token **expanded;  /* Macro-expanded argument.  */
   const cpp_token *stringified;        /* Stringified argument.  */
   unsigned int count;          /* # of tokens in argument.  */
   unsigned int expanded_count; /* # of tokens in expanded argument.  */
   const cpp_token *stringified;        /* Stringified argument.  */
   unsigned int count;          /* # of tokens in argument.  */
   unsigned int expanded_count; /* # of tokens in expanded argument.  */
@@ -55,11 +53,11 @@ struct macro_arg
 /* Macro expansion.  */
 
 static int enter_macro_context PARAMS ((cpp_reader *, cpp_hashnode *));
 /* Macro expansion.  */
 
 static int enter_macro_context PARAMS ((cpp_reader *, cpp_hashnode *));
-static const cpp_token *builtin_macro PARAMS ((cpp_reader *, cpp_hashnode *));
+static int builtin_macro PARAMS ((cpp_reader *, cpp_hashnode *));
 static void push_token_context
 static void push_token_context
-  PARAMS ((cpp_reader *, cpp_macro *, const cpp_token *, unsigned int));
+  PARAMS ((cpp_reader *, cpp_hashnode *, const cpp_token *, unsigned int));
 static void push_ptoken_context
 static void push_ptoken_context
-  PARAMS ((cpp_reader *, cpp_macro *, _cpp_buff *,
+  PARAMS ((cpp_reader *, cpp_hashnode *, _cpp_buff *,
           const cpp_token **, unsigned int));
 static _cpp_buff *collect_args PARAMS ((cpp_reader *, const cpp_hashnode *));
 static cpp_context *next_context PARAMS ((cpp_reader *));
           const cpp_token **, unsigned int));
 static _cpp_buff *collect_args PARAMS ((cpp_reader *, const cpp_hashnode *));
 static cpp_context *next_context PARAMS ((cpp_reader *));
@@ -71,19 +69,19 @@ static unsigned char *quote_string PARAMS ((unsigned char *,
                                            unsigned int));
 static const cpp_token *new_string_token PARAMS ((cpp_reader *, U_CHAR *,
                                                  unsigned int));
                                            unsigned int));
 static const cpp_token *new_string_token PARAMS ((cpp_reader *, U_CHAR *,
                                                  unsigned int));
-static const cpp_token *new_number_token PARAMS ((cpp_reader *, int));
+static const cpp_token *new_number_token PARAMS ((cpp_reader *, unsigned int));
 static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
 static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
 static const cpp_token *stringify_arg PARAMS ((cpp_reader *, macro_arg *));
 static void paste_all_tokens PARAMS ((cpp_reader *, const cpp_token *));
-static int paste_tokens PARAMS ((cpp_reader *, cpp_token *,
-                                const cpp_token *));
-static int funlike_invocation_p PARAMS ((cpp_reader *, const cpp_hashnode *));
-static void replace_args PARAMS ((cpp_reader *, cpp_macro *, macro_arg *));
+static bool paste_tokens PARAMS ((cpp_reader *, const cpp_token **,
+                                 const cpp_token *));
+static void replace_args PARAMS ((cpp_reader *, cpp_hashnode *, macro_arg *));
+static _cpp_buff *funlike_invocation_p PARAMS ((cpp_reader *, cpp_hashnode *));
 
 /* #define directive parsing and handling.  */
 
 static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
 static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
 
 /* #define directive parsing and handling.  */
 
 static cpp_token *alloc_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
 static cpp_token *lex_expansion_token PARAMS ((cpp_reader *, cpp_macro *));
-static int warn_of_redefinition PARAMS ((cpp_reader *, const cpp_hashnode *,
+static int warn_of_redefinition PARAMS ((const cpp_hashnode *,
                                         const cpp_macro *));
 static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
 static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
                                         const cpp_macro *));
 static int save_parameter PARAMS ((cpp_reader *, cpp_macro *, cpp_hashnode *));
 static int parse_params PARAMS ((cpp_reader *, cpp_macro *));
@@ -113,12 +111,13 @@ new_string_token (pfile, text, len)
 static const cpp_token *
 new_number_token (pfile, number)
      cpp_reader *pfile;
 static const cpp_token *
 new_number_token (pfile, number)
      cpp_reader *pfile;
-     int number;
+     unsigned int number;
 {
   cpp_token *token = _cpp_temp_token (pfile);
 {
   cpp_token *token = _cpp_temp_token (pfile);
-  unsigned char *buf = _cpp_pool_alloc (&pfile->ident_pool, 20);
+  /* 21 bytes holds all NUL-terminated unsigned 64-bit numbers.  */
+  unsigned char *buf = _cpp_unaligned_alloc (pfile, 21);
 
 
-  sprintf ((char *) buf, "%d", number);
+  sprintf ((char *) buf, "%u", number);
   token->type = CPP_NUMBER;
   token->val.str.text = buf;
   token->val.str.len = ustrlen (buf);
   token->type = CPP_NUMBER;
   token->val.str.text = buf;
   token->val.str.len = ustrlen (buf);
@@ -132,17 +131,22 @@ static const char * const monthnames[] =
   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
 
   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
 
-/* Handle builtin macros like __FILE__.  */
-static const cpp_token *
+/* Handle builtin macros like __FILE__, and push the resulting token
+   on the context stack.  Also handles _Pragma, for which no new token
+   is created.  Returns 1 if it generates a new token context, 0 to
+   return the token to the caller.  */
+static int
 builtin_macro (pfile, node)
      cpp_reader *pfile;
      cpp_hashnode *node;
 {
 builtin_macro (pfile, node)
      cpp_reader *pfile;
      cpp_hashnode *node;
 {
+  const cpp_token *result;
+
   switch (node->value.builtin)
     {
     default:
   switch (node->value.builtin)
     {
     default:
-      cpp_ice (pfile, "invalid builtin macro \"%s\"", NODE_NAME (node));
-      return new_number_token (pfile, 1);
+      cpp_ice (pfile, "invalid built-in macro \"%s\"", NODE_NAME (node));
+      return 0;
 
     case BT_FILE:
     case BT_BASE_FILE:
 
     case BT_FILE:
     case BT_BASE_FILE:
@@ -158,31 +162,36 @@ builtin_macro (pfile, node)
 
        name = map->to_file;
        len = strlen (name);
 
        name = map->to_file;
        len = strlen (name);
-       buf = _cpp_pool_alloc (&pfile->ident_pool, len * 4 + 1);
+       buf = _cpp_unaligned_alloc (pfile, len * 4 + 1);
        len = quote_string (buf, (const unsigned char *) name, len) - buf;
 
        len = quote_string (buf, (const unsigned char *) name, len) - buf;
 
-       return new_string_token (pfile, buf, len);
+       result = new_string_token (pfile, buf, len);
       }
       }
-       
+      break;
+
     case BT_INCLUDE_LEVEL:
       /* The line map depth counts the primary source as level 1, but
         historically __INCLUDE_DEPTH__ has called the primary source
         level 0.  */
     case BT_INCLUDE_LEVEL:
       /* The line map depth counts the primary source as level 1, but
         historically __INCLUDE_DEPTH__ has called the primary source
         level 0.  */
-      return new_number_token (pfile, pfile->line_maps.depth - 1);
+      result = new_number_token (pfile, pfile->line_maps.depth - 1);
+      break;
 
     case BT_SPECLINE:
       /* If __LINE__ is embedded in a macro, it must expand to the
         line of the macro's invocation, not its definition.
         Otherwise things like assert() will not work properly.  */
 
     case BT_SPECLINE:
       /* If __LINE__ is embedded in a macro, it must expand to the
         line of the macro's invocation, not its definition.
         Otherwise things like assert() will not work properly.  */
-      return new_number_token (pfile, SOURCE_LINE (pfile->map,
-                                                  pfile->cur_token[-1].line));
+      result = new_number_token (pfile,
+                                SOURCE_LINE (pfile->map,
+                                             pfile->cur_token[-1].line));
+      break;
 
     case BT_STDC:
       {
        int stdc = (!CPP_IN_SYSTEM_HEADER (pfile)
                    || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID);
 
     case BT_STDC:
       {
        int stdc = (!CPP_IN_SYSTEM_HEADER (pfile)
                    || pfile->spec_nodes.n__STRICT_ANSI__->type != NT_VOID);
-       return new_number_token (pfile, stdc);
+       result = new_number_token (pfile, stdc);
       }
       }
+      break;
 
     case BT_DATE:
     case BT_TIME:
 
     case BT_DATE:
     case BT_TIME:
@@ -196,7 +205,7 @@ builtin_macro (pfile, node)
          struct tm *tb = localtime (&tt);
 
          pfile->date.val.str.text =
          struct tm *tb = localtime (&tt);
 
          pfile->date.val.str.text =
-           _cpp_pool_alloc (&pfile->ident_pool, sizeof ("Oct 11 1347"));
+           _cpp_unaligned_alloc (pfile, sizeof ("Oct 11 1347"));
          pfile->date.val.str.len = sizeof ("Oct 11 1347") - 1;
          pfile->date.type = CPP_STRING;
          pfile->date.flags = 0;
          pfile->date.val.str.len = sizeof ("Oct 11 1347") - 1;
          pfile->date.type = CPP_STRING;
          pfile->date.flags = 0;
@@ -204,7 +213,7 @@ builtin_macro (pfile, node)
                   monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
 
          pfile->time.val.str.text =
                   monthnames[tb->tm_mon], tb->tm_mday, tb->tm_year + 1900);
 
          pfile->time.val.str.text =
-           _cpp_pool_alloc (&pfile->ident_pool, sizeof ("12:34:56"));
+           _cpp_unaligned_alloc (pfile, sizeof ("12:34:56"));
          pfile->time.val.str.len = sizeof ("12:34:56") - 1;
          pfile->time.type = CPP_STRING;
          pfile->time.flags = 0;
          pfile->time.val.str.len = sizeof ("12:34:56") - 1;
          pfile->time.type = CPP_STRING;
          pfile->time.flags = 0;
@@ -212,12 +221,29 @@ builtin_macro (pfile, node)
                   tb->tm_hour, tb->tm_min, tb->tm_sec);
        }
 
                   tb->tm_hour, tb->tm_min, tb->tm_sec);
        }
 
-      return node->value.builtin == BT_DATE ? &pfile->date: &pfile->time;
+      if (node->value.builtin == BT_DATE)
+       result = &pfile->date;
+      else
+       result = &pfile->time;
+      break;
+
+    case BT_PRAGMA:
+      /* Don't interpret _Pragma within directives.  The standard is
+         not clear on this, but to me this makes most sense.  */
+      if (pfile->state.in_directive)
+       return 0;
+
+      _cpp_do__Pragma (pfile);
+      return 1;
     }
     }
+
+  push_token_context (pfile, NULL, result, 1);
+  return 1;
 }
 
 }
 
-/* Adds backslashes before all backslashes and double quotes appearing
-   in strings.  Non-printable characters are converted to octal.  */
+/* Copies SRC, of length LEN, to DEST, adding backslashes before all
+   backslashes and double quotes.  Non-printable characters are
+   converted to octal.  DEST must be of sufficient size.  */
 static U_CHAR *
 quote_string (dest, src, len)
      U_CHAR *dest;
 static U_CHAR *
 quote_string (dest, src, len)
      U_CHAR *dest;
@@ -248,24 +274,22 @@ quote_string (dest, src, len)
   return dest;
 }
 
   return dest;
 }
 
-/* Convert a token sequence to a single string token according to the
-   rules of the ISO C #-operator.  */
+/* Convert a token sequence ARG to a single string token according to
+   the rules of the ISO C #-operator.  */
 static const cpp_token *
 stringify_arg (pfile, arg)
      cpp_reader *pfile;
      macro_arg *arg;
 {
 static const cpp_token *
 stringify_arg (pfile, arg)
      cpp_reader *pfile;
      macro_arg *arg;
 {
-  cpp_pool *pool = &pfile->ident_pool;
-  unsigned char *start = POOL_FRONT (pool);
-  unsigned int i, escape_it, total_len = 0, backslash_count = 0;
+  unsigned char *dest = BUFF_FRONT (pfile->u_buff);
+  unsigned int i, escape_it, backslash_count = 0;
   const cpp_token *source = NULL;
   const cpp_token *source = NULL;
+  size_t len;
 
   /* Loop, reading in the argument's tokens.  */
   for (i = 0; i < arg->count; i++)
     {
 
   /* Loop, reading in the argument's tokens.  */
   for (i = 0; i < arg->count; i++)
     {
-      unsigned char *dest;
       const cpp_token *token = arg->first[i];
       const cpp_token *token = arg->first[i];
-      unsigned int len;
 
       if (token->type == CPP_PADDING)
        {
 
       if (token->type == CPP_PADDING)
        {
@@ -277,21 +301,22 @@ stringify_arg (pfile, arg)
       escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
                   || token->type == CPP_CHAR || token->type == CPP_WCHAR);
 
       escape_it = (token->type == CPP_STRING || token->type == CPP_WSTRING
                   || token->type == CPP_CHAR || token->type == CPP_WCHAR);
 
+      /* Room for each char being written in octal, initial space and
+        final NUL.  */
       len = cpp_token_len (token);
       if (escape_it)
       len = cpp_token_len (token);
       if (escape_it)
-       /* Worst case is each char is octal.  */
        len *= 4;
        len *= 4;
-      len += 2;                        /* Room for initial space and final NUL.  */
+      len += 2;
 
 
-      dest = &start[total_len];
-      if (dest + len > POOL_LIMIT (pool))
+      if ((size_t) (BUFF_LIMIT (pfile->u_buff) - dest) < len)
        {
        {
-         _cpp_next_chunk (pool, len, (unsigned char **) &start);
-         dest = &start[total_len];
+         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;
        }
 
       /* Leading white space?  */
        }
 
       /* Leading white space?  */
-      if (total_len)
+      if (dest != BUFF_FRONT (pfile->u_buff))
        {
          if (source == NULL)
            source = token;
        {
          if (source == NULL)
            source = token;
@@ -302,15 +327,14 @@ stringify_arg (pfile, arg)
 
       if (escape_it)
        {
 
       if (escape_it)
        {
-         unsigned char *buf = (unsigned char *) xmalloc (len);
-
+         _cpp_buff *buff = _cpp_get_buff (pfile, len);
+         unsigned char *buf = BUFF_FRONT (buff);
          len = cpp_spell_token (pfile, token, buf) - buf;
          dest = quote_string (dest, buf, len);
          len = cpp_spell_token (pfile, token, buf) - buf;
          dest = quote_string (dest, buf, len);
-         free (buf);
+         _cpp_release_buff (pfile, buff);
        }
       else
        dest = cpp_spell_token (pfile, token, dest);
        }
       else
        dest = cpp_spell_token (pfile, token, dest);
-      total_len = dest - start;
 
       if (token->type == CPP_OTHER && token->val.c == '\\')
        backslash_count++;
 
       if (token->type == CPP_OTHER && token->val.c == '\\')
        backslash_count++;
@@ -322,101 +346,75 @@ stringify_arg (pfile, arg)
   if (backslash_count & 1)
     {
       cpp_warning (pfile, "invalid string literal, ignoring final '\\'");
   if (backslash_count & 1)
     {
       cpp_warning (pfile, "invalid string literal, ignoring final '\\'");
-      total_len--;
+      dest--;
     }
 
   /* Commit the memory, including NUL, and return the token.  */
     }
 
   /* Commit the memory, including NUL, and return the token.  */
-  POOL_COMMIT (pool, total_len + 1);
-  return new_string_token (pfile, start, total_len);
+  len = dest - BUFF_FRONT (pfile->u_buff);
+  BUFF_FRONT (pfile->u_buff) = dest + 1;
+  return new_string_token (pfile, dest - len, len);
 }
 
 }
 
-/* Try to paste two tokens.  On success, the LHS becomes the pasted
-   token, and 0 is returned.  For failure, we update the flags of the
-   RHS appropriately and return non-zero.  */
-static int
-paste_tokens (pfile, lhs, rhs)
+/* Try to paste two tokens.  On success, return non-zero.  In any
+   case, PLHS is updated to point to the pasted token, which is
+   guaranteed to not have the PASTE_LEFT flag set.  */
+static bool
+paste_tokens (pfile, plhs, rhs)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     cpp_token *lhs;
-     const cpp_token *rhs;
+     const cpp_token **plhs, *rhs;
 {
 {
-  unsigned char flags = 0;
-  int digraph = 0;
-  enum cpp_ttype type;
-
-  type = cpp_can_paste (pfile, lhs, rhs, &digraph);
-  
-  if (type == CPP_EOF)
-    {
-      /* Mandatory warning for all apart from assembler.  */
-      if (CPP_OPTION (pfile, lang) != CLK_ASM)
-       cpp_warning (pfile,
-        "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
-                    cpp_token_as_text (pfile, lhs),
-                    cpp_token_as_text (pfile, rhs));
-      return 1;
-    }
-
-  if (digraph)
-    flags |= DIGRAPH;
-
-  /* Identifiers and numbers need spellings to be pasted.  */
-  if (type == CPP_NAME || type == CPP_NUMBER)
-    {
-      unsigned int total_len = cpp_token_len (lhs) + cpp_token_len (rhs);
-      unsigned char *result, *end;
-
-      result = _cpp_pool_alloc (&pfile->ident_pool, total_len + 1);
-
-      /* Paste the spellings and null terminate.  */
-      end = cpp_spell_token (pfile, rhs, cpp_spell_token (pfile, lhs, result));
-      *end = '\0';
-      total_len = end - result;
-
-      if (type == CPP_NAME)
-       {
-         lhs->val.node = cpp_lookup (pfile, result, total_len);
-         if (lhs->val.node->flags & NODE_OPERATOR)
-           {
-             flags |= NAMED_OP;
-             lhs->type = lhs->val.node->value.operator;
-           }
-       }
-      else
-       {
-         lhs->val.str.text = result;
-         lhs->val.str.len = total_len;
-       }
-    }
-  else if (type == CPP_WCHAR || type == CPP_WSTRING)
-    lhs->val.str = rhs->val.str;
-
-  /* Set type and flags after pasting spellings.  */
-  lhs->type = type;
-  lhs->flags = flags;
-
-  return 0;
+  unsigned char *buf, *end;
+  const cpp_token *lhs;
+  unsigned int len;
+  bool valid;
+
+  lhs = *plhs;
+  len = cpp_token_len (lhs) + cpp_token_len (rhs) + 1;
+  buf = (unsigned char *) alloca (len);
+  end = cpp_spell_token (pfile, lhs, buf);
+
+  /* Avoid comment headers, since they are still processed in stage 3.
+     It is simpler to insert a space here, rather than modifying the
+     lexer to ignore comments in some circumstances.  Simply returning
+     false doesn't work, since we want to clear the PASTE_LEFT flag.  */
+  if (lhs->type == CPP_DIV
+      && (rhs->type == CPP_MULT || rhs->type == CPP_DIV))
+    *end++ = ' ';
+  end = cpp_spell_token (pfile, rhs, end);
+  *end = '\0';
+
+  cpp_push_buffer (pfile, buf, end - buf, /* from_stage3 */ true, 1);
+
+  /* Tweak the column number the lexer will report.  */
+  pfile->buffer->col_adjust = pfile->cur_token[-1].col - 1;
+
+  /* We don't want a leading # to be interpreted as a directive.  */
+  pfile->buffer->saved_flags = 0;
+
+  /* Set pfile->cur_token as required by _cpp_lex_direct.  */
+  pfile->cur_token = _cpp_temp_token (pfile);
+  *plhs = _cpp_lex_direct (pfile);
+  valid = pfile->buffer->cur == pfile->buffer->rlimit;
+  _cpp_pop_buffer (pfile);
+
+  return valid;
 }
 
 }
 
-/* Handles an arbitrarily long sequence of ## operators.  This
-   implementation is left-associative, non-recursive, and finishes a
-   paste before handling succeeding ones.  If the paste fails, we back
-   up a token to just after the ## operator, with the effect that it
-   appears in the output stream normally.  */
+/* Handles an arbitrarily long sequence of ## operators, with initial
+   operand LHS.  This implementation is left-associative,
+   non-recursive, and finishes a paste before handling succeeding
+   ones.  If a paste fails, we back up to the RHS of the failing ##
+   operator before pushing the context containing the result of prior
+   successful pastes, with the effect that the RHS appears in the
+   output stream after the pasted LHS normally.  */
 static void
 paste_all_tokens (pfile, lhs)
      cpp_reader *pfile;
      const cpp_token *lhs;
 {
 static void
 paste_all_tokens (pfile, lhs)
      cpp_reader *pfile;
      const cpp_token *lhs;
 {
-  cpp_token *pasted;
   const cpp_token *rhs;
   cpp_context *context = pfile->context;
 
   const cpp_token *rhs;
   cpp_context *context = pfile->context;
 
-  /* Copy lhs to pasted, but preserve original line and column.  */
-  pasted = _cpp_temp_token (pfile);
-  pasted->type = lhs->type;
-  pasted->flags = lhs->flags;
-  pasted->val.str = lhs->val.str;
-
   do
     {
       /* Take the token directly from the current context.  We can do
   do
     {
       /* Take the token directly from the current context.  We can do
@@ -432,22 +430,30 @@ paste_all_tokens (pfile, lhs)
       if (rhs->type == CPP_PADDING)
        abort ();
 
       if (rhs->type == CPP_PADDING)
        abort ();
 
-      if (paste_tokens (pfile, pasted, rhs))
+      if (!paste_tokens (pfile, &lhs, rhs))
        {
          _cpp_backup_tokens (pfile, 1);
        {
          _cpp_backup_tokens (pfile, 1);
+
+         /* Mandatory warning for all apart from assembler.  */
+         if (CPP_OPTION (pfile, lang) != CLK_ASM)
+           cpp_warning (pfile,
+        "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
+                        cpp_token_as_text (pfile, lhs),
+                        cpp_token_as_text (pfile, rhs));
          break;
        }
     }
   while (rhs->flags & PASTE_LEFT);
 
          break;
        }
     }
   while (rhs->flags & PASTE_LEFT);
 
-  /* Clear PASTE_LEFT flag, put the token in its own context.  */
-  pasted->flags &= ~PASTE_LEFT;
-  push_token_context (pfile, NULL, pasted, 1);
+  /* Put the resulting token in its own context.  */
+  push_token_context (pfile, NULL, lhs, 1);
 }
 
 }
 
-/* Reads and returns the arguments to a function-like macro invocation.
-   Assumes the opening parenthesis has been processed.  If there is an
-   error, emits an appropriate diagnostic and returns NULL.  */
+/* Reads and returns the arguments to a function-like macro
+   invocation.  Assumes the opening parenthesis has been processed.
+   If there is an error, emits an appropriate diagnostic and returns
+   NULL.  Each argument is terminated by a CPP_EOF token, for the
+   future benefit of expand_arg().  */
 static _cpp_buff *
 collect_args (pfile, node)
      cpp_reader *pfile;
 static _cpp_buff *
 collect_args (pfile, node)
      cpp_reader *pfile;
@@ -470,7 +476,7 @@ collect_args (pfile, node)
   base_buff = buff;
   args = (macro_arg *) buff->base;
   memset (args, 0, argc * sizeof (macro_arg));
   base_buff = buff;
   args = (macro_arg *) buff->base;
   memset (args, 0, argc * sizeof (macro_arg));
-  buff->cur = (char *) &args[argc];
+  buff->cur = (unsigned char *) &args[argc];
   arg = args, argc = 0;
 
   /* Collect the tokens making up each argument.  We don't yet know
   arg = args, argc = 0;
 
   /* Collect the tokens making up each argument.  We don't yet know
@@ -487,10 +493,10 @@ collect_args (pfile, node)
       for (;;)
        {
          /* Require space for 2 new tokens (including a CPP_EOF).  */
       for (;;)
        {
          /* Require space for 2 new tokens (including a CPP_EOF).  */
-         if ((char *) &arg->first[ntokens + 2] > buff->limit)
+         if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit)
            {
            {
-             buff = _cpp_extend_buff (pfile, buff,
-                                      1000 * sizeof (cpp_token *));
+             buff = _cpp_append_extend_buff (pfile, buff,
+                                             1000 * sizeof (cpp_token *));
              arg->first = (const cpp_token **) buff->cur;
            }
 
              arg->first = (const cpp_token **) buff->cur;
            }
 
@@ -535,7 +541,7 @@ collect_args (pfile, node)
         overwrite the final legitimate argument, before failing.  */
       if (argc <= macro->paramc)
        {
         overwrite the final legitimate argument, before failing.  */
       if (argc <= macro->paramc)
        {
-         buff->cur = (char *) &arg->first[ntokens + 1];
+         buff->cur = (unsigned char *) &arg->first[ntokens + 1];
          if (argc != macro->paramc)
            arg++;
        }
          if (argc != macro->paramc)
            arg++;
        }
@@ -561,10 +567,12 @@ collect_args (pfile, node)
          step_back = true;
        }
       else
          step_back = true;
        }
       else
-       /* We still need the CPP_EOF to end directives, and to end
-           pre-expansion of a macro argument.  */
        step_back = (pfile->context->prev || pfile->state.in_directive);
 
        step_back = (pfile->context->prev || pfile->state.in_directive);
 
+      /* We still need the CPP_EOF to end directives, and to end
+        pre-expansion of a macro argument.  Step back is not
+        unconditional, since we don't want to return a CPP_EOF to our
+        callers at the end of an -include-d file.  */
       if (step_back)
        _cpp_backup_tokens (pfile, 1);
       cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
       if (step_back)
        _cpp_backup_tokens (pfile, 1);
       cpp_error (pfile, "unterminated argument list invoking macro \"%s\"",
@@ -613,83 +621,108 @@ collect_args (pfile, node)
   return NULL;
 }
 
   return NULL;
 }
 
-static int
+/* Search for an opening parenthesis to the macro of NODE, in such a
+   way that, if none is found, we don't lose the information in any
+   intervening padding tokens.  If we find the parenthesis, collect
+   the arguments and return the buffer containing them.  */
+static _cpp_buff *
 funlike_invocation_p (pfile, node)
      cpp_reader *pfile;
 funlike_invocation_p (pfile, node)
      cpp_reader *pfile;
-     const cpp_hashnode *node;
+     cpp_hashnode *node;
 {
 {
-  const cpp_token *maybe_paren;
-  _cpp_buff *buff = NULL;
-
-  pfile->state.prevent_expansion++;
-  pfile->keep_tokens++;
+  const cpp_token *token, *padding = NULL;
 
 
-  pfile->state.parsing_args = 1;
-  do
-    maybe_paren = cpp_get_token (pfile);
-  while (maybe_paren->type == CPP_PADDING);
-  pfile->state.parsing_args = 2;
-
-  if (maybe_paren->type == CPP_OPEN_PAREN)
-    buff = collect_args (pfile, node);
-  else
+  for (;;)
     {
     {
-      _cpp_backup_tokens (pfile, 1);
-      if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
-       cpp_warning (pfile,
- "function-like macro \"%s\" must be used with arguments in traditional C",
-                    NODE_NAME (node));
+      token = cpp_get_token (pfile);
+      if (token->type != CPP_PADDING)
+       break;
+      if (padding == NULL
+         || (!(padding->flags & PREV_WHITE) && token->val.source == NULL))
+       padding = token;
     }
 
     }
 
-  pfile->state.parsing_args = 0;
-  pfile->keep_tokens--;
-  pfile->state.prevent_expansion--;
-
-  if (buff)
+  if (token->type == CPP_OPEN_PAREN)
     {
     {
-      if (node->value.macro->paramc > 0)
-       replace_args (pfile, node->value.macro, (macro_arg *) buff->base);
-      _cpp_release_buff (pfile, buff);
+      pfile->state.parsing_args = 2;
+      return collect_args (pfile, node);
     }
 
     }
 
-  return buff != 0;
+  /* Back up.  We may have skipped padding, in which case backing up
+     more than one token when expanding macros is in general too
+     difficult.  We re-insert it in its own context.  */
+  _cpp_backup_tokens (pfile, 1);
+  if (padding)
+    push_token_context (pfile, NULL, padding, 1);
+
+  return NULL;
 }
 
 }
 
-/* Push the context of a macro onto the context stack.  TOKEN is the
-   macro name.  If we can successfully start expanding the macro,
-   TOKEN is replaced with the first token of the expansion, and we
-   return non-zero.  */
+/* Push the context of a macro with hash entry NODE onto the context
+   stack.  If we can successfully expand the macro, we push a context
+   containing its yet-to-be-rescanned replacement list and return one.
+   Otherwise, we don't push a context and return zero.  */
 static int
 enter_macro_context (pfile, node)
      cpp_reader *pfile;
      cpp_hashnode *node;
 {
 static int
 enter_macro_context (pfile, node)
      cpp_reader *pfile;
      cpp_hashnode *node;
 {
-  if (node->flags & NODE_BUILTIN)
-    push_token_context (pfile, NULL, builtin_macro (pfile, node), 1);
-  else
+  /* The presence of a macro invalidates a file's controlling macro.  */
+  pfile->mi_valid = false;
+
+  /* Handle standard macros.  */
+  if (! (node->flags & NODE_BUILTIN))
     {
       cpp_macro *macro = node->value.macro;
 
     {
       cpp_macro *macro = node->value.macro;
 
-      if (macro->fun_like && !funlike_invocation_p (pfile, node))
-       return 0;
+      if (macro->fun_like)
+       {
+         _cpp_buff *buff;
+
+         pfile->state.prevent_expansion++;
+         pfile->keep_tokens++;
+         pfile->state.parsing_args = 1;
+         buff = funlike_invocation_p (pfile, node);
+         pfile->state.parsing_args = 0;
+         pfile->keep_tokens--;
+         pfile->state.prevent_expansion--;
+
+         if (buff == NULL)
+           {
+             if (CPP_WTRADITIONAL (pfile) && ! node->value.macro->syshdr)
+               cpp_warning (pfile,
+ "function-like macro \"%s\" must be used with arguments in traditional C",
+                            NODE_NAME (node));
+
+             return 0;
+           }
+
+         if (node->value.macro->paramc > 0)
+           replace_args (pfile, node, (macro_arg *) buff->base);
+         _cpp_release_buff (pfile, buff);
+       }
 
       /* Disable the macro within its expansion.  */
 
       /* Disable the macro within its expansion.  */
-      macro->disabled = 1;
+      node->flags |= NODE_DISABLED;
 
       if (macro->paramc == 0)
 
       if (macro->paramc == 0)
-       push_token_context (pfile, macro, macro->expansion, macro->count);
+       push_token_context (pfile, node, macro->expansion, macro->count);
+
+      return 1;
     }
     }
-  return 1;
+
+  /* Handle built-in macros and the _Pragma operator.  */
+  return builtin_macro (pfile, node);
 }
 
 }
 
-/* Take the expansion of a function-like MACRO, replacing parameters
-   with the actual arguments.  Each argument is macro-expanded before
-   replacement, unless operated upon by the # or ## operators.  */
+/* Replace the parameters in a function-like macro of NODE with the
+   actual ARGS, and place the result in a newly pushed token context.
+   Expand each argument before replacing, unless it is operated upon
+   by the # or ## operators.  */
 static void
 static void
-replace_args (pfile, macro, args)
+replace_args (pfile, node, args)
      cpp_reader *pfile;
      cpp_reader *pfile;
-     cpp_macro *macro;
+     cpp_hashnode *node;
      macro_arg *args;
 {
   unsigned int i, total;
      macro_arg *args;
 {
   unsigned int i, total;
@@ -697,11 +730,13 @@ replace_args (pfile, macro, args)
   const cpp_token **dest, **first;
   macro_arg *arg;
   _cpp_buff *buff;
   const cpp_token **dest, **first;
   macro_arg *arg;
   _cpp_buff *buff;
+  cpp_macro *macro;
 
   /* First, fully macro-expand arguments, calculating the number of
      tokens in the final expansion as we go.  The ordering of the if
      statements below is subtle; we must handle stringification before
      pasting.  */
 
   /* First, fully macro-expand arguments, calculating the number of
      tokens in the final expansion as we go.  The ordering of the if
      statements below is subtle; we must handle stringification before
      pasting.  */
+  macro = node->value.macro;
   total = macro->count;
   limit = macro->expansion + macro->count;
 
   total = macro->count;
   limit = macro->expansion + macro->count;
 
@@ -819,7 +854,7 @@ replace_args (pfile, macro, args)
     if (args[i].expanded)
       free (args[i].expanded);
 
     if (args[i].expanded)
       free (args[i].expanded);
 
-  push_ptoken_context (pfile, macro, buff, first, dest - first);
+  push_ptoken_context (pfile, node, buff, first, dest - first);
 }
 
 /* Return a special padding token, with padding inherited from SOURCE.  */
 }
 
 /* Return a special padding token, with padding inherited from SOURCE.  */
@@ -836,7 +871,8 @@ padding_token (pfile, source)
   return result;
 }
 
   return result;
 }
 
-/* Move to the next context.  Create one if there is none.  */
+/* Get a new uninitialized context.  Create a new one if we cannot
+   re-use an old one.  */
 static cpp_context *
 next_context (pfile)
      cpp_reader *pfile;
 static cpp_context *
 next_context (pfile)
      cpp_reader *pfile;
@@ -859,7 +895,7 @@ next_context (pfile)
 static void
 push_ptoken_context (pfile, macro, buff, first, count)
      cpp_reader *pfile;
 static void
 push_ptoken_context (pfile, macro, buff, first, count)
      cpp_reader *pfile;
-     cpp_macro *macro;
+     cpp_hashnode *macro;
      _cpp_buff *buff;
      const cpp_token **first;
      unsigned int count;
      _cpp_buff *buff;
      const cpp_token **first;
      unsigned int count;
@@ -877,7 +913,7 @@ push_ptoken_context (pfile, macro, buff, first, count)
 static void
 push_token_context (pfile, macro, first, count)
      cpp_reader *pfile;
 static void
 push_token_context (pfile, macro, first, count)
      cpp_reader *pfile;
-     cpp_macro *macro;
+     cpp_hashnode *macro;
      const cpp_token *first;
      unsigned int count;
 {
      const cpp_token *first;
      unsigned int count;
 {
@@ -890,6 +926,12 @@ push_token_context (pfile, macro, first, count)
   context->last.token = first + count;
 }
 
   context->last.token = first + count;
 }
 
+/* Expand an argument ARG before replacing parameters in a
+   function-like macro.  This works by pushing a context with the
+   argument's tokens, and then expanding that into a temporary buffer
+   as if it were a normal part of the token stream.  collect_args()
+   has terminated the argument's tokens with a CPP_EOF so that we know
+   when we have fully expanded the argument.  */
 static void
 expand_arg (pfile, arg)
      cpp_reader *pfile;
 static void
 expand_arg (pfile, arg)
      cpp_reader *pfile;
@@ -928,15 +970,17 @@ expand_arg (pfile, arg)
   _cpp_pop_context (pfile);
 }
 
   _cpp_pop_context (pfile);
 }
 
+/* Pop the current context off the stack, re-enabling the macro if the
+   context represented a macro's replacement list.  The context
+   structure is not freed so that we can re-use it later.  */
 void
 _cpp_pop_context (pfile)
      cpp_reader *pfile;
 {
   cpp_context *context = pfile->context;
 
 void
 _cpp_pop_context (pfile)
      cpp_reader *pfile;
 {
   cpp_context *context = pfile->context;
 
-  /* Re-enable a macro when leaving its expansion.  */
   if (context->macro)
   if (context->macro)
-    context->macro->disabled = 0;
+    context->macro->flags &= ~NODE_DISABLED;
 
   if (context->buff)
     _cpp_release_buff (pfile, context->buff);
 
   if (context->buff)
     _cpp_release_buff (pfile, context->buff);
@@ -997,39 +1041,31 @@ cpp_get_token (pfile)
 
       node = result->val.node;
 
 
       node = result->val.node;
 
-      /* Handle macros and the _Pragma operator.  */
-      if (node->type == NT_MACRO && !(result->flags & NO_EXPAND))
+      if (node->type != NT_MACRO || (result->flags & NO_EXPAND))
+       break;
+      
+      if (!(node->flags & NODE_DISABLED))
        {
        {
-         /* Macros invalidate controlling macros.  */
-         pfile->mi_valid = false;
-
-         if (!(node->flags & NODE_BUILTIN) && node->value.macro->disabled)
-           {
-             /* Flag this token as always unexpandable.  */
-             cpp_token *t = _cpp_temp_token (pfile);
-             t->type = result->type;
-             t->flags = result->flags | NO_EXPAND;
-             t->val.str = result->val.str;
-             result = t;
-           }
-         else if (!pfile->state.prevent_expansion
-                  && enter_macro_context (pfile, node))
+         if (!pfile->state.prevent_expansion
+             && enter_macro_context (pfile, node))
            {
              if (pfile->state.in_directive)
                continue;
              return padding_token (pfile, result);
            }
        }
            {
              if (pfile->state.in_directive)
                continue;
              return padding_token (pfile, result);
            }
        }
+      else
+       {
+         /* Flag this token as always unexpandable.  FIXME: move this
+            to collect_args()?.  */
+         cpp_token *t = _cpp_temp_token (pfile);
+         t->type = result->type;
+         t->flags = result->flags | NO_EXPAND;
+         t->val.str = result->val.str;
+         result = t;
+       }
 
 
-      /* Don't interpret _Pragma within directives.  The standard is
-         not clear on this, but to me this makes most sense.  */
-      if (node != pfile->spec_nodes.n__Pragma
-         || pfile->state.in_directive)
-       break;
-
-      /* Handle it, and loop back for another token.  MI is cleared
-         since this token came from either the lexer or a macro.  */
-      _cpp_do__Pragma (pfile);
+      break;
     }
 
   return result;
     }
 
   return result;
@@ -1042,9 +1078,9 @@ int
 cpp_sys_macro_p (pfile)
      cpp_reader *pfile;
 {
 cpp_sys_macro_p (pfile)
      cpp_reader *pfile;
 {
-  cpp_macro *macro = pfile->context->macro;
+  cpp_hashnode *node = pfile->context->macro;
 
 
-  return macro && macro->syshdr;
+  return node && node->value.macro && node->value.macro->syshdr;
 }
 
 /* Read each token in, until EOF.  Directives are transparently
 }
 
 /* Read each token in, until EOF.  Directives are transparently
@@ -1070,7 +1106,9 @@ _cpp_backup_tokens (pfile, count)
       while (count--)
        {
          pfile->cur_token--;
       while (count--)
        {
          pfile->cur_token--;
-         if (pfile->cur_token == pfile->cur_run->base)
+         if (pfile->cur_token == pfile->cur_run->base
+             /* Possible with -fpreprocessed and no leading #line.  */
+             && pfile->cur_run->prev != NULL)
            {
              pfile->cur_run = pfile->cur_run->prev;
              pfile->cur_token = pfile->cur_run->limit;
            {
              pfile->cur_run = pfile->cur_run->prev;
              pfile->cur_token = pfile->cur_run->limit;
@@ -1092,8 +1130,7 @@ _cpp_backup_tokens (pfile, count)
 
 /* Returns non-zero if a macro redefinition warning is required.  */
 static int
 
 /* Returns non-zero if a macro redefinition warning is required.  */
 static int
-warn_of_redefinition (pfile, node, macro2)
-     cpp_reader *pfile;
+warn_of_redefinition (node, macro2)
      const cpp_hashnode *node;
      const cpp_macro *macro2;
 {
      const cpp_hashnode *node;
      const cpp_macro *macro2;
 {
@@ -1104,9 +1141,6 @@ warn_of_redefinition (pfile, node, macro2)
   if (node->flags & NODE_WARN)
     return 1;
 
   if (node->flags & NODE_WARN)
     return 1;
 
-  if (! CPP_PEDANTIC (pfile))
-    return 0;
-
   /* Redefinition of a macro is allowed if and only if the old and new
      definitions are the same.  (6.10.3 paragraph 2).  */
   macro1 = node->value.macro;
   /* Redefinition of a macro is allowed if and only if the old and new
      definitions are the same.  (6.10.3 paragraph 2).  */
   macro1 = node->value.macro;
@@ -1132,7 +1166,6 @@ warn_of_redefinition (pfile, node, macro2)
 }
 
 /* Free the definition of hashnode H.  */
 }
 
 /* Free the definition of hashnode H.  */
-
 void
 _cpp_free_definition (h)
      cpp_hashnode *h;
 void
 _cpp_free_definition (h)
      cpp_hashnode *h;
@@ -1140,19 +1173,17 @@ _cpp_free_definition (h)
   /* Macros and assertions no longer have anything to free.  */
   h->type = NT_VOID;
   /* Clear builtin flag in case of redefinition.  */
   /* Macros and assertions no longer have anything to free.  */
   h->type = NT_VOID;
   /* Clear builtin flag in case of redefinition.  */
-  h->flags &= ~NODE_BUILTIN;
+  h->flags &= ~(NODE_BUILTIN | NODE_DISABLED);
 }
 
 /* Save parameter NODE to the parameter list of macro MACRO.  Returns
 }
 
 /* Save parameter NODE to the parameter list of macro MACRO.  Returns
-   zero on success, non-zero if the paramter is a duplicate.  */
+   zero on success, non-zero if the parameter is a duplicate.  */
 static int
 save_parameter (pfile, macro, node)
      cpp_reader *pfile;
      cpp_macro *macro;
      cpp_hashnode *node;
 {
 static int
 save_parameter (pfile, macro, node)
      cpp_reader *pfile;
      cpp_macro *macro;
      cpp_hashnode *node;
 {
-  cpp_hashnode **dest;
-
   /* Constraint 6.10.3.6 - duplicate parameter names.  */
   if (node->arg_index)
     {
   /* Constraint 6.10.3.6 - duplicate parameter names.  */
   if (node->arg_index)
     {
@@ -1160,22 +1191,16 @@ save_parameter (pfile, macro, node)
       return 1;
     }
 
       return 1;
     }
 
-  dest = &macro->params[macro->paramc];
+  if (BUFF_ROOM (pfile->a_buff)
+      < (macro->paramc + 1) * sizeof (cpp_hashnode *))
+    _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_hashnode *));
 
 
-  /* Check we have room for the parameters.  */
-  if ((unsigned char *) (dest + 1) >= POOL_LIMIT (&pfile->macro_pool))
-    {
-      _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_hashnode *),
-                      (unsigned char **) &macro->params);
-      dest = &macro->params[macro->paramc];
-    }
-
-  *dest = node;
-  node->arg_index = ++macro->paramc;
+  ((cpp_hashnode **) BUFF_FRONT (pfile->a_buff))[macro->paramc++] = node;
+  node->arg_index = macro->paramc;
   return 0;
 }
 
   return 0;
 }
 
-/* Check the syntax of the paramters in a MACRO definition.  */
+/* Check the syntax of the parameters in a MACRO definition.  */
 static int
 parse_params (pfile, macro)
      cpp_reader *pfile;
 static int
 parse_params (pfile, macro)
      cpp_reader *pfile;
@@ -1183,7 +1208,6 @@ parse_params (pfile, macro)
 {
   unsigned int prev_ident = 0;
 
 {
   unsigned int prev_ident = 0;
 
-  macro->params = (cpp_hashnode **) POOL_FRONT (&pfile->macro_pool);
   for (;;)
     {
       const cpp_token *token = _cpp_lex_token (pfile);
   for (;;)
     {
       const cpp_token *token = _cpp_lex_token (pfile);
@@ -1209,7 +1233,7 @@ parse_params (pfile, macro)
 
        case CPP_CLOSE_PAREN:
          if (prev_ident || macro->paramc == 0)
 
        case CPP_CLOSE_PAREN:
          if (prev_ident || macro->paramc == 0)
-           break;
+           return 1;
 
          /* Fall through to pick up the error.  */
        case CPP_COMMA:
 
          /* Fall through to pick up the error.  */
        case CPP_COMMA:
@@ -1237,18 +1261,13 @@ parse_params (pfile, macro)
          /* We're at the end, and just expect a closing parenthesis.  */
          token = _cpp_lex_token (pfile);
          if (token->type == CPP_CLOSE_PAREN)
          /* We're at the end, and just expect a closing parenthesis.  */
          token = _cpp_lex_token (pfile);
          if (token->type == CPP_CLOSE_PAREN)
-           break;
+           return 1;
          /* Fall through.  */
 
        case CPP_EOF:
          cpp_error (pfile, "missing ')' in macro parameter list");
          return 0;
        }
          /* Fall through.  */
 
        case CPP_EOF:
          cpp_error (pfile, "missing ')' in macro parameter list");
          return 0;
        }
-
-      /* Success.  Commit the parameter array.  */
-      POOL_COMMIT (&pfile->macro_pool,
-                  macro->paramc * sizeof (cpp_hashnode *));
-      return 1;
     }
 }
 
     }
 }
 
@@ -1258,20 +1277,14 @@ alloc_expansion_token (pfile, macro)
      cpp_reader *pfile;
      cpp_macro *macro;
 {
      cpp_reader *pfile;
      cpp_macro *macro;
 {
-  cpp_token *token = &macro->expansion[macro->count];
-
-  /* Check we have room for the token.  */
-  if ((unsigned char *) (token + 1) >= POOL_LIMIT (&pfile->macro_pool))
-    {
-      _cpp_next_chunk (&pfile->macro_pool, sizeof (cpp_token),
-                      (unsigned char **) &macro->expansion);
-      token = &macro->expansion[macro->count];
-    }
+  if (BUFF_ROOM (pfile->a_buff) < (macro->count + 1) * sizeof (cpp_token))
+    _cpp_extend_buff (pfile, &pfile->a_buff, sizeof (cpp_token));
 
 
-  macro->count++;
-  return token;
+  return &((cpp_token *) BUFF_FRONT (pfile->a_buff))[macro->count++];
 }
 
 }
 
+/* Lex a token from the expansion of MACRO, but mark parameters as we
+   find them and warn of traditional stringification.  */
 static cpp_token *
 lex_expansion_token (pfile, macro)
      cpp_reader *pfile;
 static cpp_token *
 lex_expansion_token (pfile, macro)
      cpp_reader *pfile;
@@ -1282,7 +1295,7 @@ lex_expansion_token (pfile, macro)
   pfile->cur_token = alloc_expansion_token (pfile, macro);
   token = _cpp_lex_direct (pfile);
 
   pfile->cur_token = alloc_expansion_token (pfile, macro);
   token = _cpp_lex_direct (pfile);
 
-  /* Is this an argument?  */
+  /* Is this a parameter?  */
   if (token->type == CPP_NAME && token->val.node->arg_index)
     {
       token->type = CPP_MACRO_ARG;
   if (token->type == CPP_NAME && token->val.node->arg_index)
     {
       token->type = CPP_MACRO_ARG;
@@ -1306,8 +1319,7 @@ _cpp_create_definition (pfile, node)
   const cpp_token *ctoken;
   unsigned int i, ok = 1;
 
   const cpp_token *ctoken;
   unsigned int i, ok = 1;
 
-  macro = (cpp_macro *) _cpp_pool_alloc (&pfile->macro_pool,
-                                        sizeof (cpp_macro));
+  macro = (cpp_macro *) _cpp_aligned_alloc (pfile, sizeof (cpp_macro));
   macro->line = pfile->directive_line;
   macro->params = 0;
   macro->paramc = 0;
   macro->line = pfile->directive_line;
   macro->params = 0;
   macro->paramc = 0;
@@ -1321,16 +1333,19 @@ _cpp_create_definition (pfile, node)
 
   if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
     {
 
   if (ctoken->type == CPP_OPEN_PAREN && !(ctoken->flags & PREV_WHITE))
     {
-      if (!(ok = parse_params (pfile, macro)))
+      ok = parse_params (pfile, macro);
+      macro->params = (cpp_hashnode **) BUFF_FRONT (pfile->a_buff);
+      if (!ok)
        goto cleanup2;
        goto cleanup2;
+
+      /* Success.  Commit the parameter array.  */
+      BUFF_FRONT (pfile->a_buff) = (U_CHAR *) &macro->params[macro->paramc];
       macro->fun_like = 1;
     }
   else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
     cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name");
 
       macro->fun_like = 1;
     }
   else if (ctoken->type != CPP_EOF && !(ctoken->flags & PREV_WHITE))
     cpp_pedwarn (pfile, "ISO C requires whitespace after the macro name");
 
-  pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
   saved_cur_token = pfile->cur_token;
   saved_cur_token = pfile->cur_token;
-  macro->expansion = (cpp_token *) POOL_FRONT (&pfile->macro_pool);
 
   if (macro->fun_like)
     token = lex_expansion_token (pfile, macro);
 
   if (macro->fun_like)
     token = lex_expansion_token (pfile, macro);
@@ -1388,23 +1403,30 @@ _cpp_create_definition (pfile, node)
       token = lex_expansion_token (pfile, macro);
     }
 
       token = lex_expansion_token (pfile, macro);
     }
 
+  macro->expansion = (cpp_token *) BUFF_FRONT (pfile->a_buff);
+
   /* Don't count the CPP_EOF.  */
   macro->count--;
 
   /* Don't count the CPP_EOF.  */
   macro->count--;
 
+  /* Clear whitespace on first token for warn_of_redefinition().  */
+  if (macro->count)
+    macro->expansion[0].flags &= ~PREV_WHITE;
+
+  /* Commit the memory.  */
+  BUFF_FRONT (pfile->a_buff) = (U_CHAR *) &macro->expansion[macro->count];
+
   /* Implement the macro-defined-to-itself optimisation.  */
   /* Implement the macro-defined-to-itself optimisation.  */
-  macro->disabled = (macro->count == 1 && !macro->fun_like
-                    && macro->expansion[0].type == CPP_NAME
-                    && macro->expansion[0].val.node == node);
+  if (macro->count == 1 && !macro->fun_like
+      && macro->expansion[0].type == CPP_NAME
+      && macro->expansion[0].val.node == node)
+    node->flags |= NODE_DISABLED;
 
   /* To suppress some diagnostics.  */
   macro->syshdr = pfile->map->sysp != 0;
 
 
   /* To suppress some diagnostics.  */
   macro->syshdr = pfile->map->sysp != 0;
 
-  /* Commit the memory.  */
-  POOL_COMMIT (&pfile->macro_pool, macro->count * sizeof (cpp_token));
-
   if (node->type != NT_VOID)
     {
   if (node->type != NT_VOID)
     {
-      if (warn_of_redefinition (pfile, node, macro))
+      if (warn_of_redefinition (node, macro))
        {
          cpp_pedwarn_with_line (pfile, pfile->directive_line, 0,
                                 "\"%s\" redefined", NODE_NAME (node));
        {
          cpp_pedwarn_with_line (pfile, pfile->directive_line, 0,
                                 "\"%s\" redefined", NODE_NAME (node));
@@ -1440,9 +1462,8 @@ _cpp_create_definition (pfile, node)
   return ok;
 }
 
   return ok;
 }
 
-/* Warn if a token in `string' matches one of the function macro
-   arguments in `info'.  This function assumes that the macro is a
-   function macro and not an object macro.  */
+/* Warn if a token in STRING matches one of a function-like MACRO's
+   parameters.  */
 static void
 check_trad_stringification (pfile, macro, string)
      cpp_reader *pfile;
 static void
 check_trad_stringification (pfile, macro, string)
      cpp_reader *pfile;
@@ -1476,7 +1497,7 @@ check_trad_stringification (pfile, macro, string)
              && !memcmp (p, NODE_NAME (node), len))
            {
              cpp_warning (pfile,
              && !memcmp (p, NODE_NAME (node), len))
            {
              cpp_warning (pfile,
-          "macro argument \"%s\" would be stringified with -traditional.",
+          "macro argument \"%s\" would be stringified with -traditional",
                           NODE_NAME (node));
              break;
            }
                           NODE_NAME (node));
              break;
            }
@@ -1489,7 +1510,6 @@ check_trad_stringification (pfile, macro, string)
    debugging info.  e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION".
    Caller is expected to generate the "#define" bit if needed.  The
    returned text is temporary, and automatically freed later.  */
    debugging info.  e.g. "PASTE(X, Y) X ## Y", or "MACNAME EXPANSION".
    Caller is expected to generate the "#define" bit if needed.  The
    returned text is temporary, and automatically freed later.  */
-
 const unsigned char *
 cpp_macro_definition (pfile, node)
      cpp_reader *pfile;
 const unsigned char *
 cpp_macro_definition (pfile, node)
      cpp_reader *pfile;