]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Correctly handle L'\\'
authorTom Tromey <tromey@adacore.com>
Thu, 3 Jul 2025 18:35:11 +0000 (12:35 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 7 Jul 2025 14:52:09 +0000 (08:52 -0600)
Hannes filed a bug that pointed out that:

    print L'\\'

... did not work correctly.  The bug is in convert_escape, which
simply transcribes the backslash character, rather than convert it
between encodings.

This patch fixes the error.  I also turned a macro into a lambda to
clean up this code a little.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33124
Reviewed-By: Tom de Vries <tdevries@suse.de>
Tested-By: Hannes Domani <ssbssa@yahoo.de>
gdb/c-lang.c
gdb/testsuite/gdb.base/wchar.exp

index f052401b8fd3ab8c6ad3db0f81e621b14072ec04..9fccc1f761452cc6cb33644a28869a659ab26398 100644 (file)
@@ -484,13 +484,6 @@ convert_hex (struct type *type, const char *p,
   return p;
 }
 
-#define ADVANCE                                        \
-  do {                                         \
-    ++p;                                       \
-    if (p == limit)                            \
-      error (_("Malformed escape sequence"));  \
-  } while (0)
-
 /* Convert an escape sequence to a target format.  TYPE is the target
    character type to use, and DEST_CHARSET is the name of the target
    character set.  The backslash of the escape sequence is at *P, and
@@ -502,18 +495,29 @@ static const char *
 convert_escape (struct type *type, const char *dest_charset,
                const char *p, const char *limit, struct obstack *output)
 {
+  auto advance = [&] ()
+    {
+      ++p;
+      if (p == limit)
+       error (_("Malformed escape sequence"));
+    };
+
   /* Skip the backslash.  */
-  ADVANCE;
+  advance ();
 
   switch (*p)
     {
     case '\\':
-      obstack_1grow (output, '\\');
+      /* Convert the backslash itself.  This is probably overkill but
+        it doesn't hurt to do the full conversion.  */
+      convert_between_encodings (host_charset (), dest_charset,
+                                (const gdb_byte *) p, 1, 1,
+                                output, translit_none);
       ++p;
       break;
 
     case 'x':
-      ADVANCE;
+      advance ();
       if (!ISXDIGIT (*p))
        error (_("\\x used with no following hex digits."));
       p = convert_hex (type, p, limit, output);
@@ -535,7 +539,7 @@ convert_escape (struct type *type, const char *dest_charset,
       {
        int length = *p == 'u' ? 4 : 8;
 
-       ADVANCE;
+       advance ();
        if (!ISXDIGIT (*p))
          error (_("\\u used with no following hex digits"));
        p = convert_ucn (p, limit, dest_charset, output, length);
index 70f738cb7fc34e7fcf044419fd8e8b8e400da7f3..7f09e814b0f65edd784e4172c58924150c8234b6 100644 (file)
@@ -72,3 +72,7 @@ gdb_test "print repeat_p" "= $hex L\"A$cent$cent\"\.\.\." \
 
 # From PR cli/14977, but here because it requires wchar_t.
 gdb_test "printf \"%ls\\n\", 0" "\\(null\\)"
+
+# From PR exp/33124 - a bug when converting escapes.
+set result [string_to_regexp {L'\\'}]
+gdb_test "print L'\\\\'" " = $decimal $result"