mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
gdb: use std::string vector for macro definition
Use std::vector<std::string> when defining macros, to avoid the manual memory management. With the use of std::vector, the separate `int argc` parameter is no longer needed, we can use the size of the vector instead. However, for some functions, this parameter had a dual function. For object-like macros, it was interpreted as a `macro_special_kind` enum. For these functions, remove `argc`, but add a new `special_kind` parameter. Change-Id: Ice76a6863dfe598335e3b8d5d077513e50975cc5 Approved-By: Tom de Vries <tdevries@suse.de>
This commit is contained in:
parent
a7763df8fb
commit
1cb8a69ec2
@ -160,9 +160,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
|
||||
/* It's a function-like macro. */
|
||||
gdb_assert (*p == '(');
|
||||
std::string name (body, p - body);
|
||||
int argc = 0;
|
||||
int argv_size = 1;
|
||||
char **argv = XNEWVEC (char *, argv_size);
|
||||
std::vector<std::string> argv;
|
||||
|
||||
p++;
|
||||
|
||||
@ -180,16 +178,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
|
||||
if (! *p || p == arg_start)
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
else
|
||||
{
|
||||
/* Make sure argv has room for the new argument. */
|
||||
if (argc >= argv_size)
|
||||
{
|
||||
argv_size *= 2;
|
||||
argv = XRESIZEVEC (char *, argv, argv_size);
|
||||
}
|
||||
|
||||
argv[argc++] = savestring (arg_start, p - arg_start);
|
||||
}
|
||||
argv.emplace_back (arg_start, p);
|
||||
|
||||
p = consume_improper_spaces (p, body);
|
||||
|
||||
@ -208,16 +197,12 @@ parse_macro_definition (struct macro_source_file *file, int line,
|
||||
|
||||
if (*p == ' ')
|
||||
/* Perfectly formed definition, no complaints. */
|
||||
macro_define_function (file, line, name.c_str (),
|
||||
argc, (const char **) argv,
|
||||
p + 1);
|
||||
macro_define_function (file, line, name.c_str (), argv, p + 1);
|
||||
else if (*p == '\0')
|
||||
{
|
||||
/* Complain, but do define it. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
macro_define_function (file, line, name.c_str (),
|
||||
argc, (const char **) argv,
|
||||
p);
|
||||
macro_define_function (file, line, name.c_str (), argv, p);
|
||||
}
|
||||
else
|
||||
/* Just complain. */
|
||||
@ -226,11 +211,6 @@ parse_macro_definition (struct macro_source_file *file, int line,
|
||||
else
|
||||
/* Just complain. */
|
||||
dwarf2_macro_malformed_definition_complaint (body);
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
xfree (argv[i]);
|
||||
|
||||
xfree (argv);
|
||||
}
|
||||
|
||||
/* Skip some bytes from BYTES according to the form given in FORM.
|
||||
|
@ -271,18 +271,17 @@ skip_ws (const char **expp)
|
||||
}
|
||||
|
||||
/* Try to find the bounds of an identifier. If an identifier is
|
||||
found, returns a newly allocated string; otherwise returns NULL.
|
||||
found, return it; otherwise return an empty string.
|
||||
|
||||
EXPP is a pointer to an input string; it is updated to point to the
|
||||
text following the identifier. If IS_PARAMETER is true, this
|
||||
function will also allow "..." forms as used in varargs macro
|
||||
parameters. */
|
||||
|
||||
static gdb::unique_xmalloc_ptr<char>
|
||||
static std::string
|
||||
extract_identifier (const char **expp, int is_parameter)
|
||||
{
|
||||
char *result;
|
||||
const char *p = *expp;
|
||||
unsigned int len;
|
||||
|
||||
if (is_parameter && startswith (p, "..."))
|
||||
{
|
||||
@ -291,67 +290,39 @@ extract_identifier (const char **expp, int is_parameter)
|
||||
else
|
||||
{
|
||||
if (! *p || ! macro_is_identifier_nondigit (*p))
|
||||
return NULL;
|
||||
return {};
|
||||
|
||||
for (++p;
|
||||
*p && (macro_is_identifier_nondigit (*p) || macro_is_digit (*p));
|
||||
++p)
|
||||
;
|
||||
}
|
||||
|
||||
if (is_parameter && startswith (p, "..."))
|
||||
if (is_parameter && startswith (p, "..."))
|
||||
p += 3;
|
||||
|
||||
len = p - *expp;
|
||||
result = (char *) xmalloc (len + 1);
|
||||
memcpy (result, *expp, len);
|
||||
result[len] = '\0';
|
||||
*expp += len;
|
||||
return gdb::unique_xmalloc_ptr<char> (result);
|
||||
std::string result (*expp, p);
|
||||
*expp = p;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct temporary_macro_definition : public macro_definition
|
||||
{
|
||||
temporary_macro_definition ()
|
||||
{
|
||||
table = nullptr;
|
||||
kind = macro_object_like;
|
||||
argc = 0;
|
||||
argv = nullptr;
|
||||
replacement = nullptr;
|
||||
}
|
||||
|
||||
~temporary_macro_definition ()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; ++i)
|
||||
xfree ((char *) argv[i]);
|
||||
xfree ((char *) argv);
|
||||
/* Note that the 'replacement' field is not allocated. */
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
macro_define_command (const char *exp, int from_tty)
|
||||
{
|
||||
temporary_macro_definition new_macro;
|
||||
|
||||
if (!exp)
|
||||
error (_("usage: macro define NAME[(ARGUMENT-LIST)] [REPLACEMENT-LIST]"));
|
||||
|
||||
skip_ws (&exp);
|
||||
gdb::unique_xmalloc_ptr<char> name = extract_identifier (&exp, 0);
|
||||
if (name == NULL)
|
||||
|
||||
std::string name = extract_identifier (&exp, 0);
|
||||
if (name.empty ())
|
||||
error (_("Invalid macro name."));
|
||||
|
||||
if (*exp == '(')
|
||||
{
|
||||
/* Function-like macro. */
|
||||
int alloced = 5;
|
||||
char **argv = XNEWVEC (char *, alloced);
|
||||
|
||||
new_macro.kind = macro_function_like;
|
||||
new_macro.argc = 0;
|
||||
new_macro.argv = (const char * const *) argv;
|
||||
std::vector<std::string> argv;
|
||||
|
||||
/* Skip the '(' and whitespace. */
|
||||
++exp;
|
||||
@ -359,23 +330,13 @@ macro_define_command (const char *exp, int from_tty)
|
||||
|
||||
while (*exp != ')')
|
||||
{
|
||||
int i;
|
||||
|
||||
if (new_macro.argc == alloced)
|
||||
{
|
||||
alloced *= 2;
|
||||
argv = (char **) xrealloc (argv, alloced * sizeof (char *));
|
||||
/* Must update new_macro as well... */
|
||||
new_macro.argv = (const char * const *) argv;
|
||||
}
|
||||
argv[new_macro.argc] = extract_identifier (&exp, 1).release ();
|
||||
if (! argv[new_macro.argc])
|
||||
argv.emplace_back (extract_identifier (&exp, 1));
|
||||
if (argv.back ().empty ())
|
||||
error (_("Macro is missing an argument."));
|
||||
++new_macro.argc;
|
||||
|
||||
for (i = new_macro.argc - 2; i >= 0; --i)
|
||||
for (const auto &other_arg : argv)
|
||||
{
|
||||
if (! strcmp (argv[i], argv[new_macro.argc - 1]))
|
||||
if (&other_arg != &argv.back () && other_arg == argv.back ())
|
||||
error (_("Two macro arguments with identical names."));
|
||||
}
|
||||
|
||||
@ -388,18 +349,18 @@ macro_define_command (const char *exp, int from_tty)
|
||||
else if (*exp != ')')
|
||||
error (_("',' or ')' expected at end of macro arguments."));
|
||||
}
|
||||
|
||||
/* Skip the closing paren. */
|
||||
++exp;
|
||||
skip_ws (&exp);
|
||||
|
||||
macro_define_function (macro_main (macro_user_macros), -1, name.get (),
|
||||
new_macro.argc, (const char **) new_macro.argv,
|
||||
exp);
|
||||
macro_define_function (macro_main (macro_user_macros), -1, name.c_str (),
|
||||
argv, exp);
|
||||
}
|
||||
else
|
||||
{
|
||||
skip_ws (&exp);
|
||||
macro_define_object (macro_main (macro_user_macros), -1, name.get (),
|
||||
macro_define_object (macro_main (macro_user_macros), -1, name.c_str (),
|
||||
exp);
|
||||
}
|
||||
}
|
||||
@ -412,10 +373,12 @@ macro_undef_command (const char *exp, int from_tty)
|
||||
error (_("usage: macro undef NAME"));
|
||||
|
||||
skip_ws (&exp);
|
||||
gdb::unique_xmalloc_ptr<char> name = extract_identifier (&exp, 0);
|
||||
if (name == nullptr)
|
||||
|
||||
std::string name = extract_identifier (&exp, 0);
|
||||
if (name.empty ())
|
||||
error (_("Invalid macro name."));
|
||||
macro_undef (macro_main (macro_user_macros), -1, name.get ());
|
||||
|
||||
macro_undef (macro_main (macro_user_macros), -1, name.c_str ());
|
||||
}
|
||||
|
||||
|
||||
|
@ -545,10 +545,10 @@ macro_lookup_inclusion (struct macro_source_file *source, const char *name)
|
||||
|
||||
/* Construct a definition for a macro in table T. Cache all strings,
|
||||
and the macro_definition structure itself, in T's bcache. */
|
||||
static struct macro_definition *
|
||||
new_macro_definition (struct macro_table *t,
|
||||
enum macro_kind kind,
|
||||
int argc, const char **argv,
|
||||
static macro_definition *
|
||||
new_macro_definition (macro_table *t, macro_kind kind,
|
||||
macro_special_kind special_kind,
|
||||
const std::vector<std::string> &argv,
|
||||
const char *replacement)
|
||||
{
|
||||
struct macro_definition *d
|
||||
@ -558,22 +558,24 @@ new_macro_definition (struct macro_table *t,
|
||||
d->table = t;
|
||||
d->kind = kind;
|
||||
d->replacement = macro_bcache_str (t, replacement);
|
||||
d->argc = argc;
|
||||
|
||||
if (kind == macro_function_like)
|
||||
{
|
||||
int i;
|
||||
const char **cached_argv;
|
||||
int cached_argv_size = argc * sizeof (*cached_argv);
|
||||
d->argc = argv.size ();
|
||||
|
||||
/* Bcache all the arguments. */
|
||||
cached_argv = (const char **) alloca (cached_argv_size);
|
||||
for (i = 0; i < argc; i++)
|
||||
cached_argv[i] = macro_bcache_str (t, argv[i]);
|
||||
int i = 0;
|
||||
int cached_argv_size = argv.size () * sizeof (const char *);
|
||||
const char **cached_argv = (const char **) alloca (cached_argv_size);
|
||||
|
||||
for (const auto &arg : argv)
|
||||
cached_argv[i++] = macro_bcache_str (t, arg.c_str ());
|
||||
|
||||
/* Now bcache the array of argument pointers itself. */
|
||||
d->argv = macro_bcache (t, cached_argv, cached_argv_size);
|
||||
}
|
||||
else
|
||||
d->argc = special_kind;
|
||||
|
||||
/* We don't bcache the entire definition structure because it's got
|
||||
a pointer to the macro table in it; since each compilation unit
|
||||
@ -677,13 +679,12 @@ find_definition (const char *name,
|
||||
|
||||
/* If NAME already has a definition in scope at LINE in SOURCE, return
|
||||
the key. If the old definition is different from the definition
|
||||
given by KIND, ARGC, ARGV, and REPLACEMENT, complain, too.
|
||||
Otherwise, return zero. (ARGC and ARGV are meaningless unless KIND
|
||||
given by KIND, ARGV, and REPLACEMENT, complain, too.
|
||||
Otherwise, return nullptr. (ARGV is meaningless unless KIND
|
||||
is `macro_function_like'.) */
|
||||
static struct macro_key *
|
||||
check_for_redefinition (struct macro_source_file *source, int line,
|
||||
const char *name, enum macro_kind kind,
|
||||
int argc, const char **argv,
|
||||
static macro_key *
|
||||
check_for_redefinition (macro_source_file *source, int line, const char *name,
|
||||
macro_kind kind, const std::vector<std::string> &argv,
|
||||
const char *replacement)
|
||||
{
|
||||
splay_tree_node n = find_definition (name, source, line);
|
||||
@ -708,14 +709,14 @@ check_for_redefinition (struct macro_source_file *source, int line,
|
||||
same = 0;
|
||||
else if (kind == macro_function_like)
|
||||
{
|
||||
if (argc != found_def->argc)
|
||||
if (argv.size () != found_def->argc)
|
||||
same = 0;
|
||||
else
|
||||
{
|
||||
int i;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
if (strcmp (argv[i], found_def->argv[i]))
|
||||
for (const auto &arg : argv)
|
||||
if (arg != found_def->argv[i++])
|
||||
same = 0;
|
||||
}
|
||||
}
|
||||
@ -739,15 +740,18 @@ check_for_redefinition (struct macro_source_file *source, int line,
|
||||
}
|
||||
|
||||
/* A helper function to define a new object-like or function-like macro
|
||||
according to KIND. When KIND is macro_object_like,
|
||||
the macro_special_kind must be provided as ARGC, and ARGV must be NULL.
|
||||
When KIND is macro_function_like, ARGC and ARGV are giving the function
|
||||
arguments. */
|
||||
according to KIND.
|
||||
|
||||
When KIND is macro_object_like, the possible special kind is given by
|
||||
SPECIAL_KIND, and ARGV is meaningless.
|
||||
|
||||
When KIND is macro_function_like, ARGV gives the macro argument names, and
|
||||
SPECIAL_KIND is meaningless. */
|
||||
|
||||
static void
|
||||
macro_define_internal (struct macro_source_file *source, int line,
|
||||
const char *name, enum macro_kind kind,
|
||||
int argc, const char **argv,
|
||||
macro_define_internal (macro_source_file *source, int line, const char *name,
|
||||
macro_kind kind, macro_special_kind special_kind,
|
||||
const std::vector<std::string> &argv,
|
||||
const char *replacement)
|
||||
{
|
||||
struct macro_table *t = source->table;
|
||||
@ -755,10 +759,7 @@ macro_define_internal (struct macro_source_file *source, int line,
|
||||
struct macro_definition *d;
|
||||
|
||||
if (! t->redef_ok)
|
||||
k = check_for_redefinition (source, line,
|
||||
name, kind,
|
||||
argc, argv,
|
||||
replacement);
|
||||
k = check_for_redefinition (source, line, name, kind, argv, replacement);
|
||||
|
||||
/* If we're redefining a symbol, and the existing key would be
|
||||
identical to our new key, then the splay_tree_insert function
|
||||
@ -774,7 +775,7 @@ macro_define_internal (struct macro_source_file *source, int line,
|
||||
return;
|
||||
|
||||
k = new_macro_key (t, name, source, line);
|
||||
d = new_macro_definition (t, kind, argc, argv, replacement);
|
||||
d = new_macro_definition (t, kind, special_kind, argv, replacement);
|
||||
splay_tree_insert (t->definitions, (splay_tree_key) k, (splay_tree_value) d);
|
||||
}
|
||||
|
||||
@ -785,10 +786,8 @@ macro_define_object_internal (struct macro_source_file *source, int line,
|
||||
const char *name, const char *replacement,
|
||||
enum macro_special_kind special_kind)
|
||||
{
|
||||
macro_define_internal (source, line,
|
||||
name, macro_object_like,
|
||||
special_kind, NULL,
|
||||
replacement);
|
||||
macro_define_internal (source, line, name, macro_object_like, special_kind,
|
||||
{}, replacement);
|
||||
}
|
||||
|
||||
void
|
||||
@ -811,14 +810,12 @@ macro_define_special (struct macro_table *table)
|
||||
}
|
||||
|
||||
void
|
||||
macro_define_function (struct macro_source_file *source, int line,
|
||||
const char *name, int argc, const char **argv,
|
||||
macro_define_function (macro_source_file *source, int line, const char *name,
|
||||
const std::vector<std::string> &argv,
|
||||
const char *replacement)
|
||||
{
|
||||
macro_define_internal (source, line,
|
||||
name, macro_function_like,
|
||||
argc, argv,
|
||||
replacement);
|
||||
macro_define_internal (source, line, name, macro_function_like,
|
||||
macro_ordinary, argv, replacement);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -242,26 +242,23 @@ struct macro_source_file *macro_lookup_inclusion
|
||||
Record in SOURCE's macro table that, at line number LINE in SOURCE,
|
||||
we #defined a preprocessor symbol named NAME, whose replacement
|
||||
string is REPLACEMENT. This function makes copies of NAME and
|
||||
REPLACEMENT; the caller is responsible for freeing them. */
|
||||
REPLACEMENT. */
|
||||
void macro_define_object (struct macro_source_file *source, int line,
|
||||
const char *name, const char *replacement);
|
||||
|
||||
|
||||
/* Record an function-like #definition (i.e., one with a parameter list).
|
||||
/* Record a function-like #definition (i.e., one with a parameter list).
|
||||
|
||||
Record in SOURCE's macro table that, at line number LINE in SOURCE,
|
||||
we #defined a preprocessor symbol named NAME, with ARGC arguments
|
||||
whose names are given in ARGV, whose replacement string is REPLACEMENT. If
|
||||
the macro takes a variable number of arguments, then ARGC should be
|
||||
one greater than the number of named arguments, and ARGV[ARGC-1]
|
||||
should be the string "...". This function makes its own copies of
|
||||
NAME, ARGV, and REPLACEMENT; the caller is responsible for freeing
|
||||
them. */
|
||||
void macro_define_function (struct macro_source_file *source, int line,
|
||||
const char *name, int argc, const char **argv,
|
||||
we #defined a preprocessor symbol named NAME, with argument names given by
|
||||
ARGV, whose replacement string is REPLACEMENT. If the macro takes a variable
|
||||
number of arguments, then the last element of ARGV should be the string
|
||||
"...". This function makes copies of NAME, ARGV, and REPLACEMENT. */
|
||||
void macro_define_function (macro_source_file *source, int line,
|
||||
const char *name,
|
||||
const std::vector<std::string> &argv,
|
||||
const char *replacement);
|
||||
|
||||
|
||||
/* Record an #undefinition.
|
||||
Record in SOURCE's macro table that, at line number LINE in SOURCE,
|
||||
we removed the definition for the preprocessor symbol named NAME. */
|
||||
|
Loading…
Reference in New Issue
Block a user