diff options
author | Tom Tromey <tromey@adacore.com> | 2025-07-03 12:35:11 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2025-07-07 08:52:09 -0600 |
commit | 0a082f5cf8a5e42b7c947b377c117ec3451dcce8 (patch) | |
tree | 786ddbde32807985d456c3e6473266962d0438db | |
parent | 392f8c40f0d3d9cbd4ee38d94bde06cf1b845e9f (diff) | |
download | binutils-0a082f5cf8a5e42b7c947b377c117ec3451dcce8.zip binutils-0a082f5cf8a5e42b7c947b377c117ec3451dcce8.tar.gz binutils-0a082f5cf8a5e42b7c947b377c117ec3451dcce8.tar.bz2 |
Correctly handle L'\\'
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>
-rw-r--r-- | gdb/c-lang.c | 26 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/wchar.exp | 4 |
2 files changed, 19 insertions, 11 deletions
diff --git a/gdb/c-lang.c b/gdb/c-lang.c index f052401..9fccc1f 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -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); diff --git a/gdb/testsuite/gdb.base/wchar.exp b/gdb/testsuite/gdb.base/wchar.exp index 70f738c..7f09e81 100644 --- a/gdb/testsuite/gdb.base/wchar.exp +++ b/gdb/testsuite/gdb.base/wchar.exp @@ -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" |