This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
RFA: stringification in macros
- From: Tom Tromey <tromey at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Thu, 21 Aug 2008 18:08:46 -0600
- Subject: RFA: stringification in macros
- Reply-to: tromey at redhat dot com
This patch implements stringification in macro expansion.
Built and regtested on x86-64 (compile farm).
New test cases included.
Ok?
Tom
:ADDPATCH macros:
2008-08-21 Tom Tromey <tromey@redhat.com>
* macroexp.c (stringify): New function.
(find_parameter): Likewise.
(substitute_args): Implement stringification. Use
find_parameter.
2008-08-21 Tom Tromey <tromey@redhat.com>
* gdb.base/macscp.exp: Add stringification tests.
diff --git a/gdb/macroexp.c b/gdb/macroexp.c
index 8102bc0..946a4c7 100644
--- a/gdb/macroexp.c
+++ b/gdb/macroexp.c
@@ -625,6 +625,50 @@ append_tokens_without_splicing (struct macro_buffer *dest,
_("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, char *arg, int len)
+{
+ /* Trim initial whitespace from ARG. */
+ while (len > 0 && macro_is_whitespace (*arg))
+ {
+ ++arg;
+ --len;
+ }
+
+ /* Trim trailing whitespace from ARG. */
+ while (len > 0 && macro_is_whitespace (arg[len - 1]))
+ --len;
+
+ /* Insert the string. */
+ appendc (dest, '"');
+ while (len > 0)
+ {
+ /* We could try to handle strange cases here, like control
+ characters, but there doesn't seem to be much point. */
+ if (macro_is_whitespace (*arg))
+ {
+ /* Replace a sequence of whitespace with a single space. */
+ appendc (dest, ' ');
+ while (len > 1 && macro_is_whitespace (arg[1]))
+ {
+ ++arg;
+ --len;
+ }
+ }
+ else if (*arg == '\\' || *arg == '"')
+ {
+ appendc (dest, '\\');
+ appendc (dest, *arg);
+ }
+ else
+ appendc (dest, *arg);
+ ++arg;
+ --len;
+ }
+ appendc (dest, '"');
+}
/* Expanding macros! */
@@ -800,6 +844,20 @@ static void scan (struct macro_buffer *dest,
macro_lookup_ftype *lookup_func,
void *lookup_baton);
+/* A helper function for substitute_args. If the token TOK is the
+ name of a parameter, return the parameter's index. ARGV is a
+ vector of all the arguments; ARGC is the number of arguments. If
+ TOK is not an argument, return -1. */
+static int
+find_parameter (const struct macro_buffer *tok,
+ int argc, const char * const *argv)
+{
+ int i;
+ for (i = 0; i < argc; ++i)
+ if (tok->len == strlen (argv[i]) && ! memcmp (tok->text, argv[i], tok->len))
+ return i;
+ return -1;
+}
/* Given the macro definition DEF, being invoked with the actual
arguments given by ARGC and ARGV, substitute the arguments into the
@@ -847,7 +905,20 @@ substitute_args (struct macro_buffer *dest,
/* Is this token the stringification operator? */
if (tok.len == 1
&& tok.text[0] == '#')
- error (_("Stringification is not implemented yet."));
+ {
+ int arg;
+
+ if (! get_token (&tok, &replacement_list))
+ error (_("Stringification operator requires an argument."));
+
+ arg = find_parameter (&tok, def->argc, def->argv);
+ if (arg == -1)
+ error (_("Argument to stringification operator must name "
+ "a macro parameter."));
+
+ stringify (dest, argv[arg].text, argv[arg].len);
+ continue;
+ }
/* Is this token the splicing operator? */
if (tok.len == 2
@@ -858,7 +929,7 @@ substitute_args (struct macro_buffer *dest,
/* Is this token an identifier? */
if (tok.is_identifier)
{
- int i;
+ int arg;
/* Is it the magic varargs parameter? */
if (tok.len == 11
@@ -866,9 +937,8 @@ substitute_args (struct macro_buffer *dest,
error (_("Variable-arity macros not implemented yet."));
/* Is it one of the parameters? */
- for (i = 0; i < def->argc; i++)
- if (tok.len == strlen (def->argv[i])
- && ! memcmp (tok.text, def->argv[i], tok.len))
+ arg = find_parameter (&tok, def->argc, def->argv);
+ if (arg != -1)
{
struct macro_buffer arg_src;
@@ -877,10 +947,9 @@ substitute_args (struct macro_buffer *dest,
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[i].text, argv[i].len);
+ init_shared_buffer (&arg_src, argv[arg].text, argv[arg].len);
scan (dest, &arg_src, no_loop, lookup_func, lookup_baton);
substituted = 1;
- break;
}
}
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
index 3424714..9f79743 100644
--- a/gdb/testsuite/gdb.base/macscp.exp
+++ b/gdb/testsuite/gdb.base/macscp.exp
@@ -484,3 +484,46 @@ gdb_test "macro undef" \
gdb_test "macro expand SPLICE(x, y)" \
"Token splicing is not implemented yet." \
"macro splicing lexes correctly"
+
+
+# Stringification tests.
+
+gdb_test "macro define str(x) #x" \
+ "" \
+ "define stringification macro"
+
+gdb_test "macro define maude 5" \
+ "" \
+ "define first stringification helper"
+
+gdb_test "macro define xstr(x) str(x)" \
+ "" \
+ "define second stringification helper"
+
+gdb_test "print str(5)" \
+ " = \"5\"" \
+ "simple stringify"
+
+gdb_test "print str(hi bob)" \
+ " = \"hi bob\"" \
+ "stringify with one space"
+
+gdb_test "print str( hi bob )" \
+ " = \"hi bob\"" \
+ "stringify with many spaces"
+
+gdb_test "print str(hi \"bob\")" \
+ " = \"hi \\\\\"bob\\\\\"\"" \
+ "stringify with quotes"
+
+gdb_test "print str(hi \\bob\\)" \
+ " = \"hi \\\\\\\\bob\\\\\\\\\"" \
+ "stringify with backslashes"
+
+gdb_test "print str(maude)" \
+ " = \"maude\"" \
+ "stringify without substitution"
+
+gdb_test "print xstr(maude)" \
+ " = \"5\"" \
+ "stringify with substitution"