This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: stringification in macros


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"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]