diff options
author | Tom Tromey <tromey@redhat.com> | 2008-07-18 20:55:33 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2008-07-18 20:55:33 +0000 |
commit | d7d9f01ea18f14a9a1574042bd65dd73f9b6b2b8 (patch) | |
tree | 350b57eb105730c6e52b961f7c55b0821f6b222e /gdb/macrocmd.c | |
parent | a9dc948127c2cb5127cec5ca87dbc19f17dd16cf (diff) | |
download | gdb-d7d9f01ea18f14a9a1574042bd65dd73f9b6b2b8.zip gdb-d7d9f01ea18f14a9a1574042bd65dd73f9b6b2b8.tar.gz gdb-d7d9f01ea18f14a9a1574042bd65dd73f9b6b2b8.tar.bz2 |
gdb
PR gdb/855:
* NEWS: Add entry for macro commands.
* Makefile.in (macrocmd.o): Add gdb_string.h.
* macroscope.h (user_macro_scope): Declare.
(default_macro_scope): Update documentation.
(macro_user_macros): Declare.
* c-lang.c (c_preprocess_and_parse): Always attempt macro lookup.
Use user_macro_scope.
(null_macro_lookup): Remove.
* macrotab.h (macro_callback_fn): Declare.
(macro_for_each): Likewise.
(macro_allow_redefinitions): Likewise.
* macrotab.c (foreach_macro): New function
(macro_for_each): Likewise.
(struct macro_table) <redef_ok>: New field.
(macro_allow_redefinitions): New function.
(new_macro_table): Update.
(macro_define_function): Likewise.
(macro_define_object): Likewise.
* macroscope.c (user_macro_scope): New function.
(default_macro_scope): Use it.
(macro_user_macros): New global.
(standard_macro_lookup): Look in macro_user_macros.
(_initialize_macroscope): New function.
* macroexp.h (macro_is_whitespace, macro_is_digit,
macro_is_identifier_nondigit): Declare.
* macroexp.c (macro_is_whitespace): Rename. No longer static.
(macro_is_digit): Likewise.
(macro_is_identifier_nondigit): Likewise.
(get_identifier): Update.
(get_pp_number): Likewise.
(get_token): Likewise.
* macrocmd.c (skip_ws): New function.
(extract_identifier): Likewise.
(free_macro_definition_ptr): Likewise.
(user_macros): Remove.
(macro_define_command): Implement.
(_initialize_macrocmd): Update.
(macro_undef_command): Implement.
(print_one_macro): New function.
(macro_list_command): Implement.
gdb/doc
* gdb.texinfo (Macros): Update. Use @code rather than @command.
gdb/testsuite
* gdb.base/macscp.exp: Add macro tests.
Diffstat (limited to 'gdb/macrocmd.c')
-rw-r--r-- | gdb/macrocmd.c | 146 |
1 files changed, 135 insertions, 11 deletions
diff --git a/gdb/macrocmd.c b/gdb/macrocmd.c index c5d3a8f..4a70d4f 100644 --- a/gdb/macrocmd.c +++ b/gdb/macrocmd.c @@ -24,6 +24,7 @@ #include "macroscope.h" #include "command.h" #include "gdbcmd.h" +#include "gdb_string.h" /* The `macro' prefix command. */ @@ -189,31 +190,156 @@ info_macro_command (char *name, int from_tty) /* User-defined macros. */ -/* A table of user-defined macros. Unlike the macro tables used for - symtabs, this one uses xmalloc for all its allocation, not an - obstack, and it doesn't bcache anything; it just xmallocs things. So - it's perfectly possible to remove things from this, or redefine - things. */ -static struct macro_table *user_macros; +static void +skip_ws (char **expp) +{ + while (macro_is_whitespace (**expp)) + ++*expp; +} + +static char * +extract_identifier (char **expp) +{ + char *result; + char *p = *expp; + unsigned int len; + if (! *p || ! macro_is_identifier_nondigit (*p)) + return NULL; + for (++p; + *p && (macro_is_identifier_nondigit (*p) || macro_is_digit (*p)); + ++p) + ; + len = p - *expp; + result = (char *) xmalloc (len + 1); + memcpy (result, *expp, len); + result[len] = '\0'; + *expp += len; + return result; +} + +/* Helper function to clean up a temporarily-constructed macro object. + This assumes that the contents were all allocated with xmalloc. */ +static void +free_macro_definition_ptr (void *ptr) +{ + int i; + struct macro_definition *loc = (struct macro_definition *) ptr; + for (i = 0; i < loc->argc; ++i) + xfree ((char *) loc->argv[i]); + xfree ((char *) loc->argv); + /* Note that the 'replacement' field is not allocated. */ +} static void macro_define_command (char *exp, int from_tty) { - error (_("Command not implemented yet.")); + struct macro_definition new_macro; + char *name = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_macro_definition_ptr, + &new_macro); + make_cleanup (free_current_contents, &name); + + memset (&new_macro, 0, sizeof (struct macro_definition)); + + skip_ws (&exp); + name = extract_identifier (&exp); + if (! name) + error (_("Invalid macro name.")); + if (*exp == '(') + { + /* Function-like macro. */ + int alloced = 5; + char **argv = (char **) xmalloc (alloced * sizeof (char *)); + + new_macro.kind = macro_function_like; + new_macro.argc = 0; + new_macro.argv = (const char * const *) argv; + + /* Skip the '(' and whitespace. */ + ++exp; + skip_ws (&exp); + + 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); + if (! argv[new_macro.argc]) + error (_("Macro is missing an argument.")); + ++new_macro.argc; + + for (i = new_macro.argc - 2; i >= 0; --i) + { + if (! strcmp (argv[i], argv[new_macro.argc - 1])) + error (_("Two macro arguments with identical names.")); + } + + skip_ws (&exp); + if (*exp == ',') + { + ++exp; + skip_ws (&exp); + } + else if (*exp != ')') + error (_("',' or ')' expected at end of macro arguments.")); + } + /* Skip the closing paren. */ + ++exp; + + macro_define_function (macro_main (macro_user_macros), -1, name, + new_macro.argc, (const char **) new_macro.argv, + exp); + } + else + macro_define_object (macro_main (macro_user_macros), -1, name, exp); + + do_cleanups (cleanup_chain); } static void macro_undef_command (char *exp, int from_tty) { - error (_("Command not implemented yet.")); + char *name; + skip_ws (&exp); + name = extract_identifier (&exp); + if (! name) + error (_("Invalid macro name.")); + macro_undef (macro_main (macro_user_macros), -1, name); + xfree (name); +} + + +static void +print_one_macro (const char *name, const struct macro_definition *macro) +{ + fprintf_filtered (gdb_stdout, "macro define %s", name); + if (macro->kind == macro_function_like) + { + int i; + fprintf_filtered (gdb_stdout, "("); + for (i = 0; i < macro->argc; ++i) + fprintf_filtered (gdb_stdout, "%s%s", (i > 0) ? ", " : "", + macro->argv[i]); + fprintf_filtered (gdb_stdout, ")"); + } + /* Note that we don't need a leading space here -- "macro define" + provided it. */ + fprintf_filtered (gdb_stdout, "%s\n", macro->replacement); } static void macro_list_command (char *exp, int from_tty) { - error (_("Command not implemented yet.")); + macro_for_each (macro_user_macros, print_one_macro); } @@ -273,6 +399,4 @@ Remove the definition of the C/C++ preprocessor macro with the given name."), add_cmd ("list", no_class, macro_list_command, _("List all the macros defined using the `macro define' command."), ¯olist); - - user_macros = new_macro_table (0, 0); } |