Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / macroexp.c
index 8d1876e0b3af8976d45f08b931b8b579cc677adc..1ece8d5d5be580a797029a09e36f2161154cfe0f 100644 (file)
@@ -1,5 +1,5 @@
 /* C preprocessor macro expansion for GDB.
-   Copyright (C) 2002-2017 Free Software Foundation, Inc.
+   Copyright (C) 2002-2021 Free Software Foundation, Inc.
    Contributed by Red Hat, Inc.
 
    This file is part of GDB.
 
 #include "defs.h"
 #include "gdb_obstack.h"
-#include "bcache.h"
 #include "macrotab.h"
 #include "macroexp.h"
+#include "macroscope.h"
 #include "c-lang.h"
 
 
 \f
-/* A resizeable, substringable string type.  */
 
+/* A string type that we can use to refer to substrings of other
+   strings.  */
 
-/* A string type that we can resize, quickly append to, and use to
-   refer to substrings of other strings.  */
-struct macro_buffer
+struct shared_macro_buffer
 {
-  /* An array of characters.  The first LEN bytes are the real text,
-     but there are SIZE bytes allocated to the array.  If SIZE is
-     zero, then this doesn't point to a malloc'ed block.  If SHARED is
-     non-zero, then this buffer is actually a pointer into some larger
-     string, and we shouldn't append characters to it, etc.  Because
-     of sharing, we can't assume in general that the text is
+  /* An array of characters.  This buffer is a pointer into some
+     larger string and thus we can't assume in that the text is
      null-terminated.  */
-  char *text;
+  const char *text;
 
   /* The number of characters in the string.  */
   int len;
 
-  /* The number of characters allocated to the string.  If SHARED is
-     non-zero, this is meaningless; in this case, we set it to zero so
-     that any "do we have room to append something?" tests will fail,
-     so we don't always have to check SHARED before using this field.  */
-  int size;
-
-  /* Zero if TEXT can be safely realloc'ed (i.e., it's its own malloc
-     block).  Non-zero if TEXT is actually pointing into the middle of
-     some other block, or to a string literal, and we shouldn't
-     reallocate it.  */
-  bool shared;
-
   /* For detecting token splicing. 
 
      This is the index in TEXT of the first character of the token
@@ -65,121 +48,124 @@ struct macro_buffer
      no token abutting the end of TEXT (it's just whitespace), and
      again, we set this equal to LEN.  We set this to -1 if we don't
      know the nature of TEXT.  */
-  int last_token;
+  int last_token = -1;
 
   /* If this buffer is holding the result from get_token, then this 
      is non-zero if it is an identifier token, zero otherwise.  */
-  int is_identifier;
-};
+  int is_identifier = 0;
 
+  shared_macro_buffer ()
+    : text (NULL),
+      len (0)
+  {
+  }
 
-/* Set the macro buffer *B to the empty string, guessing that its
-   final contents will fit in N bytes.  (It'll get resized if it
-   doesn't, so the guess doesn't have to be right.)  Allocate the
-   initial storage with xmalloc.  */
-static void
-init_buffer (struct macro_buffer *b, int n)
-{
-  b->size = n;
-  if (n > 0)
-    b->text = (char *) xmalloc (n);
-  else
-    b->text = NULL;
-  b->len = 0;
-  b->shared = false;
-  b->last_token = -1;
-}
+  /* Set the macro buffer to refer to the LEN bytes at ADDR, as a
+     shared substring.  */
+  shared_macro_buffer (const char *addr, int len)
+  {
+    set_shared (addr, len);
+  }
 
+  /* Set the macro buffer to refer to the LEN bytes at ADDR, as a
+     shared substring.  */
+  void set_shared (const char *addr, int len_)
+  {
+    text = addr;
+    len = len_;
+  }
+};
 
-/* Set the macro buffer *BUF to refer to the LEN bytes at ADDR, as a
-   shared substring.  */
+/* A string type that we can resize and quickly append to.  */
 
-static void
-init_shared_buffer (struct macro_buffer *buf, const char *addr, int len)
+struct growable_macro_buffer
 {
-  /* The function accept a "const char *" addr so that clients can
-     pass in string literals without casts.  */
-  buf->text = (char *) addr;
-  buf->len = len;
-  buf->shared = true;
-  buf->size = 0;
-  buf->last_token = -1;
-}
-
+  /* An array of characters.  The first LEN bytes are the real text,
+     but there are SIZE bytes allocated to the array.  */
+  char *text;
 
-/* Free the text of the buffer B.  Raise an error if B is shared.  */
-static void
-free_buffer (struct macro_buffer *b)
-{
-  gdb_assert (! b->shared);
-  if (b->size)
-    xfree (b->text);
-}
+  /* The number of characters in the string.  */
+  int len;
 
-/* Like free_buffer, but return the text as an xstrdup()d string.
-   This only exists to try to make the API relatively clean.  */
+  /* The number of characters allocated to the string.  */
+  int size;
 
-static char *
-free_buffer_return_text (struct macro_buffer *b)
-{
-  gdb_assert (! b->shared);
-  gdb_assert (b->size);
-  /* Nothing to do.  */
-  return b->text;
-}
+  /* For detecting token splicing.
 
-/* A cleanup function for macro buffers.  */
-static void
-cleanup_macro_buffer (void *untyped_buf)
-{
-  free_buffer ((struct macro_buffer *) untyped_buf);
-}
+     This is the index in TEXT of the first character of the token
+     that abuts the end of TEXT.  If TEXT contains no tokens, then we
+     set this equal to LEN.  If TEXT ends in whitespace, then there is
+     no token abutting the end of TEXT (it's just whitespace), and
+     again, we set this equal to LEN.  We set this to -1 if we don't
+     know the nature of TEXT.  */
+  int last_token = -1;
+
+  /* Set the macro buffer to the empty string, guessing that its
+     final contents will fit in N bytes.  (It'll get resized if it
+     doesn't, so the guess doesn't have to be right.)  Allocate the
+     initial storage with xmalloc.  */
+  explicit growable_macro_buffer (int n)
+    : len (0),
+      size (n)
+  {
+    if (n > 0)
+      text = (char *) xmalloc (n);
+    else
+      text = NULL;
+  }
 
+  DISABLE_COPY_AND_ASSIGN (growable_macro_buffer);
 
-/* Resize the buffer B to be at least N bytes long.  Raise an error if
-   B shouldn't be resized.  */
-static void
-resize_buffer (struct macro_buffer *b, int n)
-{
-  /* We shouldn't be trying to resize shared strings.  */
-  gdb_assert (! b->shared);
-  
-  if (b->size == 0)
-    b->size = n;
-  else
-    while (b->size <= n)
-      b->size *= 2;
+  ~growable_macro_buffer ()
+  {
+    xfree (text);
+  }
 
-  b->text = (char *) xrealloc (b->text, b->size);
-}
+  /* Release the text of the buffer to the caller.  */
+  gdb::unique_xmalloc_ptr<char> release ()
+  {
+    gdb_assert (size);
+    char *result = text;
+    text = NULL;
+    return gdb::unique_xmalloc_ptr<char> (result);
+  }
 
+  /* Resize the buffer to be at least N bytes long.  */
+  void resize_buffer (int n)
+  {
+    if (size == 0)
+      size = n;
+    else
+      while (size <= n)
+       size *= 2;
 
-/* Append the character C to the buffer B.  */
-static void
-appendc (struct macro_buffer *b, int c)
-{
-  int new_len = b->len + 1;
+    text = (char *) xrealloc (text, size);
+  }
 
-  if (new_len > b->size)
-    resize_buffer (b, new_len);
+  /* Append the character C to the buffer.  */
+  void appendc (int c)
+  {
+    int new_len = len + 1;
 
-  b->text[b->len] = c;
-  b->len = new_len;
-}
+    if (new_len > size)
+      resize_buffer (new_len);
 
+    text[len] = c;
+    len = new_len;
+  }
 
-/* Append the LEN bytes at ADDR to the buffer B.  */
-static void
-appendmem (struct macro_buffer *b, const char *addr, int len)
-{
-  int new_len = b->len + len;
+  /* Append the COUNT bytes at ADDR to the buffer.  */
+  void appendmem (const char *addr, int count)
+  {
+    int new_len = len + count;
 
-  if (new_len > b->size)
-    resize_buffer (b, new_len);
+    if (new_len > size)
+      resize_buffer (new_len);
 
-  memcpy (b->text + b->len, addr, len);
-  b->len = new_len;
-}
+    memcpy (text + len, addr, count);
+    len = new_len;
+  }
+};
 
 
 \f
