From: Keith Seitz Date: Sat, 10 Nov 2012 20:19:01 +0000 (+0000) Subject: PR gdb/14288 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0d63ecdad04d410698c905283d095505680ba907;p=binutils-gdb.git 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b8fc3969c9a..4175f2ff7cb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +2012-11-10 Keith Seitz + + 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 * tui/tui.c (tui_rl_command_key): Switch to TUI_ONE_COMMAND_MODE diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 7a1bb02be63..dada9e2ac2c 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -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 diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 26f2b3f08f4..f42ca37d43c 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2012-11-10 Keith Seitz + + 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 * gdb.mi/mi-disassemble.exp: Expect fullname field in mi diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c index 743734b4a5c..d80c13d95af 100644 --- a/gdb/testsuite/gdb.base/printcmds.c +++ b/gdb/testsuite/gdb.base/printcmds.c @@ -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 () diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index 4f76cec98f7..4dfe90f3f11 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -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' } + set end(E) {} + set end(S) {c} + set end(L) {cdccddcccddd} + set end(R) {'c' } + set invalid(S) {\\240} + set invalid(L) {\\240\\240\\240\\240} + set invalid(R) {'\\240' } + + 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 diff --git a/gdb/testsuite/gdb.base/wchar.c b/gdb/testsuite/gdb.base/wchar.c index 22f5beb5341..7bdfd68677e 100644 --- a/gdb/testsuite/gdb.base/wchar.c +++ b/gdb/testsuite/gdb.base/wchar.c @@ -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); diff --git a/gdb/testsuite/gdb.base/wchar.exp b/gdb/testsuite/gdb.base/wchar.exp index 2451d92edcd..4c7ebf1fc40 100644 --- a/gdb/testsuite/gdb.base/wchar.exp +++ b/gdb/testsuite/gdb.base/wchar.exp @@ -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' , \"B.*" + +global hex +gdb_test "print repeat_p" \ + "= $hex L\"A\", '$cent' , \"B\"" + +gdb_test_no_output "set print null on" + +gdb_test "print repeat" "= L\"A\", '$cent' , \"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)" diff --git a/gdb/valprint.c b/gdb/valprint.c index 583329d3baf..8600be03dce 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -40,6 +40,43 @@ #include +/* 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 (_(" "), 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 ("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); - /* 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) + /* 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 num_chars; - enum wchar_iterate_result result; - gdb_wchar_t *chars; - const gdb_byte *buf; - size_t buflen; + int r; 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; - } + /* Grab the next character and repeat count. */ + r = count_next_character (iter, &converted_chars); - /* 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 (_(" "), 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; - } + /* If less than zero, the end of the input string was reached. */ + if (r < 0) + break; - while (reps-- > 0) - { - print_wchar (current_char, orig_buf, - orig_len, width, - byte_order, &wchar_buf, - quote_char, &need_escape); - ++things_printed; - } - } - } + /* Otherwise, add the count to the total print count and get + the next character. */ + i += r; + } - /* 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; - } + /* 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); - 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; + /* Ensure that CONVERTED_CHARS is terminated. */ + last->result = wchar_iterate_eof; - 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 (" ")); - finished = 1; - break; - } - } + /* 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); - /* 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 ("..."));