PR gdb/14288
* c-valprint.c (c_val_print): For character arrays with "print null" option on, print ellipses if the output is truncated and the next character is not \000. * valprint.c (MAX_WCHARS): Define. (WCHAR_BUFLEN): Likewise. (WCHAR_BUFLEN_MAX): Likewise. (struct converted_character): New structure. (count_next_character): New function. (print_converted_chars_to_obstack): New function. (generic_printstr): Rewrite using count_next_character and print_converted_chars_to_obstack. * gdb.base/printcmds.c: Add invalid_XXX globals for repeated byte tests. * gdb.base/printcmds.exp (test_repeat_bytes): New procedure. * gdb.base/wchar.c (main): Add and construct a wchar_t array with repeated characters. * gdb.base/wchar.exp: Add repeated character tests.
This commit is contained in:
parent
9b8d682720
commit
0d63ecdad0
8 changed files with 554 additions and 160 deletions
|
@ -1,3 +1,18 @@
|
|||
2012-11-10 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
PR gdb/14288
|
||||
* c-valprint.c (c_val_print): For character arrays
|
||||
with "print null" option on, print ellipses if
|
||||
the output is truncated and the next character is not \000.
|
||||
* valprint.c (MAX_WCHARS): Define.
|
||||
(WCHAR_BUFLEN): Likewise.
|
||||
(WCHAR_BUFLEN_MAX): Likewise.
|
||||
(struct converted_character): New structure.
|
||||
(count_next_character): New function.
|
||||
(print_converted_chars_to_obstack): New function.
|
||||
(generic_printstr): Rewrite using count_next_character
|
||||
and print_converted_chars_to_obstack.
|
||||
|
||||
2012-11-10 Stephane Carrez <Stephane.Carrez@gmail.com>
|
||||
|
||||
* tui/tui.c (tui_rl_command_key): Switch to TUI_ONE_COMMAND_MODE
|
||||
|
|
|
@ -177,6 +177,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
|
|||
TARGET_CHAR_BIT * embedded_offset,
|
||||
TARGET_CHAR_BIT * TYPE_LENGTH (type)))
|
||||
{
|
||||
int force_ellipses = 0;
|
||||
|
||||
/* If requested, look for the first null char and only
|
||||
print elements up to it. */
|
||||
if (options->stop_print_at_null)
|
||||
|
@ -191,12 +193,26 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
|
|||
eltlen, byte_order) != 0);
|
||||
++temp_len)
|
||||
;
|
||||
|
||||
/* Force LA_PRINT_STRING to print ellipses if
|
||||
we've printed the maximum characters and
|
||||
the next character is not \000. */
|
||||
if (temp_len == options->print_max && temp_len < len)
|
||||
{
|
||||
ULONGEST val
|
||||
= extract_unsigned_integer (valaddr + embedded_offset
|
||||
+ temp_len * eltlen,
|
||||
eltlen, byte_order);
|
||||
if (val != 0)
|
||||
force_ellipses = 1;
|
||||
}
|
||||
|
||||
len = temp_len;
|
||||
}
|
||||
|
||||
LA_PRINT_STRING (stream, unresolved_elttype,
|
||||
valaddr + embedded_offset, len,
|
||||
NULL, 0, options);
|
||||
NULL, force_ellipses, options);
|
||||
i = len;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
2012-11-10 Keith Seitz <keiths@redhat.com>
|
||||
|
||||
PR gdb/14288
|
||||
* gdb.base/printcmds.c: Add invalid_XXX globals
|
||||
for repeated byte tests.
|
||||
* gdb.base/printcmds.exp (test_repeat_bytes): New procedure.
|
||||
* gdb.base/wchar.c (main): Add and construct a wchar_t
|
||||
array with repeated characters.
|
||||
* gdb.base/wchar.exp: Add repeated character tests.
|
||||
|
||||
2012-11-09 Andrew Burgess <aburgess@broadcom.com>
|
||||
|
||||
* gdb.mi/mi-disassemble.exp: Expect fullname field in mi
|
||||
|
|
|
@ -122,6 +122,98 @@ struct some_struct
|
|||
}
|
||||
};
|
||||
|
||||
/* The following variables are used for testing byte repeat sequences.
|
||||
The variable names are encoded: invalid_XYZ where:
|
||||
X = start
|
||||
Y = invalid
|
||||
Z = end
|
||||
|
||||
Each of X and Z can be "E" (empty), "S" (single), "L" (long single),
|
||||
or "R" (repeat).
|
||||
|
||||
Y can be either any of the above except "E" (otherwise there is nothing
|
||||
to test). */
|
||||
char invalid_ESE[] = "\240";
|
||||
char invalid_SSE[] = "a\240";
|
||||
char invalid_LSE[] = "abaabbaaabbb\240";
|
||||
char invalid_RSE[] = "aaaaaaaaaaaaaaaaaaaa\240";
|
||||
char invalid_ESS[] = "\240c";
|
||||
char invalid_SSS[] = "a\240c";
|
||||
char invalid_LSS[] = "abaabbaaabbb\240c";
|
||||
char invalid_RSS[] = "aaaaaaaaaaaaaaaaaaaa\240c";
|
||||
char invalid_ESL[] = "\240cdccddcccddd";
|
||||
char invalid_SSL[] = "a\240cdccddcccddd";
|
||||
char invalid_LSL[] = "abaabbaaabbb\240cdccddcccddd";
|
||||
char invalid_RSL[] = "aaaaaaaaaaaaaaaaaaaa\240cdccddcccddd";
|
||||
char invalid_ESR[] = "\240cccccccccccccccccccc";
|
||||
char invalid_SSR[] = "a\240cccccccccccccccccccc";
|
||||
char invalid_LSR[] = "abaabbaaabbb\240cccccccccccccccccccc";
|
||||
char invalid_RSR[] = "aaaaaaaaaaaaaaaaaaaa\240cccccccccccccccccccc";
|
||||
char invalid_ELE[] = "\240\240\240\240";
|
||||
char invalid_SLE[] = "a\240\240\240\240";
|
||||
char invalid_LLE[] = "abaabbaaabbb\240\240\240\240";
|
||||
char invalid_RLE[] = "aaaaaaaaaaaaaaaaaaaa\240\240\240\240";
|
||||
char invalid_ELS[] = "\240\240\240\240c";
|
||||
char invalid_SLS[] = "a\240\240\240\240c";
|
||||
char invalid_LLS[] = "abaabbaaabbb\240\240\240\240c";
|
||||
char invalid_RLS[] = "aaaaaaaaaaaaaaaaaaaa\240\240\240\240c";
|
||||
char invalid_ELL[] = "\240\240\240\240cdccddcccddd";
|
||||
char invalid_SLL[] = "a\240\240\240\240cdccddcccddd";
|
||||
char invalid_LLL[] = "abaabbaaabbb\240\240\240\240cdccddcccddd";
|
||||
char invalid_RLL[] = "aaaaaaaaaaaaaaaaaaaa\240\240\240\240cdccddcccddd";
|
||||
char invalid_ELR[] = "\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_SLR[] = "a\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_LLR[] = "abaabbaaabbb\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_RLR[] = "aaaaaaaaaaaaaaaaaaaa\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_ERE[] = ""
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240";
|
||||
char invalid_LRE[] = "abaabbaaabbb"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240";
|
||||
char invalid_RRE[] = "aaaaaaaaaaaaaaaaaaaa"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240";
|
||||
char invalid_ERS[] = ""
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240c";
|
||||
char invalid_ERL[] = ""
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cdccddcccddd";
|
||||
char invalid_ERR[] = ""
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_SRE[] = "a"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240";
|
||||
char invalid_SRS[] = "a"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240c";
|
||||
char invalid_SRL[] = "a"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cdccddcccddd";
|
||||
char invalid_SRR[] = "a"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_LRS[] = "abaabbaaabbb"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240c";
|
||||
char invalid_LRL[] = "abaabbaaabbb"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cdccddcccddd";
|
||||
char invalid_LRR[] = "abaabbaaabbb"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cccccccccccccccccccc";
|
||||
char invalid_RRS[] = "aaaaaaaaaaaaaaaaaaaa"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240c";
|
||||
char invalid_RRL[] = "aaaaaaaaaaaaaaaaaaaa"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cdccddcccddd";
|
||||
char invalid_RRR[] = "aaaaaaaaaaaaaaaaaaaa"
|
||||
"\240\240\240\240\240\240\240\240\240\240"
|
||||
"\240\240\240\240\240\240\240\240\240\240cccccccccccccccccccc";
|
||||
|
||||
/* -- */
|
||||
|
||||
int main ()
|
||||
|
|
|
@ -792,6 +792,76 @@ proc gdb_test_escape_braces { args } {
|
|||
gdb_test [lindex $args 0] $esc_pattern [lindex $args 2]
|
||||
}
|
||||
|
||||
proc test_repeat_bytes {} {
|
||||
set start(E) {}
|
||||
set start(S) {a}
|
||||
set start(L) {abaabbaaabbb}
|
||||
set start(R) {'a' <repeats 20 times>}
|
||||
set end(E) {}
|
||||
set end(S) {c}
|
||||
set end(L) {cdccddcccddd}
|
||||
set end(R) {'c' <repeats 20 times>}
|
||||
set invalid(S) {\\240}
|
||||
set invalid(L) {\\240\\240\\240\\240}
|
||||
set invalid(R) {'\\240' <repeats 20 times>}
|
||||
|
||||
set fmt(SSS) "\"%s%s%s\""
|
||||
set fmt(SSR) "\"%s%s\", %s"
|
||||
set fmt(SRS) "\"%s\", %s, \"%s\""
|
||||
set fmt(RSS) "%s, \"%s%s\""
|
||||
set fmt(RSR) "%s, \"%s\", %s"
|
||||
set fmt(SRR) "\"%s\", %s, %s"
|
||||
set fmt(RRS) "%s, %s, \"%s\""
|
||||
set fmt(RRR) "%s, %s, %s"
|
||||
|
||||
set fmt(RS) "%s, \"%s\""
|
||||
set fmt(RR) "%s, %s"
|
||||
set fmt(SR) "\"%s\", %s"
|
||||
set fmt(SS) "\"%s%s\""
|
||||
|
||||
# Test the various permutations of invalid characters
|
||||
foreach i [array names invalid] {
|
||||
set I $i
|
||||
|
||||
if {$i == "L"} {
|
||||
set i "S"
|
||||
}
|
||||
|
||||
foreach s [array names start] {
|
||||
set S $s
|
||||
|
||||
if {$s == "L"} {
|
||||
set s "S"
|
||||
}
|
||||
|
||||
|
||||
foreach e [array names end] {
|
||||
set E $e
|
||||
|
||||
if {$e == "L"} {
|
||||
set e "S"
|
||||
}
|
||||
|
||||
# Skip E*E.
|
||||
if {$s == "E" && $e == "E"} { continue }
|
||||
|
||||
# Special cases...
|
||||
if {$s == "E"} {
|
||||
set result [format $fmt($i$e) $invalid($I) $end($E)]
|
||||
} elseif {$e == "E"} {
|
||||
set result [format $fmt($s$i) $start($S) $invalid($I)]
|
||||
} else {
|
||||
set result [format $fmt($s$i$e) \
|
||||
$start($S) $invalid($I) $end($E)]
|
||||
}
|
||||
|
||||
send_log "expecting: = $result\n"
|
||||
gdb_test "print invalid_$S$I$E" "= $result"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Start with a fresh gdb.
|
||||
|
||||
gdb_exit
|
||||
|
@ -851,3 +921,4 @@ test_print_enums
|
|||
test_printf
|
||||
test_printf_with_dfp
|
||||
test_print_symbol
|
||||
test_repeat_bytes
|
||||
|
|
|
@ -25,11 +25,21 @@ do_nothing (wchar_t *c)
|
|||
int
|
||||
main (void)
|
||||
{
|
||||
int i;
|
||||
wchar_t narrow = 97;
|
||||
wchar_t single = 0xbeef;
|
||||
wchar_t simple[] = L"facile";
|
||||
wchar_t difficile[] = { 0xdead, 0xbeef, 0xfeed, 0xface};
|
||||
wchar_t mixed[] = {L'f', 0xdead, L'a', L'c', 0xfeed, 0xface};
|
||||
wchar_t *cent = L"\242";
|
||||
wchar_t repeat[128];
|
||||
wchar_t *repeat_p = repeat;
|
||||
|
||||
repeat[0] = 0;
|
||||
wcscat (repeat, L"A");
|
||||
for (i = 0; i < 21; ++i)
|
||||
wcscat (repeat, cent);
|
||||
wcscat (repeat, L"B");
|
||||
|
||||
do_nothing (&narrow); /* START */
|
||||
do_nothing (&single);
|
||||
|
|
|
@ -36,3 +36,22 @@ gdb_test "print simple\[2\]" "= 99 L'c'"
|
|||
|
||||
gdb_test "print difficile\[2\]" "= 65261 L'\\\\xfeed'"
|
||||
|
||||
set cent "\\\\242"
|
||||
gdb_test "print repeat" "= L\"A\", '$cent' <repeats 21 times>, \"B.*"
|
||||
|
||||
global hex
|
||||
gdb_test "print repeat_p" \
|
||||
"= $hex L\"A\", '$cent' <repeats 21 times>, \"B\""
|
||||
|
||||
gdb_test_no_output "set print null on"
|
||||
|
||||
gdb_test "print repeat" "= L\"A\", '$cent' <repeats 21 times>, \"B\"" \
|
||||
"print repeat (print null on)"
|
||||
|
||||
gdb_test_no_output "set print elements 3"
|
||||
|
||||
gdb_test "print repeat" "= L\"A$cent$cent\"\.\.\." \
|
||||
"print repeat (print elements 3)"
|
||||
|
||||
gdb_test "print repeat_p" "= $hex L\"A$cent$cent\"\.\.\." \
|
||||
"print repeat_p (print elements 3)"
|
||||
|
|
479
gdb/valprint.c
479
gdb/valprint.c
|
@ -40,6 +40,43 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
/* Maximum number of wchars returned from wchar_iterate. */
|
||||
#define MAX_WCHARS 4
|
||||
|
||||
/* A convenience macro to compute the size of a wchar_t buffer containing X
|
||||
characters. */
|
||||
#define WCHAR_BUFLEN(X) ((X) * sizeof (gdb_wchar_t))
|
||||
|
||||
/* Character buffer size saved while iterating over wchars. */
|
||||
#define WCHAR_BUFLEN_MAX WCHAR_BUFLEN (MAX_WCHARS)
|
||||
|
||||
/* A structure to encapsulate state information from iterated
|
||||
character conversions. */
|
||||
struct converted_character
|
||||
{
|
||||
/* The number of characters converted. */
|
||||
int num_chars;
|
||||
|
||||
/* The result of the conversion. See charset.h for more. */
|
||||
enum wchar_iterate_result result;
|
||||
|
||||
/* The (saved) converted character(s). */
|
||||
gdb_wchar_t chars[WCHAR_BUFLEN_MAX];
|
||||
|
||||
/* The first converted target byte. */
|
||||
const gdb_byte *buf;
|
||||
|
||||
/* The number of bytes converted. */
|
||||
size_t buflen;
|
||||
|
||||
/* How many times this character(s) is repeated. */
|
||||
int repeat_count;
|
||||
};
|
||||
|
||||
typedef struct converted_character converted_character_d;
|
||||
DEF_VEC_O (converted_character_d);
|
||||
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static int partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr,
|
||||
|
@ -2045,6 +2082,253 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream,
|
|||
do_cleanups (cleanups);
|
||||
}
|
||||
|
||||
/* Return the repeat count of the next character/byte in ITER,
|
||||
storing the result in VEC. */
|
||||
|
||||
static int
|
||||
count_next_character (struct wchar_iterator *iter,
|
||||
VEC (converted_character_d) **vec)
|
||||
{
|
||||
struct converted_character *current;
|
||||
|
||||
if (VEC_empty (converted_character_d, *vec))
|
||||
{
|
||||
struct converted_character tmp;
|
||||
gdb_wchar_t *chars;
|
||||
|
||||
tmp.num_chars
|
||||
= wchar_iterate (iter, &tmp.result, &chars, &tmp.buf, &tmp.buflen);
|
||||
if (tmp.num_chars > 0)
|
||||
{
|
||||
gdb_assert (tmp.num_chars < MAX_WCHARS);
|
||||
memcpy (tmp.chars, chars, tmp.num_chars * sizeof (gdb_wchar_t));
|
||||
}
|
||||
VEC_safe_push (converted_character_d, *vec, &tmp);
|
||||
}
|
||||
|
||||
current = VEC_last (converted_character_d, *vec);
|
||||
|
||||
/* Count repeated characters or bytes. */
|
||||
current->repeat_count = 1;
|
||||
if (current->num_chars == -1)
|
||||
{
|
||||
/* EOF */
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gdb_wchar_t *chars;
|
||||
struct converted_character d;
|
||||
int repeat;
|
||||
|
||||
d.repeat_count = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Get the next character. */
|
||||
d.num_chars
|
||||
= wchar_iterate (iter, &d.result, &chars, &d.buf, &d.buflen);
|
||||
|
||||
/* If a character was successfully converted, save the character
|
||||
into the converted character. */
|
||||
if (d.num_chars > 0)
|
||||
{
|
||||
gdb_assert (d.num_chars < MAX_WCHARS);
|
||||
memcpy (d.chars, chars, WCHAR_BUFLEN (d.num_chars));
|
||||
}
|
||||
|
||||
/* Determine if the current character is the same as this
|
||||
new character. */
|
||||
if (d.num_chars == current->num_chars && d.result == current->result)
|
||||
{
|
||||
/* There are two cases to consider:
|
||||
|
||||
1) Equality of converted character (num_chars > 0)
|
||||
2) Equality of non-converted character (num_chars == 0) */
|
||||
if ((current->num_chars > 0
|
||||
&& memcmp (current->chars, d.chars,
|
||||
WCHAR_BUFLEN (current->num_chars)) == 0)
|
||||
|| (current->num_chars == 0
|
||||
&& current->buflen == d.buflen
|
||||
&& memcmp (current->buf, d.buf, current->buflen) == 0))
|
||||
++current->repeat_count;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
/* Push this next converted character onto the result vector. */
|
||||
repeat = current->repeat_count;
|
||||
VEC_safe_push (converted_character_d, *vec, &d);
|
||||
return repeat;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the characters in CHARS to the OBSTACK. QUOTE_CHAR is the quote
|
||||
character to use with string output. WIDTH is the size of the output
|
||||
character type. BYTE_ORDER is the the target byte order. OPTIONS
|
||||
is the user's print options. */
|
||||
|
||||
static void
|
||||
print_converted_chars_to_obstack (struct obstack *obstack,
|
||||
VEC (converted_character_d) *chars,
|
||||
int quote_char, int width,
|
||||
enum bfd_endian byte_order,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
unsigned int idx;
|
||||
struct converted_character *elem;
|
||||
enum {START, SINGLE, REPEAT, INCOMPLETE, FINISH} state, last;
|
||||
gdb_wchar_t wide_quote_char = gdb_btowc (quote_char);
|
||||
int need_escape = 0;
|
||||
|
||||
/* Set the start state. */
|
||||
idx = 0;
|
||||
last = state = START;
|
||||
elem = NULL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case START:
|
||||
/* Nothing to do. */
|
||||
break;
|
||||
|
||||
case SINGLE:
|
||||
{
|
||||
int j;
|
||||
|
||||
/* We are outputting a single character
|
||||
(< options->repeat_count_threshold). */
|
||||
|
||||
if (last != SINGLE)
|
||||
{
|
||||
/* We were outputting some other type of content, so we
|
||||
must output and a comma and a quote. */
|
||||
if (last != START)
|
||||
obstack_grow_wstr (obstack, LCST (", "));
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (obstack, LCST ("\\"));
|
||||
obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t));
|
||||
}
|
||||
/* Output the character. */
|
||||
for (j = 0; j < elem->repeat_count; ++j)
|
||||
{
|
||||
if (elem->result == wchar_iterate_ok)
|
||||
print_wchar (elem->chars[0], elem->buf, elem->buflen, width,
|
||||
byte_order, obstack, quote_char, &need_escape);
|
||||
else
|
||||
print_wchar (gdb_WEOF, elem->buf, elem->buflen, width,
|
||||
byte_order, obstack, quote_char, &need_escape);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case REPEAT:
|
||||
{
|
||||
int j;
|
||||
char *s;
|
||||
|
||||
/* We are outputting a character with a repeat count
|
||||
greater than options->repeat_count_threshold. */
|
||||
|
||||
if (last == SINGLE)
|
||||
{
|
||||
/* We were outputting a single string. Terminate the
|
||||
string. */
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (obstack, LCST ("\\"));
|
||||
obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t));
|
||||
}
|
||||
if (last != START)
|
||||
obstack_grow_wstr (obstack, LCST (", "));
|
||||
|
||||
/* Output the character and repeat string. */
|
||||
obstack_grow_wstr (obstack, LCST ("'"));
|
||||
if (elem->result == wchar_iterate_ok)
|
||||
print_wchar (elem->chars[0], elem->buf, elem->buflen, width,
|
||||
byte_order, obstack, quote_char, &need_escape);
|
||||
else
|
||||
print_wchar (gdb_WEOF, elem->buf, elem->buflen, width,
|
||||
byte_order, obstack, quote_char, &need_escape);
|
||||
obstack_grow_wstr (obstack, LCST ("'"));
|
||||
s = xstrprintf (_(" <repeats %u times>"), elem->repeat_count);
|
||||
for (j = 0; s[j]; ++j)
|
||||
{
|
||||
gdb_wchar_t w = gdb_btowc (s[j]);
|
||||
obstack_grow (obstack, &w, sizeof (gdb_wchar_t));
|
||||
}
|
||||
xfree (s);
|
||||
}
|
||||
break;
|
||||
|
||||
case INCOMPLETE:
|
||||
/* We are outputting an incomplete sequence. */
|
||||
if (last == SINGLE)
|
||||
{
|
||||
/* If we were outputting a string of SINGLE characters,
|
||||
terminate the quote. */
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (obstack, LCST ("\\"));
|
||||
obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t));
|
||||
}
|
||||
if (last != START)
|
||||
obstack_grow_wstr (obstack, LCST (", "));
|
||||
|
||||
/* Output the incomplete sequence string. */
|
||||
obstack_grow_wstr (obstack, LCST ("<incomplete sequence "));
|
||||
print_wchar (gdb_WEOF, elem->buf, elem->buflen, width, byte_order,
|
||||
obstack, 0, &need_escape);
|
||||
obstack_grow_wstr (obstack, LCST (">"));
|
||||
|
||||
/* We do not attempt to outupt anything after this. */
|
||||
state = FINISH;
|
||||
break;
|
||||
|
||||
case FINISH:
|
||||
/* All done. If we were outputting a string of SINGLE
|
||||
characters, the string must be terminated. Otherwise,
|
||||
REPEAT and INCOMPLETE are always left properly terminated. */
|
||||
if (last == SINGLE)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (obstack, LCST ("\\"));
|
||||
obstack_grow (obstack, &wide_quote_char, sizeof (gdb_wchar_t));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the next element and state. */
|
||||
last = state;
|
||||
if (state != FINISH)
|
||||
{
|
||||
elem = VEC_index (converted_character_d, chars, idx++);
|
||||
switch (elem->result)
|
||||
{
|
||||
case wchar_iterate_ok:
|
||||
case wchar_iterate_invalid:
|
||||
if (elem->repeat_count > options->repeat_count_threshold)
|
||||
state = REPEAT;
|
||||
else
|
||||
state = SINGLE;
|
||||
break;
|
||||
|
||||
case wchar_iterate_incomplete:
|
||||
state = INCOMPLETE;
|
||||
break;
|
||||
|
||||
case wchar_iterate_eof:
|
||||
state = FINISH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the character string STRING, printing at most LENGTH
|
||||
characters. LENGTH is -1 if the string is nul terminated. TYPE is
|
||||
the type of each character. OPTIONS holds the printing options;
|
||||
|
@ -2064,16 +2348,13 @@ generic_printstr (struct ui_file *stream, struct type *type,
|
|||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
int width = TYPE_LENGTH (type);
|
||||
struct obstack wchar_buf, output;
|
||||
struct cleanup *cleanup;
|
||||
struct wchar_iterator *iter;
|
||||
int finished = 0;
|
||||
int need_escape = 0;
|
||||
gdb_wchar_t wide_quote_char = gdb_btowc (quote_char);
|
||||
struct converted_character *last;
|
||||
VEC (converted_character_d) *converted_chars;
|
||||
|
||||
if (length == -1)
|
||||
{
|
||||
|
@ -2107,166 +2388,46 @@ generic_printstr (struct ui_file *stream, struct type *type,
|
|||
/* Arrange to iterate over the characters, in wchar_t form. */
|
||||
iter = make_wchar_iterator (string, length * width, encoding, width);
|
||||
cleanup = make_cleanup_wchar_iterator (iter);
|
||||
converted_chars = NULL;
|
||||
make_cleanup (VEC_cleanup (converted_character_d), &converted_chars);
|
||||
|
||||
/* Convert characters until the string is over or the maximum
|
||||
number of printed characters has been reached. */
|
||||
i = 0;
|
||||
while (i < options->print_max)
|
||||
{
|
||||
int r;
|
||||
|
||||
QUIT;
|
||||
|
||||
/* Grab the next character and repeat count. */
|
||||
r = count_next_character (iter, &converted_chars);
|
||||
|
||||
/* If less than zero, the end of the input string was reached. */
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
/* Otherwise, add the count to the total print count and get
|
||||
the next character. */
|
||||
i += r;
|
||||
}
|
||||
|
||||
/* Get the last element and determine if the entire string was
|
||||
processed. */
|
||||
last = VEC_last (converted_character_d, converted_chars);
|
||||
finished = (last->result == wchar_iterate_eof);
|
||||
|
||||
/* Ensure that CONVERTED_CHARS is terminated. */
|
||||
last->result = wchar_iterate_eof;
|
||||
|
||||
/* WCHAR_BUF is the obstack we use to represent the string in
|
||||
wchar_t form. */
|
||||
obstack_init (&wchar_buf);
|
||||
make_cleanup_obstack_free (&wchar_buf);
|
||||
|
||||
while (!finished && things_printed < options->print_max)
|
||||
{
|
||||
int num_chars;
|
||||
enum wchar_iterate_result result;
|
||||
gdb_wchar_t *chars;
|
||||
const gdb_byte *buf;
|
||||
size_t buflen;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
obstack_grow_wstr (&wchar_buf, LCST (", "));
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen);
|
||||
/* We only look at repetitions when we were able to convert a
|
||||
single character in isolation. This makes the code simpler
|
||||
and probably does the sensible thing in the majority of
|
||||
cases. */
|
||||
while (num_chars == 1 && things_printed < options->print_max)
|
||||
{
|
||||
/* Count the number of repetitions. */
|
||||
unsigned int reps = 0;
|
||||
gdb_wchar_t current_char = chars[0];
|
||||
const gdb_byte *orig_buf = buf;
|
||||
int orig_len = buflen;
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
obstack_grow_wstr (&wchar_buf, LCST (", "));
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
while (num_chars == 1 && current_char == chars[0])
|
||||
{
|
||||
num_chars = wchar_iterate (iter, &result, &chars,
|
||||
&buf, &buflen);
|
||||
++reps;
|
||||
}
|
||||
|
||||
/* Emit CURRENT_CHAR according to the repetition count and
|
||||
options. */
|
||||
if (reps > options->repeat_count_threshold)
|
||||
{
|
||||
if (in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\\"));
|
||||
obstack_grow (&wchar_buf, &wide_quote_char,
|
||||
sizeof (gdb_wchar_t));
|
||||
obstack_grow_wstr (&wchar_buf, LCST (", "));
|
||||
in_quotes = 0;
|
||||
}
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("'"));
|
||||
need_escape = 0;
|
||||
print_wchar (current_char, orig_buf, orig_len, width,
|
||||
byte_order, &wchar_buf, '\'', &need_escape);
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("'"));
|
||||
{
|
||||
/* Painful gyrations. */
|
||||
int j;
|
||||
char *s = xstrprintf (_(" <repeats %u times>"), reps);
|
||||
|
||||
for (j = 0; s[j]; ++j)
|
||||
{
|
||||
gdb_wchar_t w = gdb_btowc (s[j]);
|
||||
obstack_grow (&wchar_buf, &w, sizeof (gdb_wchar_t));
|
||||
}
|
||||
xfree (s);
|
||||
}
|
||||
things_printed += options->repeat_count_threshold;
|
||||
need_comma = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Saw the character one or more times, but fewer than
|
||||
the repetition threshold. */
|
||||
if (!in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\\"));
|
||||
obstack_grow (&wchar_buf, &wide_quote_char,
|
||||
sizeof (gdb_wchar_t));
|
||||
in_quotes = 1;
|
||||
need_escape = 0;
|
||||
}
|
||||
|
||||
while (reps-- > 0)
|
||||
{
|
||||
print_wchar (current_char, orig_buf,
|
||||
orig_len, width,
|
||||
byte_order, &wchar_buf,
|
||||
quote_char, &need_escape);
|
||||
++things_printed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NUM_CHARS and the other outputs from wchar_iterate are valid
|
||||
here regardless of which branch was taken above. */
|
||||
if (num_chars < 0)
|
||||
{
|
||||
/* Hit EOF. */
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case wchar_iterate_invalid:
|
||||
if (!in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\\"));
|
||||
obstack_grow (&wchar_buf, &wide_quote_char,
|
||||
sizeof (gdb_wchar_t));
|
||||
in_quotes = 1;
|
||||
}
|
||||
need_escape = 0;
|
||||
print_wchar (gdb_WEOF, buf, buflen, width, byte_order,
|
||||
&wchar_buf, quote_char, &need_escape);
|
||||
break;
|
||||
|
||||
case wchar_iterate_incomplete:
|
||||
if (in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\\"));
|
||||
obstack_grow (&wchar_buf, &wide_quote_char,
|
||||
sizeof (gdb_wchar_t));
|
||||
obstack_grow_wstr (&wchar_buf, LCST (","));
|
||||
in_quotes = 0;
|
||||
}
|
||||
obstack_grow_wstr (&wchar_buf,
|
||||
LCST (" <incomplete sequence "));
|
||||
print_wchar (gdb_WEOF, buf, buflen, width,
|
||||
byte_order, &wchar_buf,
|
||||
0, &need_escape);
|
||||
obstack_grow_wstr (&wchar_buf, LCST (">"));
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\\"));
|
||||
obstack_grow (&wchar_buf, &wide_quote_char,
|
||||
sizeof (gdb_wchar_t));
|
||||
}
|
||||
/* Print the output string to the obstack. */
|
||||
print_converted_chars_to_obstack (&wchar_buf, converted_chars, quote_char,
|
||||
width, byte_order, options);
|
||||
|
||||
if (force_ellipses || !finished)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("..."));
|
||||
|
|
Loading…
Reference in a new issue