@@ -190,10 +176,10 @@ int
 macro_is_whitespace (int c)
 {
   return (c == ' '
-          || c == '\t'
-          || c == '\n'
-          || c == '\v'
-          || c == '\f');
+         || c == '\t'
+         || c == '\n'
+         || c == '\v'
+         || c == '\f');
 }
 
 
@@ -208,15 +194,15 @@ int
 macro_is_identifier_nondigit (int c)
 {
   return (c == '_'
-          || ('a' <= c && c <= 'z')
-          || ('A' <= c && c <= 'Z'));
+         || ('a' <= c && c <= 'z')
+         || ('A' <= c && c <= 'Z'));
 }
 
 
 static void
-set_token (struct macro_buffer *tok, char *start, char *end)
+set_token (shared_macro_buffer *tok, const char *start, const char *end)
 {
-  init_shared_buffer (tok, start, end - start);
+  tok->set_shared (start, end - start);
   tok->last_token = 0;
 
   /* Presumed; get_identifier may overwrite this.  */
@@ -225,38 +211,38 @@ set_token (struct macro_buffer *tok, char *start, char *end)
 
 
 static int
-get_comment (struct macro_buffer *tok, char *p, char *end)
+get_comment (shared_macro_buffer *tok, const char *p, const char *end)
 {
   if (p + 2 > end)
     return 0;
   else if (p[0] == '/'
-           && p[1] == '*')
+          && p[1] == '*')
     {
-      char *tok_start = p;
+      const char *tok_start = p;
 
       p += 2;
 
       for (; p < end; p++)
-        if (p + 2 <= end
-            && p[0] == '*'
-            && p[1] == '/')
-          {
-            p += 2;
-            set_token (tok, tok_start, p);
-            return 1;
-          }
+       if (p + 2 <= end
+           && p[0] == '*'
+           && p[1] == '/')
+         {
+           p += 2;
+           set_token (tok, tok_start, p);
+           return 1;
+         }
 
       error (_("Unterminated comment in macro expansion."));
     }
   else if (p[0] == '/'
-           && p[1] == '/')
+          && p[1] == '/')
     {
-      char *tok_start = p;
+      const char *tok_start = p;
 
       p += 2;
       for (; p < end; p++)
-        if (*p == '\n')
-          break;
+       if (*p == '\n')
+         break;
 
       set_token (tok, tok_start, p);
       return 1;
@@ -267,17 +253,17 @@ get_comment (struct macro_buffer *tok, char *p, char *end)
 
 
 static int
-get_identifier (struct macro_buffer *tok, char *p, char *end)
+get_identifier (shared_macro_buffer *tok, const char *p, const char *end)
 {
   if (p < end
       && macro_is_identifier_nondigit (*p))
     {
-      char *tok_start = p;
+      const char *tok_start = p;
 
       while (p < end
-             && (macro_is_identifier_nondigit (*p)
-                 || macro_is_digit (*p)))
-        p++;
+            && (macro_is_identifier_nondigit (*p)
+                || macro_is_digit (*p)))
+       p++;
 
       set_token (tok, tok_start, p);
       tok->is_identifier = 1;
@@ -289,29 +275,29 @@ get_identifier (struct macro_buffer *tok, char *p, char *end)
 
 
 static int
-get_pp_number (struct macro_buffer *tok, char *p, char *end)
+get_pp_number (shared_macro_buffer *tok, const char *p, const char *end)
 {
   if (p < end
       && (macro_is_digit (*p)
-          || (*p == '.'
+         || (*p == '.'
              && p + 2 <= end
              && macro_is_digit (p[1]))))
     {
-      char *tok_start = p;
+      const char *tok_start = p;
 
       while (p < end)
-        {
+       {
          if (p + 2 <= end
              && strchr ("eEpP", *p)
              && (p[1] == '+' || p[1] == '-'))
-            p += 2;
-          else if (macro_is_digit (*p)
+           p += 2;
+         else if (macro_is_digit (*p)
                   || macro_is_identifier_nondigit (*p)
                   || *p == '.')
-            p++;
-          else
-            break;
-        }
+           p++;
+         else
+           break;
+       }
 
       set_token (tok, tok_start, p);
       return 1;
@@ -328,7 +314,8 @@ get_pp_number (struct macro_buffer *tok, char *p, char *end)
    Signal an error if it contains a malformed or incomplete character
    constant.  */
 static int
-get_character_constant (struct macro_buffer *tok, char *p, char *end)
+get_character_constant (shared_macro_buffer *tok,
+                       const char *p, const char *end)
 {
   /* ISO/IEC 9899:1999 (E)  Section 6.4.4.4  paragraph 1 
      But of course, what really matters is that we handle it the same
@@ -339,42 +326,42 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end)
          && (p[0] == 'L' || p[0] == 'u' || p[0] == 'U')
          && p[1] == '\''))
     {
-      char *tok_start = p;
+      const char *tok_start = p;
       int char_count = 0;
 
       if (*p == '\'')
-        p++;
+       p++;
       else if (*p == 'L' || *p == 'u' || *p == 'U')
-        p += 2;
+       p += 2;
       else
-        gdb_assert_not_reached ("unexpected character constant");
+       gdb_assert_not_reached ("unexpected character constant");
 
       for (;;)
-        {
-          if (p >= end)
-            error (_("Unmatched single quote."));
-          else if (*p == '\'')
-            {
-              if (!char_count)
-                error (_("A character constant must contain at least one "
-                       "character."));
-              p++;
-              break;
-            }
-          else if (*p == '\\')
-            {
+       {
+         if (p >= end)
+           error (_("Unmatched single quote."));
+         else if (*p == '\'')
+           {
+             if (!char_count)
+               error (_("A character constant must contain at least one "
+                      "character."));
+             p++;
+             break;
+           }
+         else if (*p == '\\')
+           {
              const char *s, *o;
 
              s = o = ++p;
              char_count += c_parse_escape (&s, NULL);
              p += s - o;
-            }
-          else
+           }
+         else
            {
              p++;
              char_count++;
            }
-        }
+       }
 
       set_token (tok, tok_start, p);
       return 1;
@@ -389,46 +376,46 @@ get_character_constant (struct macro_buffer *tok, char *p, char *end)
    literal, and return 1.  Otherwise, return zero.  Signal an error if
    it contains a malformed or incomplete string literal.  */
 static int
-get_string_literal (struct macro_buffer *tok, char *p, char *end)
+get_string_literal (shared_macro_buffer *tok, const char *p, const char *end)
 {
   if ((p + 1 <= end
        && *p == '"')
       || (p + 2 <= end
-          && (p[0] == 'L' || p[0] == 'u' || p[0] == 'U')
-          && p[1] == '"'))
+         && (p[0] == 'L' || p[0] == 'u' || p[0] == 'U')
+         && p[1] == '"'))
     {
-      char *tok_start = p;
+      const char *tok_start = p;
 
       if (*p == '"')
-        p++;
+       p++;
       else if (*p == 'L' || *p == 'u' || *p == 'U')
-        p += 2;
+       p += 2;
       else
-        gdb_assert_not_reached ("unexpected string literal");
+       gdb_assert_not_reached ("unexpected string literal");
 
       for (;;)
-        {
-          if (p >= end)
-            error (_("Unterminated string in expression."));
-          else if (*p == '"')
-            {
-              p++;
-              break;
-            }
-          else if (*p == '\n')
-            error (_("Newline characters may not appear in string "
-                   "constants."));
-          else if (*p == '\\')
-            {
+       {
+         if (p >= end)
+           error (_("Unterminated string in expression."));
+         else if (*p == '"')
+           {
+             p++;
+             break;
+           }
+         else if (*p == '\n')
+           error (_("Newline characters may not appear in string "
+                  "constants."));
+         else if (*p == '\\')
+           {
              const char *s, *o;
 
              s = o = ++p;
              c_parse_escape (&s, NULL);
              p += s - o;
-            }
-          else
-            p++;
-        }
+           }
+         else
+           p++;
+       }
 
       set_token (tok, tok_start, p);
       return 1;
@@ -439,7 +426,7 @@ get_string_literal (struct macro_buffer *tok, char *p, char *end)
 
 
 static int
-get_punctuator (struct macro_buffer *tok, char *p, char *end)
+get_punctuator (shared_macro_buffer *tok, const char *p, const char *end)
 {
   /* Here, speed is much less important than correctness and clarity.  */
 
@@ -472,21 +459,21 @@ get_punctuator (struct macro_buffer *tok, char *p, char *end)
   if (p + 1 <= end)
     {
       for (i = 0; punctuators[i]; i++)
-        {
-          const char *punctuator = punctuators[i];
-
-          if (p[0] == punctuator[0])
-            {
-              int len = strlen (punctuator);
-
-              if (p + len <= end
-                  && ! memcmp (p, punctuator, len))
-                {
-                  set_token (tok, p, p + len);
-                  return 1;
-                }
-            }
-        }
+       {
+         const char *punctuator = punctuators[i];
+
+         if (p[0] == punctuator[0])
+           {
+             int len = strlen (punctuator);
+
+             if (p + len <= end
+                 && ! memcmp (p, punctuator, len))
+               {
+                 set_token (tok, p, p + len);
+                 return 1;
+               }
+           }
+       }
     }
 
   return 0;
@@ -495,29 +482,27 @@ get_punctuator (struct macro_buffer *tok, char *p, char *end)
 
 /* Peel the next preprocessor token off of SRC, and put it in TOK.
    Mutate TOK to refer to the first token in SRC, and mutate SRC to
-   refer to the text after that token.  SRC must be a shared buffer;
-   the resulting TOK will be shared, pointing into the same string SRC
-   does.  Initialize TOK's last_token field.  Return non-zero if we
-   succeed, or 0 if we didn't find any more tokens in SRC.  */
+   refer to the text after that token.  The resulting TOK will point
+   into the same string SRC does.  Initialize TOK's last_token field.
+   Return non-zero if we succeed, or 0 if we didn't find any more
+   tokens in SRC.  */
+
 static int
-get_token (struct macro_buffer *tok,
-           struct macro_buffer *src)
+get_token (shared_macro_buffer *tok, shared_macro_buffer *src)
 {
-  char *p = src->text;
-  char *end = p + src->len;
-
-  gdb_assert (src->shared);
+  const char *p = src->text;
+  const char *end = p + src->len;
 
   /* From the ISO C standard, ISO/IEC 9899:1999 (E), section 6.4:
 
      preprocessing-token: 
-         header-name
-         identifier
-         pp-number
-         character-constant
-         string-literal
-         punctuator
-         each non-white-space character that cannot be one of the above
+        header-name
+        identifier
+        pp-number
+        character-constant
+        string-literal
+        punctuator
+        each non-white-space character that cannot be one of the above
 
      We don't have to deal with header-name tokens, since those can
      only occur after a #include, which we will never see.  */
@@ -528,37 +513,37 @@ get_token (struct macro_buffer *tok,
     else if (get_comment (tok, p, end))
       p += tok->len;
     else if (get_pp_number (tok, p, end)
-             || get_character_constant (tok, p, end)
-             || get_string_literal (tok, p, end)
-             /* Note: the grammar in the standard seems to be
-                ambiguous: L'x' can be either a wide character
-                constant, or an identifier followed by a normal
-                character constant.  By trying `get_identifier' after
-                we try get_character_constant and get_string_literal,
-                we give the wide character syntax precedence.  Now,
-                since GDB doesn't handle wide character constants
-                anyway, is this the right thing to do?  */
-             || get_identifier (tok, p, end)
-             || get_punctuator (tok, p, end))
+            || get_character_constant (tok, p, end)
+            || get_string_literal (tok, p, end)
+            /* Note: the grammar in the standard seems to be
+               ambiguous: L'x' can be either a wide character
+               constant, or an identifier followed by a normal
+               character constant.  By trying `get_identifier' after
+               we try get_character_constant and get_string_literal,
+               we give the wide character syntax precedence.  Now,
+               since GDB doesn't handle wide character constants
+               anyway, is this the right thing to do?  */
+            || get_identifier (tok, p, end)
+            || get_punctuator (tok, p, end))
       {
-        /* How many characters did we consume, including whitespace?  */
-        int consumed = p - src->text + tok->len;
+       /* How many characters did we consume, including whitespace?  */
+       int consumed = p - src->text + tok->len;
 
-        src->text += consumed;
-        src->len -= consumed;
-        return 1;
+       src->text += consumed;
+       src->len -= consumed;
+       return 1;
       }
     else 
       {
-        /* We have found a "non-whitespace character that cannot be
-           one of the above."  Make a token out of it.  */
-        int consumed;
-
-        set_token (tok, p, p + 1);
-        consumed = p - src->text + tok->len;
-        src->text += consumed;
-        src->len -= consumed;
-        return 1;
+       /* We have found a "non-whitespace character that cannot be
+          one of the above."  Make a token out of it.  */
+       int consumed;
+
+       set_token (tok, p, p + 1);
+       consumed = p - src->text + tok->len;
+       src->text += consumed;
+       src->len -= consumed;
+       return 1;
       }
 
   return 0;
@@ -585,18 +570,18 @@ get_token (struct macro_buffer *tok,
    fine to return with DEST set to "x y".  Similarly, "<" and "<" must
    yield "< <", not "<<", etc.  */
 static void
-append_tokens_without_splicing (struct macro_buffer *dest,
-                                struct macro_buffer *src)
+append_tokens_without_splicing (growable_macro_buffer *dest,
+                                shared_macro_buffer *src)
 {
   int original_dest_len = dest->len;
-  struct macro_buffer dest_tail, new_token;
+  shared_macro_buffer dest_tail, new_token;
 
   gdb_assert (src->last_token != -1);
   gdb_assert (dest->last_token != -1);
   
   /* First, just try appending the two, and call get_token to see if
      we got a splice.  */
-  appendmem (dest, src->text, src->len);
+  dest->appendmem (src->text, src->len);
 
   /* If DEST originally had no token abutting its end, then we can't
      have spliced anything, so we're done.  */
@@ -608,9 +593,8 @@ append_tokens_without_splicing (struct macro_buffer *dest,
 
   /* Set DEST_TAIL to point to the last token in DEST, followed by
      all the stuff we just appended.  */
-  init_shared_buffer (&dest_tail,
-                      dest->text + dest->last_token,
-                      dest->len - dest->last_token);
+  dest_tail.set_shared (dest->text + dest->last_token,
+                       dest->len - dest->last_token);
 
   /* Re-parse DEST's last token.  We know that DEST used to contain
      at least one token, so if it doesn't contain any after the
@@ -619,7 +603,7 @@ append_tokens_without_splicing (struct macro_buffer *dest,
      the first time.  This is not a bug fix.)  */
   if (get_token (&new_token, &dest_tail)
       && (new_token.text + new_token.len
-          == dest->text + original_dest_len))
+         == dest->text + original_dest_len))
     {
       /* No splice, so we're done.  */
       dest->last_token = original_dest_len + src->last_token;
@@ -630,17 +614,16 @@ append_tokens_without_splicing (struct macro_buffer *dest,
      its original length and try again, but separate the texts with a
      space.  */
   dest->len = original_dest_len;
-  appendc (dest, ' ');
-  appendmem (dest, src->text, src->len);
+  dest->appendc (' ');
+  dest->appendmem (src->text, src->len);
 
-  init_shared_buffer (&dest_tail,
-                      dest->text + dest->last_token,
-                      dest->len - dest->last_token);
+  dest_tail.set_shared (dest->text + dest->last_token,
+                       dest->len - dest->last_token);
 
   /* Try to re-parse DEST's last token, as above.  */
   if (get_token (&new_token, &dest_tail)
       && (new_token.text + new_token.len
-          == dest->text + original_dest_len))
+         == dest->text + original_dest_len))
     {
       /* No splice, so we're done.  */
       dest->last_token = original_dest_len + 1 + src->last_token;
@@ -650,14 +633,14 @@ append_tokens_without_splicing (struct macro_buffer *dest,
   /* As far as I know, there's no case where inserting a space isn't
      enough to prevent a splice.  */
   internal_error (__FILE__, __LINE__,
-                  _("unable to avoid splicing tokens during macro expansion"));
+                 _("unable to avoid splicing tokens during macro expansion"));
 }
 
 /* Stringify an argument, and insert it into DEST.  ARG is the text to
    stringify; it is LEN bytes long.  */
 
 static void
-stringify (struct macro_buffer *dest, const char *arg, int len)
+stringify (growable_macro_buffer *dest, const char *arg, int len)
 {
   /* Trim initial whitespace from ARG.  */
   while (len > 0 && macro_is_whitespace (*arg))
@@ -671,7 +654,7 @@ stringify (struct macro_buffer *dest, const char *arg, int len)
     --len;
 
   /* Insert the string.  */
-  appendc (dest, '"');
+  dest->appendc ('"');
   while (len > 0)
     {
       /* We could try to handle strange cases here, like control
@@ -679,7 +662,7 @@ stringify (struct macro_buffer *dest, const char *arg, int len)
       if (macro_is_whitespace (*arg))
        {
          /* Replace a sequence of whitespace with a single space.  */
-         appendc (dest, ' ');
+         dest->appendc (' ');
          while (len > 1 && macro_is_whitespace (arg[1]))
            {
              ++arg;
@@ -688,31 +671,30 @@ stringify (struct macro_buffer *dest, const char *arg, int len)
        }
       else if (*arg == '\\' || *arg == '"')
        {
-         appendc (dest, '\\');
-         appendc (dest, *arg);
+         dest->appendc ('\\');
+         dest->appendc (*arg);
        }
       else
-       appendc (dest, *arg);
+       dest->appendc (*arg);
       ++arg;
       --len;
     }
-  appendc (dest, '"');
+  dest->appendc ('"');
   dest->last_token = dest->len;
 }
 
 /* See macroexp.h.  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 macro_stringify (const char *str)
 {
-  struct macro_buffer buffer;
   int len = strlen (str);
+  growable_macro_buffer buffer (len);
 
-  init_buffer (&buffer, len);
   stringify (&buffer, str, len);
-  appendc (&buffer, '\0');
+  buffer.appendc ('\0');
 
-  return free_buffer_return_text (&buffer);
+  return buffer.release ();
 }
 
 \f
@@ -759,22 +741,19 @@ currently_rescanning (struct macro_name_list *list, const char *name)
    baz).
 
    If SRC doesn't start with an open paren ( token at all, return
-   zero, leave SRC unchanged, and don't set *ARGC_P to anything.
+   false, leave SRC unchanged, and don't set *ARGS_PTR to anything.
 
    If SRC doesn't contain a properly terminated argument list, then
    raise an error.
-   
+
    For a variadic macro, NARGS holds the number of formal arguments to
    the macro.  For a GNU-style variadic macro, this should be the
    number of named arguments.  For a non-variadic macro, NARGS should
    be -1.
 
-   Otherwise, return a pointer to the first element of an array of
-   macro buffers referring to the argument texts, and set *ARGC_P to
-   the number of arguments we found --- the number of elements in the
-   array.  The macro buffers share their text with SRC, and their
-   last_token fields are initialized.  The array is allocated with
-   xmalloc, and the caller is responsible for freeing it.
+   Otherwise, return true and set *ARGS_PTR to a vector of macro
+   buffers referring to the argument texts.  The macro buffers share
+   their text with SRC, and their last_token fields are initialized.
 
    NOTE WELL: if SRC starts with a open paren ( token followed
    immediately by a close paren ) token (e.g., the invocation looks
@@ -787,131 +766,105 @@ currently_rescanning (struct macro_name_list *list, const char *name)
    Consume the tokens from SRC; after this call, SRC contains the text
    following the invocation.  */
 
-static struct macro_buffer *
-gather_arguments (const char *name, struct macro_buffer *src,
-                 int nargs, int *argc_p)
+static bool
+gather_arguments (const char *name, shared_macro_buffer *src, int nargs,
+                 std::vector<shared_macro_buffer> *args_ptr)
 {
-  struct macro_buffer tok;
-  int args_len, args_size;
-  struct macro_buffer *args = NULL;
-  struct cleanup *back_to = make_cleanup (free_current_contents, &args);
+  shared_macro_buffer tok;
+  std::vector<shared_macro_buffer> args;
 
   /* Does SRC start with an opening paren token?  Read from a copy of
      SRC, so SRC itself is unaffected if we don't find an opening
      paren.  */
   {
-    struct macro_buffer temp;
-
-    init_shared_buffer (&temp, src->text, src->len);
+    shared_macro_buffer temp (src->text, src->len);
 
     if (! get_token (&tok, &temp)
-        || tok.len != 1
-        || tok.text[0] != '(')
-      {
-        discard_cleanups (back_to);
-        return 0;
-      }
+       || tok.len != 1
+       || tok.text[0] != '(')
+      return false;
   }
 
   /* Consume SRC's opening paren.  */
   get_token (&tok, src);
 
-  args_len = 0;
-  args_size = 6;
-  args = XNEWVEC (struct macro_buffer, args_size);
-
   for (;;)
     {
-      struct macro_buffer *arg;
+      shared_macro_buffer *arg;
       int depth;
 
-      /* Make sure we have room for the next argument.  */
-      if (args_len >= args_size)
-        {
-          args_size *= 2;
-          args = XRESIZEVEC (struct macro_buffer, args, args_size);
-        }
-
       /* Initialize the next argument.  */
-      arg = &args[args_len++];
+      args.emplace_back ();
+      arg = &args.back ();
       set_token (arg, src->text, src->text);
 
       /* Gather the argument's tokens.  */
       depth = 0;
       for (;;)
-        {
-          if (! get_token (&tok, src))
-            error (_("Malformed argument list for macro `%s'."), name);
-      
-          /* Is tok an opening paren?  */
-          if (tok.len == 1 && tok.text[0] == '(')
-            depth++;
-
-          /* Is tok is a closing paren?  */
-          else if (tok.len == 1 && tok.text[0] == ')')
-            {
-              /* If it's a closing paren at the top level, then that's
-                 the end of the argument list.  */
-              if (depth == 0)
-                {
+       {
+         if (! get_token (&tok, src))
+           error (_("Malformed argument list for macro `%s'."), name);
+
+         /* Is tok an opening paren?  */
+         if (tok.len == 1 && tok.text[0] == '(')
+           depth++;
+
+         /* Is tok is a closing paren?  */
+         else if (tok.len == 1 && tok.text[0] == ')')
+           {
+             /* If it's a closing paren at the top level, then that's
+                the end of the argument list.  */
+             if (depth == 0)
+               {
                  /* In the varargs case, the last argument may be
                     missing.  Add an empty argument in this case.  */
-                 if (nargs != -1 && args_len == nargs - 1)
+                 if (nargs != -1 && args.size () == nargs - 1)
                    {
-                     /* Make sure we have room for the argument.  */
-                     if (args_len >= args_size)
-                       {
-                         args_size++;
-                         args = XRESIZEVEC (struct macro_buffer, args,
-                                            args_size);
-                       }
-                     arg = &args[args_len++];
+                     args.emplace_back ();
+                     arg = &args.back ();
                      set_token (arg, src->text, src->text);
                    }
 
-                  discard_cleanups (back_to);
-                  *argc_p = args_len;
-                  return args;
-                }
-
-              depth--;
-            }
-
-          /* If tok is a comma at top level, then that's the end of
-             the current argument.  However, if we are handling a
-             variadic macro and we are computing the last argument, we
-             want to include the comma and remaining tokens.  */
-          else if (tok.len == 1 && tok.text[0] == ',' && depth == 0
-                  && (nargs == -1 || args_len < nargs))
-            break;
-
-          /* Extend the current argument to enclose this token.  If
-             this is the current argument's first token, leave out any
-             leading whitespace, just for aesthetics.  */
-          if (arg->len == 0)
-            {
-              arg->text = tok.text;
-              arg->len = tok.len;
-              arg->last_token = 0;
-            }
-          else
-            {
-              arg->len = (tok.text + tok.len) - arg->text;
-              arg->last_token = tok.text - arg->text;
-            }
-        }
+                 *args_ptr = std::move (args);
+                 return true;
+               }
+
+             depth--;
+           }
+
+         /* If tok is a comma at top level, then that's the end of
+            the current argument.  However, if we are handling a
+            variadic macro and we are computing the last argument, we
+            want to include the comma and remaining tokens.  */
+         else if (tok.len == 1 && tok.text[0] == ',' && depth == 0
+                  && (nargs == -1 || args.size () < nargs))
+           break;
+
+         /* Extend the current argument to enclose this token.  If
+            this is the current argument's first token, leave out any
+            leading whitespace, just for aesthetics.  */
+         if (arg->len == 0)
+           {
+             arg->text = tok.text;
+             arg->len = tok.len;
+             arg->last_token = 0;
+           }
+         else
+           {
+             arg->len = (tok.text + tok.len) - arg->text;
+             arg->last_token = tok.text - arg->text;
+           }
+       }
     }
 }
 
 
 /* The `expand' and `substitute_args' functions both invoke `scan'
    recursively, so we need a forward declaration somewhere.  */
-static void scan (struct macro_buffer *dest,
-                  struct macro_buffer *src,
-                  struct macro_name_list *no_loop,
-                  macro_lookup_ftype *lookup_func,
-                  void *lookup_baton);
-
+static void scan (growable_macro_buffer *dest,
+                 shared_macro_buffer *src,
+                 struct macro_name_list *no_loop,
+                 const macro_scope &scope);
 
 /* A helper function for substitute_args.
    
@@ -925,8 +878,8 @@ static void scan (struct macro_buffer *dest,
    index.  If TOK is not an argument, return -1.  */
 
 static int
-find_parameter (const struct macro_buffer *tok,
-               int is_varargs, const struct macro_buffer *va_arg_name,
+find_parameter (const shared_macro_buffer *tok,
+               int is_varargs, const shared_macro_buffer *va_arg_name,
                int argc, const char * const *argv)
 {
   int i;
@@ -950,11 +903,11 @@ find_parameter (const struct macro_buffer *tok,
    updates the passed-in state variables.  */
 
 static void
-get_next_token_for_substitution (struct macro_buffer *replacement_list,
-                                struct macro_buffer *token,
-                                char **start,
-                                struct macro_buffer *lookahead,
-                                char **lookahead_start,
+get_next_token_for_substitution (shared_macro_buffer *replacement_list,
+                                shared_macro_buffer *token,
+                                const char **start,
+                                shared_macro_buffer *lookahead,
+                                const char **lookahead_start,
                                 int *lookahead_valid,
                                 bool *keep_going)
 {
@@ -971,7 +924,7 @@ get_next_token_for_substitution (struct macro_buffer *replacement_list,
 }
 
 /* Given the macro definition DEF, being invoked with the actual
-   arguments given by ARGC and ARGV, substitute the arguments into the
+   arguments given by ARGV, substitute the arguments into the
    replacement list, and store the result in DEST.
 
    IS_VARARGS should be true if DEF is a varargs macro.  In this case,
@@ -986,30 +939,28 @@ get_next_token_for_substitution (struct macro_buffer *replacement_list,
    NO_LOOP.  */
 
 static void
-substitute_args (struct macro_buffer *dest, 
-                 struct macro_definition *def,
-                int is_varargs, const struct macro_buffer *va_arg_name,
-                 int argc, struct macro_buffer *argv,
-                 struct macro_name_list *no_loop,
-                 macro_lookup_ftype *lookup_func,
-                 void *lookup_baton)
+substitute_args (growable_macro_buffer *dest,
+                struct macro_definition *def,
+                int is_varargs, const shared_macro_buffer *va_arg_name,
+                const std::vector<shared_macro_buffer> &argv,
+                struct macro_name_list *no_loop,
+                const macro_scope &scope)
 {
-  /* A macro buffer for the macro's replacement list.  */
-  struct macro_buffer replacement_list;
   /* The token we are currently considering.  */
-  struct macro_buffer tok;
+  shared_macro_buffer tok;
   /* The replacement list's pointer from just before TOK was lexed.  */
-  char *original_rl_start;
+  const char *original_rl_start;
   /* We have a single lookahead token to handle token splicing.  */
-  struct macro_buffer lookahead;
+  shared_macro_buffer lookahead;
   /* The lookahead token might not be valid.  */
   int lookahead_valid;
   /* The replacement list's pointer from just before LOOKAHEAD was
      lexed.  */
-  char *lookahead_rl_start;
+  const char *lookahead_rl_start;
 
-  init_shared_buffer (&replacement_list, def->replacement,
-                      strlen (def->replacement));
+  /* A macro buffer for the macro's replacement list.  */
+  shared_macro_buffer replacement_list (def->replacement,
+                                       strlen (def->replacement));
 
   gdb_assert (dest->len == 0);
   dest->last_token = 0;
@@ -1037,7 +988,7 @@ substitute_args (struct macro_buffer *dest,
                                        &keep_going))
     {
       bool token_is_vaopt = (tok.len == 10
-                            && strncmp (tok.text, "__VA_OPT__", 10) == 0);
+                            && startswith (tok.text, "__VA_OPT__"));
 
       if (vaopt_state > 0)
        {
@@ -1066,7 +1017,7 @@ substitute_args (struct macro_buffer *dest,
 
          /* If __VA_ARGS__ is empty, then drop the contents of
             __VA_OPT__.  */
-         if (argv[argc - 1].len == 0)
+         if (argv.back ().len == 0)
            continue;
        }
       else if (token_is_vaopt)
@@ -1079,16 +1030,16 @@ substitute_args (struct macro_buffer *dest,
        }
 
       /* Just for aesthetics.  If we skipped some whitespace, copy
-         that to DEST.  */
+        that to DEST.  */
       if (tok.text > original_rl_start)
-        {
-          appendmem (dest, original_rl_start, tok.text - original_rl_start);
-          dest->last_token = dest->len;
-        }
+       {
+         dest->appendmem (original_rl_start, tok.text - original_rl_start);
+         dest->last_token = dest->len;
+       }
 
       /* Is this token the stringification operator?  */
       if (tok.len == 1
-          && tok.text[0] == '#')
+         && tok.text[0] == '#')
        {
          int arg;
 
@@ -1135,9 +1086,9 @@ substitute_args (struct macro_buffer *dest,
                                        def->argc, def->argv);
 
              if (arg != -1)
-               appendmem (dest, argv[arg].text, argv[arg].len);
+               dest->appendmem (argv[arg].text, argv[arg].len);
              else
-               appendmem (dest, tok.text, tok.len);
+               dest->appendmem (tok.text, tok.len);
            }
 
          /* Apply a possible sequence of ## operators.  */
@@ -1160,8 +1111,8 @@ substitute_args (struct macro_buffer *dest,
                  if (! (is_varargs
                         && tok.len == va_arg_name->len
                         && !memcmp (tok.text, va_arg_name->text, tok.len)
-                        && argv[argc - 1].len == 0))
-                   appendmem (dest, ",", 1);
+                        && argv.back ().len == 0))
+                   dest->appendmem (",", 1);
                  prev_was_comma = 0;
                }
 
@@ -1175,9 +1126,9 @@ substitute_args (struct macro_buffer *dest,
                                            def->argc, def->argv);
 
                  if (arg != -1)
-                   appendmem (dest, argv[arg].text, argv[arg].len);
+                   dest->appendmem (argv[arg].text, argv[arg].len);
                  else
-                   appendmem (dest, tok.text, tok.len);
+                   dest->appendmem (tok.text, tok.len);
                }
 
              /* Now read another token.  If it is another splice, we
@@ -1198,10 +1149,10 @@ substitute_args (struct macro_buffer *dest,
          if (prev_was_comma)
            {
              /* We saw a comma.  Insert it now.  */
-             appendmem (dest, ",", 1);
+             dest->appendmem (",", 1);
            }
 
-          dest->last_token = dest->len;
+         dest->last_token = dest->len;
          if (finished)
            lookahead_valid = 0;
          else
@@ -1221,15 +1172,13 @@ substitute_args (struct macro_buffer *dest,
 
          if (arg != -1)
            {
-             struct macro_buffer arg_src;
-
              /* Expand any macro invocations in the argument text,
                 and append the result to dest.  Remember that scan
                 mutates its source, so we need to scan a new buffer
                 referring to the argument's text, not the argument
                 itself.  */
-             init_shared_buffer (&arg_src, argv[arg].text, argv[arg].len);
-             scan (dest, &arg_src, no_loop, lookup_func, lookup_baton);
+             shared_macro_buffer arg_src (argv[arg].text, argv[arg].len);
+             scan (dest, &arg_src, no_loop, scope);
              substituted = 1;
            }
 
@@ -1255,12 +1204,11 @@ substitute_args (struct macro_buffer *dest,
    we don't expand it.)  If we return zero, leave SRC unchanged.  */
 static int
 expand (const char *id,
-        struct macro_definition *def, 
-        struct macro_buffer *dest,
-        struct macro_buffer *src,
-        struct macro_name_list *no_loop,
-        macro_lookup_ftype *lookup_func,
-        void *lookup_baton)
+       struct macro_definition *def,
+       growable_macro_buffer *dest,
+       shared_macro_buffer *src,
+       struct macro_name_list *no_loop,
+       const macro_scope &scope)
 {
   struct macro_name_list new_no_loop;
 
@@ -1275,22 +1223,15 @@ expand (const char *id,
   /* What kind of macro are we expanding?  */
   if (def->kind == macro_object_like)
     {
-      struct macro_buffer replacement_list;
+      shared_macro_buffer replacement_list (def->replacement,
+                                           strlen (def->replacement));
 
-      init_shared_buffer (&replacement_list, def->replacement,
-                          strlen (def->replacement));
-
-      scan (dest, &replacement_list, &new_no_loop, lookup_func, lookup_baton);
+      scan (dest, &replacement_list, &new_no_loop, scope);
       return 1;
     }
   else if (def->kind == macro_function_like)
     {
-      struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-      int argc = 0;
-      struct macro_buffer *argv = NULL;
-      struct macro_buffer substituted;
-      struct macro_buffer substituted_src;
-      struct macro_buffer va_arg_name = {0};
+      shared_macro_buffer va_arg_name;
       int is_varargs = 0;
 
       if (def->argc >= 1)
@@ -1299,8 +1240,7 @@ expand (const char *id,
            {
              /* In C99-style varargs, substitution is done using
                 __VA_ARGS__.  */
-             init_shared_buffer (&va_arg_name, "__VA_ARGS__",
-                                 strlen ("__VA_ARGS__"));
+             va_arg_name.set_shared ("__VA_ARGS__", strlen ("__VA_ARGS__"));
              is_varargs = 1;
            }
          else
@@ -1313,70 +1253,60 @@ expand (const char *id,
                  /* In GNU-style varargs, the name of the
                     substitution parameter is the name of the formal
                     argument without the "...".  */
-                 init_shared_buffer (&va_arg_name,
-                                     def->argv[def->argc - 1],
-                                     len - 3);
+                 va_arg_name.set_shared (def->argv[def->argc - 1], len - 3);
                  is_varargs = 1;
                }
            }
        }
 
-      make_cleanup (free_current_contents, &argv);
-      argv = gather_arguments (id, src, is_varargs ? def->argc : -1,
-                              &argc);
-
+      std::vector<shared_macro_buffer> argv;
       /* If we couldn't find any argument list, then we don't expand
-         this macro.  */
-      if (! argv)
-        {
-          do_cleanups (back_to);
-          return 0;
-        }
+        this macro.  */
+      if (!gather_arguments (id, src, is_varargs ? def->argc : -1,
+                            &argv))
+       return 0;
 
       /* Check that we're passing an acceptable number of arguments for
-         this macro.  */
-      if (argc != def->argc)
-        {
-         if (is_varargs && argc >= def->argc - 1)
+        this macro.  */
+      if (argv.size () != def->argc)
+       {
+         if (is_varargs && argv.size () >= def->argc - 1)
            {
              /* Ok.  */
            }
-          /* Remember that a sequence of tokens like "foo()" is a
-             valid invocation of a macro expecting either zero or one
-             arguments.  */
-          else if (! (argc == 1
+         /* Remember that a sequence of tokens like "foo()" is a
+            valid invocation of a macro expecting either zero or one
+            arguments.  */
+         else if (! (argv.size () == 1
                      && argv[0].len == 0
                      && def->argc == 0))
-            error (_("Wrong number of arguments to macro `%s' "
-                   "(expected %d, got %d)."),
-                   id, def->argc, argc);
-        }
+           error (_("Wrong number of arguments to macro `%s' "
+                  "(expected %d, got %d)."),
+                  id, def->argc, int (argv.size ()));
+       }
 
       /* Note that we don't expand macro invocations in the arguments
-         yet --- we let subst_args take care of that.  Parameters that
-         appear as operands of the stringifying operator "#" or the
-         splicing operator "##" don't get macro references expanded,
-         so we can't really tell whether it's appropriate to macro-
-         expand an argument until we see how it's being used.  */
-      init_buffer (&substituted, 0);
-      make_cleanup (cleanup_macro_buffer, &substituted);
+        yet --- we let subst_args take care of that.  Parameters that
+        appear as operands of the stringifying operator "#" or the
+        splicing operator "##" don't get macro references expanded,
+        so we can't really tell whether it's appropriate to macro-
+        expand an argument until we see how it's being used.  */
+      growable_macro_buffer substituted (0);
       substitute_args (&substituted, def, is_varargs, &va_arg_name,
-                      argc, argv, no_loop, lookup_func, lookup_baton);
+                      argv, no_loop, scope);
 
       /* Now `substituted' is the macro's replacement list, with all
-         argument values substituted into it properly.  Re-scan it for
-         macro references, but don't expand invocations of this macro.
-
-         We create a new buffer, `substituted_src', which points into
-         `substituted', and scan that.  We can't scan `substituted'
-         itself, since the tokenization process moves the buffer's
-         text pointer around, and we still need to be able to find
-         `substituted's original text buffer after scanning it so we
-         can free it.  */
-      init_shared_buffer (&substituted_src, substituted.text, substituted.len);
-      scan (dest, &substituted_src, &new_no_loop, lookup_func, lookup_baton);
-
-      do_cleanups (back_to);
+        argument values substituted into it properly.  Re-scan it for
+        macro references, but don't expand invocations of this macro.
+
+        We create a new buffer, `substituted_src', which points into
+        `substituted', and scan that.  We can't scan `substituted'
+        itself, since the tokenization process moves the buffer's
+        text pointer around, and we still need to be able to find
+        `substituted's original text buffer after scanning it so we
+        can free it.  */
+      shared_macro_buffer substituted_src (substituted.text, substituted.len);
+      scan (dest, &substituted_src, &new_no_loop, scope);
 
       return 1;
     }
@@ -1386,51 +1316,35 @@ expand (const char *id,
 
 
 /* If the single token in SRC_FIRST followed by the tokens in SRC_REST
-   constitute a macro invokation not forbidden in NO_LOOP, append its
+   constitute a macro invocation not forbidden in NO_LOOP, append its
    expansion to DEST and return non-zero.  Otherwise, return zero, and
    leave DEST unchanged.
 
-   SRC_FIRST and SRC_REST must be shared buffers; DEST must not be one.
    SRC_FIRST must be a string built by get_token.  */
 static int
-maybe_expand (struct macro_buffer *dest,
-              struct macro_buffer *src_first,
-              struct macro_buffer *src_rest,
-              struct macro_name_list *no_loop,
-              macro_lookup_ftype *lookup_func,
-              void *lookup_baton)
+maybe_expand (growable_macro_buffer *dest,
+             shared_macro_buffer *src_first,
+             shared_macro_buffer *src_rest,
+             struct macro_name_list *no_loop,
+             const macro_scope &scope)
 {
-  gdb_assert (src_first->shared);
-  gdb_assert (src_rest->shared);
-  gdb_assert (! dest->shared);
-
   /* Is this token an identifier?  */
   if (src_first->is_identifier)
     {
       /* Make a null-terminated copy of it, since that's what our
-         lookup function expects.  */
-      char *id = (char *) xmalloc (src_first->len + 1);
-      struct cleanup *back_to = make_cleanup (xfree, id);
+        lookup function expects.  */
+      std::string id (src_first->text, src_first->len);
 
-      memcpy (id, src_first->text, src_first->len);
-      id[src_first->len] = 0;
-          
       /* If we're currently re-scanning the result of expanding
-         this macro, don't expand it again.  */
-      if (! currently_rescanning (no_loop, id))
-        {
-          /* Does this identifier have a macro definition in scope?  */
-          struct macro_definition *def = lookup_func (id, lookup_baton);
-
-          if (def && expand (id, def, dest, src_rest, no_loop,
-                             lookup_func, lookup_baton))
-            {
-              do_cleanups (back_to);
-              return 1;
-            }
-        }
-
-      do_cleanups (back_to);
+        this macro, don't expand it again.  */
+      if (! currently_rescanning (no_loop, id.c_str ()))
+       {
+         /* Does this identifier have a macro definition in scope?  */
+         macro_definition *def = standard_macro_lookup (id.c_str (), scope);
+
+         if (def && expand (id.c_str (), def, dest, src_rest, no_loop, scope))
+           return 1;
+       }
     }
 
   return 0;
@@ -1439,122 +1353,99 @@ maybe_expand (struct macro_buffer *dest,
 
 /* Expand macro references in SRC, appending the results to DEST.
    Assume we are re-scanning the result of expanding the macros named
-   in NO_LOOP, and don't try to re-expand references to them.
+   in NO_LOOP, and don't try to re-expand references to them.  */
 
-   SRC must be a shared buffer; DEST must not be one.  */
 static void
-scan (struct macro_buffer *dest,
-      struct macro_buffer *src,
+scan (growable_macro_buffer *dest,
+      shared_macro_buffer *src,
       struct macro_name_list *no_loop,
-      macro_lookup_ftype *lookup_func,
-      void *lookup_baton)
+      const macro_scope &scope)
 {
-  gdb_assert (src->shared);
-  gdb_assert (! dest->shared);
 
   for (;;)
     {
-      struct macro_buffer tok;
-      char *original_src_start = src->text;
+      shared_macro_buffer tok;
+      const char *original_src_start = src->text;
 
       /* Find the next token in SRC.  */
       if (! get_token (&tok, src))
-        break;
+       break;
 
       /* Just for aesthetics.  If we skipped some whitespace, copy
-         that to DEST.  */
+        that to DEST.  */
       if (tok.text > original_src_start)
-        {
-          appendmem (dest, original_src_start, tok.text - original_src_start);
-          dest->last_token = dest->len;
-        }
-
-      if (! maybe_expand (dest, &tok, src, no_loop, lookup_func, lookup_baton))
-        /* We didn't end up expanding tok as a macro reference, so
-           simply append it to dest.  */
-        append_tokens_without_splicing (dest, &tok);
+       {
+         dest->appendmem (original_src_start, tok.text - original_src_start);
+         dest->last_token = dest->len;
+       }
+
+      if (! maybe_expand (dest, &tok, src, no_loop, scope))
+       /* We didn't end up expanding tok as a macro reference, so
+          simply append it to dest.  */
+       append_tokens_without_splicing (dest, &tok);
     }
 
   /* Just for aesthetics.  If there was any trailing whitespace in
      src, copy it to dest.  */
   if (src->len)
     {
-      appendmem (dest, src->text, src->len);
+      dest->appendmem (src->text, src->len);
       dest->last_token = dest->len;
     }
 }
 
 
-char *
-macro_expand (const char *source,
-              macro_lookup_ftype *lookup_func,
-              void *lookup_func_baton)
+gdb::unique_xmalloc_ptr<char>
+macro_expand (const char *source, const macro_scope &scope)
 {
-  struct macro_buffer src, dest;
-  struct cleanup *back_to;
+  shared_macro_buffer src (source, strlen (source));
 
-  init_shared_buffer (&src, source, strlen (source));
-
-  init_buffer (&dest, 0);
+  growable_macro_buffer dest (0);
   dest.last_token = 0;
-  back_to = make_cleanup (cleanup_macro_buffer, &dest);
 
-  scan (&dest, &src, 0, lookup_func, lookup_func_baton);
+  scan (&dest, &src, 0, scope);
 
-  appendc (&dest, '\0');
+  dest.appendc ('\0');
 
-  discard_cleanups (back_to);
-  return dest.text;
+  return dest.release ();
 }
 
 
-char *
-macro_expand_once (const char *source,
-                   macro_lookup_ftype *lookup_func,
-                   void *lookup_func_baton)
+gdb::unique_xmalloc_ptr<char>
+macro_expand_once (const char *source, const macro_scope &scope)
 {
   error (_("Expand-once not implemented yet."));
 }
 
-
-char *
-macro_expand_next (const char **lexptr,
-                   macro_lookup_ftype *lookup_func,
-                   void *lookup_baton)
+gdb::unique_xmalloc_ptr<char>
+macro_expand_next (const char **lexptr, const macro_scope &scope)
 {
-  struct macro_buffer src, dest, tok;
-  struct cleanup *back_to;
+  shared_macro_buffer tok;
 
   /* Set up SRC to refer to the input text, pointed to by *lexptr.  */
-  init_shared_buffer (&src, *lexptr, strlen (*lexptr));
+  shared_macro_buffer src (*lexptr, strlen (*lexptr));
 
   /* Set up DEST to receive the expansion, if there is one.  */
-  init_buffer (&dest, 0);
+  growable_macro_buffer dest (0);
   dest.last_token = 0;
-  back_to = make_cleanup (cleanup_macro_buffer, &dest);
 
   /* Get the text's first preprocessing token.  */
   if (! get_token (&tok, &src))
-    {
-      do_cleanups (back_to);
-      return 0;
-    }
+    return nullptr;
 
   /* If it's a macro invocation, expand it.  */
-  if (maybe_expand (&dest, &tok, &src, 0, lookup_func, lookup_baton))
+  if (maybe_expand (&dest, &tok, &src, 0, scope))
     {
       /* It was a macro invocation!  Package up the expansion as a
-         null-terminated string and return it.  Set *lexptr to the
-         start of the next token in the input.  */
-      appendc (&dest, '\0');
-      discard_cleanups (back_to);
+        null-terminated string and return it.  Set *lexptr to the
+        start of the next token in the input.  */
+      dest.appendc ('\0');
       *lexptr = src.text;
-      return dest.text;
+      return dest.release ();
     }
   else
     {
       /* It wasn't a macro invocation.  */
-      do_cleanups (back_to);
-      return 0;
+      return nullptr;
     }
 }
This page took 0.046158 seconds and 4 git commands to generate.