mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-06 12:09:26 +08:00
Class-ify macro_buffer
This patch changes macro_buffer to be a bit more of a C++ class, adding constructors, a destructor, and some members. Then this is used to remove various cleanups in macroexp.c. 2018-02-08 Tom Tromey <tom@tromey.com> * macroexp.c (struct macro_buffer): Add initializers for some members. (init_buffer, init_shared_buffer, free_buffer) (free_buffer_return_text): Remove. (macro_buffer): New constructors. (~macro_buffer): New destructor. (macro_buffer::set_shared): New method. (macro_buffer::resize_buffer, macro_buffer::appendc) (macro_buffer::appendmem): Now methods, not free functions. (set_token, append_tokens_without_splicing, stringify) (macro_stringify): Update. (gather_arguments): Change return type. Remove argc_p argument, add args_ptr argument. Use std::vector. (substitute_args): Remove argc argument. Accept std::vector. (expand): Update. Use std::vector. (scan, macro_expand, macro_expand_next): Update.
This commit is contained in:
parent
f6c2623eb8
commit
1739cf248f
@ -1,3 +1,22 @@
|
||||
2018-02-08 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* macroexp.c (struct macro_buffer): Add initializers for some
|
||||
members.
|
||||
(init_buffer, init_shared_buffer, free_buffer)
|
||||
(free_buffer_return_text): Remove.
|
||||
(macro_buffer): New constructors.
|
||||
(~macro_buffer): New destructor.
|
||||
(macro_buffer::set_shared): New method.
|
||||
(macro_buffer::resize_buffer, macro_buffer::appendc)
|
||||
(macro_buffer::appendmem): Now methods, not free functions.
|
||||
(set_token, append_tokens_without_splicing, stringify)
|
||||
(macro_stringify): Update.
|
||||
(gather_arguments): Change return type. Remove argc_p argument,
|
||||
add args_ptr argument. Use std::vector.
|
||||
(substitute_args): Remove argc argument. Accept std::vector.
|
||||
(expand): Update. Use std::vector.
|
||||
(scan, macro_expand, macro_expand_next): Update.
|
||||
|
||||
2018-02-08 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* symtab.c (default_collect_symbol_completion_matches_break_on):
|
||||
|
436
gdb/macroexp.c
436
gdb/macroexp.c
@ -65,123 +65,112 @@ 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;
|
||||
|
||||
|
||||
macro_buffer ()
|
||||
: text (NULL),
|
||||
len (0),
|
||||
size (0),
|
||||
shared (false)
|
||||
{
|
||||
}
|
||||
|
||||
/* 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 macro_buffer (int n)
|
||||
: len (0),
|
||||
size (n),
|
||||
shared (false)
|
||||
{
|
||||
if (n > 0)
|
||||
text = (char *) xmalloc (n);
|
||||
else
|
||||
text = NULL;
|
||||
}
|
||||
|
||||
/* Set the macro buffer to refer to the LEN bytes at ADDR, as a
|
||||
shared substring. */
|
||||
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 = (char *) addr;
|
||||
len = len_;
|
||||
size = 0;
|
||||
shared = true;
|
||||
}
|
||||
|
||||
~macro_buffer ()
|
||||
{
|
||||
if (! shared && size)
|
||||
xfree (text);
|
||||
}
|
||||
|
||||
/* Release the text of the buffer to the caller, which is now
|
||||
responsible for freeing it. */
|
||||
char *release ()
|
||||
{
|
||||
gdb_assert (! shared);
|
||||
gdb_assert (size);
|
||||
char *result = text;
|
||||
text = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Resize the buffer to be at least N bytes long. Raise an error if
|
||||
the buffer shouldn't be resized. */
|
||||
void resize_buffer (int n)
|
||||
{
|
||||
/* We shouldn't be trying to resize shared strings. */
|
||||
gdb_assert (! shared);
|
||||
|
||||
if (size == 0)
|
||||
size = n;
|
||||
else
|
||||
while (size <= n)
|
||||
size *= 2;
|
||||
|
||||
text = (char *) xrealloc (text, size);
|
||||
}
|
||||
|
||||
/* Append the character C to the buffer. */
|
||||
void appendc (int c)
|
||||
{
|
||||
int new_len = len + 1;
|
||||
|
||||
if (new_len > size)
|
||||
resize_buffer (new_len);
|
||||
|
||||
text[len] = c;
|
||||
len = new_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 > size)
|
||||
resize_buffer (new_len);
|
||||
|
||||
memcpy (text + len, addr, count);
|
||||
len = new_len;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* 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 *BUF to refer to the LEN bytes at ADDR, as a
|
||||
shared substring. */
|
||||
|
||||
static void
|
||||
init_shared_buffer (struct macro_buffer *buf, const char *addr, int len)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* Like free_buffer, but return the text as an xstrdup()d string.
|
||||
This only exists to try to make the API relatively clean. */
|
||||
|
||||
static char *
|
||||
free_buffer_return_text (struct macro_buffer *b)
|
||||
{
|
||||
gdb_assert (! b->shared);
|
||||
gdb_assert (b->size);
|
||||
/* Nothing to do. */
|
||||
return b->text;
|
||||
}
|
||||
|
||||
/* A cleanup function for macro buffers. */
|
||||
static void
|
||||
cleanup_macro_buffer (void *untyped_buf)
|
||||
{
|
||||
free_buffer ((struct macro_buffer *) untyped_buf);
|
||||
}
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
b->text = (char *) xrealloc (b->text, b->size);
|
||||
}
|
||||
|
||||
|
||||
/* Append the character C to the buffer B. */
|
||||
static void
|
||||
appendc (struct macro_buffer *b, int c)
|
||||
{
|
||||
int new_len = b->len + 1;
|
||||
|
||||
if (new_len > b->size)
|
||||
resize_buffer (b, new_len);
|
||||
|
||||
b->text[b->len] = c;
|
||||
b->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;
|
||||
|
||||
if (new_len > b->size)
|
||||
resize_buffer (b, new_len);
|
||||
|
||||
memcpy (b->text + b->len, addr, len);
|
||||
b->len = new_len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Recognizing preprocessor tokens. */
|
||||
|
||||
@ -216,7 +205,7 @@ macro_is_identifier_nondigit (int c)
|
||||
static void
|
||||
set_token (struct macro_buffer *tok, char *start, 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. */
|
||||
@ -596,7 +585,7 @@ append_tokens_without_splicing (struct macro_buffer *dest,
|
||||
|
||||
/* 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 +597,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
|
||||
@ -630,12 +618,11 @@ 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)
|
||||
@ -671,7 +658,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 +666,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,15 +675,15 @@ 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;
|
||||
}
|
||||
|
||||
@ -705,14 +692,13 @@ stringify (struct macro_buffer *dest, const char *arg, int len)
|
||||
char *
|
||||
macro_stringify (const char *str)
|
||||
{
|
||||
struct macro_buffer buffer;
|
||||
int len = strlen (str);
|
||||
struct 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 ();
|
||||
}
|
||||
|
||||
|
||||
@ -759,22 +745,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,53 +770,36 @@ 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, struct macro_buffer *src, int nargs,
|
||||
std::vector<struct 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);
|
||||
std::vector<struct 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);
|
||||
struct macro_buffer temp (src->text, src->len);
|
||||
|
||||
if (! get_token (&tok, &temp)
|
||||
|| tok.len != 1
|
||||
|| tok.text[0] != '(')
|
||||
{
|
||||
discard_cleanups (back_to);
|
||||
return 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;
|
||||
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. */
|
||||
@ -842,7 +808,7 @@ gather_arguments (const char *name, struct macro_buffer *src,
|
||||
{
|
||||
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++;
|
||||
@ -856,22 +822,15 @@ gather_arguments (const char *name, struct macro_buffer *src,
|
||||
{
|
||||
/* 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;
|
||||
*args_ptr = std::move (args);
|
||||
return true;
|
||||
}
|
||||
|
||||
depth--;
|
||||
@ -882,7 +841,7 @@ gather_arguments (const char *name, struct macro_buffer *src,
|
||||
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))
|
||||
&& (nargs == -1 || args.size () < nargs))
|
||||
break;
|
||||
|
||||
/* Extend the current argument to enclose this token. If
|
||||
@ -971,7 +930,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,16 +945,14 @@ get_next_token_for_substitution (struct macro_buffer *replacement_list,
|
||||
NO_LOOP. */
|
||||
|
||||
static void
|
||||
substitute_args (struct macro_buffer *dest,
|
||||
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,
|
||||
const std::vector<struct macro_buffer> &argv,
|
||||
struct macro_name_list *no_loop,
|
||||
macro_lookup_ftype *lookup_func,
|
||||
void *lookup_baton)
|
||||
{
|
||||
/* A macro buffer for the macro's replacement list. */
|
||||
struct macro_buffer replacement_list;
|
||||
/* The token we are currently considering. */
|
||||
struct macro_buffer tok;
|
||||
/* The replacement list's pointer from just before TOK was lexed. */
|
||||
@ -1008,8 +965,9 @@ substitute_args (struct macro_buffer *dest,
|
||||
lexed. */
|
||||
char *lookahead_rl_start;
|
||||
|
||||
init_shared_buffer (&replacement_list, def->replacement,
|
||||
strlen (def->replacement));
|
||||
/* A macro buffer for the macro's replacement list. */
|
||||
struct macro_buffer replacement_list (def->replacement,
|
||||
strlen (def->replacement));
|
||||
|
||||
gdb_assert (dest->len == 0);
|
||||
dest->last_token = 0;
|
||||
@ -1066,7 +1024,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)
|
||||
@ -1082,7 +1040,7 @@ substitute_args (struct macro_buffer *dest,
|
||||
that to DEST. */
|
||||
if (tok.text > original_rl_start)
|
||||
{
|
||||
appendmem (dest, original_rl_start, tok.text - original_rl_start);
|
||||
dest->appendmem (original_rl_start, tok.text - original_rl_start);
|
||||
dest->last_token = dest->len;
|
||||
}
|
||||
|
||||
@ -1135,9 +1093,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 +1118,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 +1133,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,7 +1156,7 @@ 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;
|
||||
@ -1221,14 +1179,12 @@ 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);
|
||||
struct macro_buffer arg_src (argv[arg].text, argv[arg].len);
|
||||
scan (dest, &arg_src, no_loop, lookup_func, lookup_baton);
|
||||
substituted = 1;
|
||||
}
|
||||
@ -1275,22 +1231,15 @@ expand (const char *id,
|
||||
/* What kind of macro are we expanding? */
|
||||
if (def->kind == macro_object_like)
|
||||
{
|
||||
struct macro_buffer replacement_list;
|
||||
|
||||
init_shared_buffer (&replacement_list, def->replacement,
|
||||
strlen (def->replacement));
|
||||
struct macro_buffer replacement_list (def->replacement,
|
||||
strlen (def->replacement));
|
||||
|
||||
scan (dest, &replacement_list, &new_no_loop, lookup_func, lookup_baton);
|
||||
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};
|
||||
struct macro_buffer va_arg_name;
|
||||
int is_varargs = 0;
|
||||
|
||||
if (def->argc >= 1)
|
||||
@ -1299,8 +1248,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,43 +1261,36 @@ 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<struct 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;
|
||||
}
|
||||
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 (argv.size () != def->argc)
|
||||
{
|
||||
if (is_varargs && argc >= def->argc - 1)
|
||||
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
|
||||
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);
|
||||
id, def->argc, int (argv.size ()));
|
||||
}
|
||||
|
||||
/* Note that we don't expand macro invocations in the arguments
|
||||
@ -1358,10 +1299,9 @@ expand (const char *id,
|
||||
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);
|
||||
struct macro_buffer substituted (0);
|
||||
substitute_args (&substituted, def, is_varargs, &va_arg_name,
|
||||
argc, argv, no_loop, lookup_func, lookup_baton);
|
||||
argv, no_loop, lookup_func, lookup_baton);
|
||||
|
||||
/* Now `substituted' is the macro's replacement list, with all
|
||||
argument values substituted into it properly. Re-scan it for
|
||||
@ -1373,11 +1313,9 @@ expand (const char *id,
|
||||
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);
|
||||
struct macro_buffer substituted_src (substituted.text, substituted.len);
|
||||
scan (dest, &substituted_src, &new_no_loop, lookup_func, lookup_baton);
|
||||
|
||||
do_cleanups (back_to);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@ -1465,7 +1403,7 @@ scan (struct macro_buffer *dest,
|
||||
that to DEST. */
|
||||
if (tok.text > original_src_start)
|
||||
{
|
||||
appendmem (dest, original_src_start, tok.text - original_src_start);
|
||||
dest->appendmem (original_src_start, tok.text - original_src_start);
|
||||
dest->last_token = dest->len;
|
||||
}
|
||||
|
||||
@ -1479,7 +1417,7 @@ scan (struct macro_buffer *dest,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1490,21 +1428,16 @@ macro_expand (const char *source,
|
||||
macro_lookup_ftype *lookup_func,
|
||||
void *lookup_func_baton)
|
||||
{
|
||||
struct macro_buffer src, dest;
|
||||
struct cleanup *back_to;
|
||||
struct macro_buffer src (source, strlen (source));
|
||||
|
||||
init_shared_buffer (&src, source, strlen (source));
|
||||
|
||||
init_buffer (&dest, 0);
|
||||
struct 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);
|
||||
|
||||
appendc (&dest, '\0');
|
||||
dest.appendc ('\0');
|
||||
|
||||
discard_cleanups (back_to);
|
||||
return gdb::unique_xmalloc_ptr<char> (dest.text);
|
||||
return gdb::unique_xmalloc_ptr<char> (dest.release ());
|
||||
}
|
||||
|
||||
|
||||
@ -1522,23 +1455,18 @@ macro_expand_next (const char **lexptr,
|
||||
macro_lookup_ftype *lookup_func,
|
||||
void *lookup_baton)
|
||||
{
|
||||
struct macro_buffer src, dest, tok;
|
||||
struct cleanup *back_to;
|
||||
struct macro_buffer tok;
|
||||
|
||||
/* Set up SRC to refer to the input text, pointed to by *lexptr. */
|
||||
init_shared_buffer (&src, *lexptr, strlen (*lexptr));
|
||||
struct macro_buffer src (*lexptr, strlen (*lexptr));
|
||||
|
||||
/* Set up DEST to receive the expansion, if there is one. */
|
||||
init_buffer (&dest, 0);
|
||||
struct 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 0;
|
||||
|
||||
/* If it's a macro invocation, expand it. */
|
||||
if (maybe_expand (&dest, &tok, &src, 0, lookup_func, lookup_baton))
|
||||
@ -1546,15 +1474,13 @@ macro_expand_next (const char **lexptr,
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user