aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/c-lang.c4
-rw-r--r--gdb/language.h7
-rw-r--r--gdb/printcmd.c2
-rw-r--r--gdb/rust-lang.h5
-rw-r--r--gdb/testsuite/gdb.base/options.exp1
-rw-r--r--gdb/testsuite/gdb.base/printcmds.exp43
-rw-r--r--gdb/valprint.c48
-rw-r--r--gdb/valprint.h6
8 files changed, 113 insertions, 3 deletions
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 7689635..8737308 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -857,6 +857,10 @@ public:
const char *natural_name () const override
{ return "C++"; }
+ /* See language.h */
+ const char *get_digit_separator () const override
+ { return "\'"; }
+
/* See language.h. */
const std::vector<const char *> &filename_extensions () const override
diff --git a/gdb/language.h b/gdb/language.h
index f288500..c6812c5 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -282,6 +282,13 @@ struct language_defn
virtual const char *natural_name () const = 0;
+ /* Digit separator of the language. */
+
+ virtual const char *get_digit_separator () const
+ {
+ return " ";
+ }
+
/* Return a vector of file extensions for this language. The extension
must include the ".", like ".c". If this language doesn't need to
provide any filename extensions, this may be an empty vector (which is
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 806c5d1..ce3dd38 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -485,7 +485,7 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type,
break;
case 't':
- print_binary_chars (stream, valaddr, len, byte_order, size > 0);
+ print_binary_chars (stream, valaddr, len, byte_order, size > 0, options);
break;
case 'x':
print_hex_chars (stream, valaddr, len, byte_order, size > 0);
diff --git a/gdb/rust-lang.h b/gdb/rust-lang.h
index 514494a..6da57f8 100644
--- a/gdb/rust-lang.h
+++ b/gdb/rust-lang.h
@@ -71,6 +71,11 @@ public:
/* See language.h. */
+ const char *get_digit_separator () const override
+ { return "_"; }
+
+ /* See language.h. */
+
const std::vector<const char *> &filename_extensions () const override
{
static const std::vector<const char *> extensions = { ".rs" };
diff --git a/gdb/testsuite/gdb.base/options.exp b/gdb/testsuite/gdb.base/options.exp
index 4146661..d10e7f8 100644
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -168,6 +168,7 @@ proc_with_prefix test-print {{prefix ""}} {
"-elements"
"-max-depth"
"-memory-tag-violations"
+ "-nibbles"
"-null-stop"
"-object"
"-pretty"
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index 3260c8a..04d390d 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -709,6 +709,48 @@ proc test_print_char_arrays {} {
gdb_test_no_output "set print address off" "address off char arrays"
}
+proc test_print_nibbles {} {
+ gdb_test_no_output "set print nibbles on"
+ foreach lang_line {
+ {"ada" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"asm" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"c" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"c++" "0" "0" "0011'0000" "1111'1111" "1111" "0001" "1111'0000'1111"}
+ {"d" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"fortran" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"go" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"minimal" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"objective-c" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"opencl" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"pascal" "0" "0" "0011 0000" "1111 1111" "1111" "0001" "1111 0000 1111"}
+ {"rust" "0" "0" "0011_0000" "1111_1111" "1111" "0001" "1111_0000_1111"}
+ } {
+ set lang [lindex $lang_line 0]
+ set val1 [lindex $lang_line 1]
+ set val2 [lindex $lang_line 2]
+ set val3 [lindex $lang_line 3]
+ set val4 [lindex $lang_line 4]
+ set val5 [lindex $lang_line 5]
+ set val6 [lindex $lang_line 6]
+ set val7 [lindex $lang_line 7]
+ set val8 [lindex $lang_line 8]
+
+ with_test_prefix "$lang" {
+ gdb_test_no_output "set language $lang"
+ gdb_test "p/t 0" $val1
+ gdb_test "p/t 0x0" $val2
+ gdb_test "p/t 0x30" $val3
+ gdb_test "p/t 0xff" $val4
+ gdb_test "p/t 0x0f" $val5
+ gdb_test "p/t 0x01" $val6
+ gdb_test "p/t 0xf0f" $val7
+ gdb_test "p/t 0x70f" $val8
+ gdb_test_no_output "set language auto"
+ }
+ }
+ gdb_test_no_output "set print nibbles off"
+}
+
proc test_print_string_constants {} {
global gdb_prompt
@@ -1086,6 +1128,7 @@ test_print_int_arrays
test_print_typedef_arrays
test_artificial_arrays
test_print_char_arrays
+test_print_nibbles
# We used to do the runto main here.
test_print_string_constants
test_print_array_constants
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 4711467..e63ec30 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -105,6 +105,7 @@ struct value_print_options user_print_options =
0, /* vtblprint */
1, /* unionprint */
1, /* addressprint */
+ false, /* nibblesprint */
0, /* objectprint */
PRINT_MAX_DEFAULT, /* print_max */
10, /* repeat_count_threshold */
@@ -257,6 +258,17 @@ show_unionprint (struct ui_file *file, int from_tty,
value);
}
+/* Controls the format of printing binary values. */
+
+static void
+show_nibbles (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file,
+ _("Printing binary values in groups is %s.\n"),
+ value);
+}
+
/* If nonzero, causes machine addresses to be printed in certain contexts. */
static void
@@ -1357,18 +1369,23 @@ print_floating (const gdb_byte *valaddr, struct type *type,
void
print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
- unsigned len, enum bfd_endian byte_order, bool zero_pad)
+ unsigned len, enum bfd_endian byte_order, bool zero_pad,
+ const struct value_print_options *options)
{
const gdb_byte *p;
unsigned int i;
int b;
bool seen_a_one = false;
+ const char *digit_separator = nullptr;
/* Declared "int" so it will be signed.
This ensures that right shift will shift in zeros. */
const int mask = 0x080;
+ if (options->nibblesprint)
+ digit_separator = current_language->get_digit_separator();
+
if (byte_order == BFD_ENDIAN_BIG)
{
for (p = valaddr;
@@ -1380,6 +1397,9 @@ print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
for (i = 0; i < (HOST_CHAR_BIT * sizeof (*p)); i++)
{
+ if (options->nibblesprint && seen_a_one && i % 4 == 0)
+ gdb_putc (*digit_separator, stream);
+
if (*p & (mask >> i))
b = '1';
else
@@ -1387,6 +1407,13 @@ print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
if (zero_pad || seen_a_one || b == '1')
gdb_putc (b, stream);
+ else if (options->nibblesprint)
+ {
+ if ((0xf0 & (mask >> i) && (*p & 0xf0))
+ || (0x0f & (mask >> i) && (*p & 0x0f)))
+ gdb_putc (b, stream);
+ }
+
if (b == '1')
seen_a_one = true;
}
@@ -1400,6 +1427,9 @@ print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
{
for (i = 0; i < (HOST_CHAR_BIT * sizeof (*p)); i++)
{
+ if (options->nibblesprint && seen_a_one && i % 4 == 0)
+ gdb_putc (*digit_separator, stream);
+
if (*p & (mask >> i))
b = '1';
else
@@ -1407,6 +1437,13 @@ print_binary_chars (struct ui_file *stream, const gdb_byte *valaddr,
if (zero_pad || seen_a_one || b == '1')
gdb_putc (b, stream);
+ else if (options->nibblesprint)
+ {
+ if ((0xf0 & (mask >> i) && (*p & 0xf0))
+ || (0x0f & (mask >> i) && (*p & 0x0f)))
+ gdb_putc (b, stream);
+ }
+
if (b == '1')
seen_a_one = true;
}
@@ -2837,6 +2874,15 @@ static const gdb::option::option_def value_print_option_defs[] = {
NULL, /* help_doc */
},
+ boolean_option_def {
+ "nibbles",
+ [] (value_print_options *opt) { return &opt->nibblesprint; },
+ show_nibbles, /* show_cmd_cb */
+ N_("Set whether to print binary values in groups of four bits."),
+ N_("Show whether to print binary values in groups of four bits."),
+ NULL, /* help_doc */
+ },
+
uinteger_option_def {
"elements",
[] (value_print_options *opt) { return &opt->print_max; },
diff --git a/gdb/valprint.h b/gdb/valprint.h
index ff536fb..d6ad45d 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -44,6 +44,9 @@ struct value_print_options
/* Controls printing of addresses. */
bool addressprint;
+ /* Controls printing of nibbles. */
+ bool nibblesprint;
+
/* Controls looking up an object's derived type using what we find
in its vtables. */
bool objectprint;
@@ -149,7 +152,8 @@ extern void value_print_scalar_formatted
int size, struct ui_file *stream);
extern void print_binary_chars (struct ui_file *, const gdb_byte *,
- unsigned int, enum bfd_endian, bool);
+ unsigned int, enum bfd_endian, bool,
+ const struct value_print_options *options);
extern void print_octal_chars (struct ui_file *, const gdb_byte *,
unsigned int, enum bfd_endian);