gdb
PR fortran/10036: * valprint.h (generic_emit_char, generic_printstr): Declare. * valprint.c (wchar_printable, append_string_as_wide) (print_wchar): Move from c-lang.c. (generic_emit_char): New function; mostly taken from c_emit_char. (generic_printstr): New function; mostly taken from c_printstr. * f-valprint.c (f_val_print) <TYPE_CODE_ARRAY>: Handle strings represented as arrays. <TYPE_CODE_CHAR>: Treat as TYPE_CODE_INT; recognize as character type. * f-typeprint.c (f_type_print_base) <TYPE_CODE_CHAR>: Treat identically to TYPE_CODE_INT. * f-lang.c (f_get_encoding): New function. (f_emit_char): Use generic_emit_char. (f_printchar): Replace comment. (f_printstr): Use generic_printstr. * dwarf2read.c (read_base_type) <DW_ATE_unsigned>: Handle Fortran "character" types specially. <DW_ATE_signed_char, DW_ATE_unsigned_char>: Make TYPE_CODE_CHAR for Fortran. * c-lang.c (wchar_printable, append_string_as_wide, print_wchar): Move to valprint.c (c_emit_char): Call generic_emit_char. (c_printstr): Call generic_printstr. gdb/testsuite * gdb.fortran/charset.exp: New file. * gdb.fortran/charset.f90: New file.
This commit is contained in:
parent
168e6d4402
commit
3b2b8feaf4
11 changed files with 616 additions and 528 deletions
|
@ -1,3 +1,30 @@
|
|||
2011-06-29 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR fortran/10036:
|
||||
* valprint.h (generic_emit_char, generic_printstr): Declare.
|
||||
* valprint.c (wchar_printable, append_string_as_wide)
|
||||
(print_wchar): Move from c-lang.c.
|
||||
(generic_emit_char): New function; mostly taken from c_emit_char.
|
||||
(generic_printstr): New function; mostly taken from c_printstr.
|
||||
* f-valprint.c (f_val_print) <TYPE_CODE_ARRAY>: Handle strings
|
||||
represented as arrays.
|
||||
<TYPE_CODE_CHAR>: Treat as TYPE_CODE_INT; recognize as character
|
||||
type.
|
||||
* f-typeprint.c (f_type_print_base) <TYPE_CODE_CHAR>: Treat
|
||||
identically to TYPE_CODE_INT.
|
||||
* f-lang.c (f_get_encoding): New function.
|
||||
(f_emit_char): Use generic_emit_char.
|
||||
(f_printchar): Replace comment.
|
||||
(f_printstr): Use generic_printstr.
|
||||
* dwarf2read.c (read_base_type) <DW_ATE_unsigned>: Handle Fortran
|
||||
"character" types specially.
|
||||
<DW_ATE_signed_char, DW_ATE_unsigned_char>: Make TYPE_CODE_CHAR
|
||||
for Fortran.
|
||||
* c-lang.c (wchar_printable, append_string_as_wide, print_wchar):
|
||||
Move to valprint.c
|
||||
(c_emit_char): Call generic_emit_char.
|
||||
(c_printstr): Call generic_printstr.
|
||||
|
||||
2011-06-29 Gary Benson <gbenson@redhat.com>
|
||||
|
||||
* breakpoint.c (bpstat_what): Removed duplicated case.
|
||||
|
|
412
gdb/c-lang.c
412
gdb/c-lang.c
|
@ -140,123 +140,6 @@ classify_type (struct type *elttype, struct gdbarch *gdbarch,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Return true if print_wchar can display W without resorting to a
|
||||
numeric escape, false otherwise. */
|
||||
|
||||
static int
|
||||
wchar_printable (gdb_wchar_t w)
|
||||
{
|
||||
return (gdb_iswprint (w)
|
||||
|| w == LCST ('\a') || w == LCST ('\b')
|
||||
|| w == LCST ('\f') || w == LCST ('\n')
|
||||
|| w == LCST ('\r') || w == LCST ('\t')
|
||||
|| w == LCST ('\v'));
|
||||
}
|
||||
|
||||
/* A helper function that converts the contents of STRING to wide
|
||||
characters and then appends them to OUTPUT. */
|
||||
|
||||
static void
|
||||
append_string_as_wide (const char *string,
|
||||
struct obstack *output)
|
||||
{
|
||||
for (; *string; ++string)
|
||||
{
|
||||
gdb_wchar_t w = gdb_btowc (*string);
|
||||
obstack_grow (output, &w, sizeof (gdb_wchar_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a wide character W to OUTPUT. ORIG is a pointer to the
|
||||
original (target) bytes representing the character, ORIG_LEN is the
|
||||
number of valid bytes. WIDTH is the number of bytes in a base
|
||||
characters of the type. OUTPUT is an obstack to which wide
|
||||
characters are emitted. QUOTER is a (narrow) character indicating
|
||||
the style of quotes surrounding the character to be printed.
|
||||
NEED_ESCAPE is an in/out flag which is used to track numeric
|
||||
escapes across calls. */
|
||||
|
||||
static void
|
||||
print_wchar (gdb_wint_t w, const gdb_byte *orig,
|
||||
int orig_len, int width,
|
||||
enum bfd_endian byte_order,
|
||||
struct obstack *output,
|
||||
int quoter, int *need_escapep)
|
||||
{
|
||||
int need_escape = *need_escapep;
|
||||
|
||||
*need_escapep = 0;
|
||||
if (gdb_iswprint (w) && (!need_escape || (!gdb_iswdigit (w)
|
||||
&& w != LCST ('8')
|
||||
&& w != LCST ('9'))))
|
||||
{
|
||||
gdb_wchar_t wchar = w;
|
||||
|
||||
if (w == gdb_btowc (quoter) || w == LCST ('\\'))
|
||||
obstack_grow_wstr (output, LCST ("\\"));
|
||||
obstack_grow (output, &wchar, sizeof (gdb_wchar_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (w)
|
||||
{
|
||||
case LCST ('\a'):
|
||||
obstack_grow_wstr (output, LCST ("\\a"));
|
||||
break;
|
||||
case LCST ('\b'):
|
||||
obstack_grow_wstr (output, LCST ("\\b"));
|
||||
break;
|
||||
case LCST ('\f'):
|
||||
obstack_grow_wstr (output, LCST ("\\f"));
|
||||
break;
|
||||
case LCST ('\n'):
|
||||
obstack_grow_wstr (output, LCST ("\\n"));
|
||||
break;
|
||||
case LCST ('\r'):
|
||||
obstack_grow_wstr (output, LCST ("\\r"));
|
||||
break;
|
||||
case LCST ('\t'):
|
||||
obstack_grow_wstr (output, LCST ("\\t"));
|
||||
break;
|
||||
case LCST ('\v'):
|
||||
obstack_grow_wstr (output, LCST ("\\v"));
|
||||
break;
|
||||
default:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i + width <= orig_len; i += width)
|
||||
{
|
||||
char octal[30];
|
||||
ULONGEST value;
|
||||
|
||||
value = extract_unsigned_integer (&orig[i], width,
|
||||
byte_order);
|
||||
/* If the value fits in 3 octal digits, print it that
|
||||
way. Otherwise, print it as a hex escape. */
|
||||
if (value <= 0777)
|
||||
sprintf (octal, "\\%.3o", (int) (value & 0777));
|
||||
else
|
||||
sprintf (octal, "\\x%lx", (long) value);
|
||||
append_string_as_wide (octal, output);
|
||||
}
|
||||
/* If we somehow have extra bytes, print them now. */
|
||||
while (i < orig_len)
|
||||
{
|
||||
char octal[5];
|
||||
|
||||
sprintf (octal, "\\%.3o", orig[i] & 0xff);
|
||||
append_string_as_wide (octal, output);
|
||||
++i;
|
||||
}
|
||||
|
||||
*need_escapep = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a
|
||||
literal string whose delimiter is QUOTER. Note that that format
|
||||
for printing characters and strings is language specific. */
|
||||
|
@ -265,85 +148,10 @@ void
|
|||
c_emit_char (int c, struct type *type,
|
||||
struct ui_file *stream, int quoter)
|
||||
{
|
||||
enum bfd_endian byte_order
|
||||
= gdbarch_byte_order (get_type_arch (type));
|
||||
struct obstack wchar_buf, output;
|
||||
struct cleanup *cleanups;
|
||||
const char *encoding;
|
||||
gdb_byte *buf;
|
||||
struct wchar_iterator *iter;
|
||||
int need_escape = 0;
|
||||
|
||||
classify_type (type, get_type_arch (type), &encoding);
|
||||
|
||||
buf = alloca (TYPE_LENGTH (type));
|
||||
pack_long (buf, type, c);
|
||||
|
||||
iter = make_wchar_iterator (buf, TYPE_LENGTH (type),
|
||||
encoding, TYPE_LENGTH (type));
|
||||
cleanups = make_cleanup_wchar_iterator (iter);
|
||||
|
||||
/* This holds the printable form of the wchar_t data. */
|
||||
obstack_init (&wchar_buf);
|
||||
make_cleanup_obstack_free (&wchar_buf);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int num_chars;
|
||||
gdb_wchar_t *chars;
|
||||
const gdb_byte *buf;
|
||||
size_t buflen;
|
||||
int print_escape = 1;
|
||||
enum wchar_iterate_result result;
|
||||
|
||||
num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen);
|
||||
if (num_chars < 0)
|
||||
break;
|
||||
if (num_chars > 0)
|
||||
{
|
||||
/* If all characters are printable, print them. Otherwise,
|
||||
we're going to have to print an escape sequence. We
|
||||
check all characters because we want to print the target
|
||||
bytes in the escape sequence, and we don't know character
|
||||
boundaries there. */
|
||||
int i;
|
||||
|
||||
print_escape = 0;
|
||||
for (i = 0; i < num_chars; ++i)
|
||||
if (!wchar_printable (chars[i]))
|
||||
{
|
||||
print_escape = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!print_escape)
|
||||
{
|
||||
for (i = 0; i < num_chars; ++i)
|
||||
print_wchar (chars[i], buf, buflen,
|
||||
TYPE_LENGTH (type), byte_order,
|
||||
&wchar_buf, quoter, &need_escape);
|
||||
}
|
||||
}
|
||||
|
||||
/* This handles the NUM_CHARS == 0 case as well. */
|
||||
if (print_escape)
|
||||
print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type),
|
||||
byte_order, &wchar_buf, quoter, &need_escape);
|
||||
}
|
||||
|
||||
/* The output in the host encoding. */
|
||||
obstack_init (&output);
|
||||
make_cleanup_obstack_free (&output);
|
||||
|
||||
convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (),
|
||||
obstack_base (&wchar_buf),
|
||||
obstack_object_size (&wchar_buf),
|
||||
1, &output, translit_char);
|
||||
obstack_1grow (&output, '\0');
|
||||
|
||||
fputs_filtered (obstack_base (&output), stream);
|
||||
|
||||
do_cleanups (cleanups);
|
||||
generic_emit_char (c, type, stream, quoter, encoding);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -385,6 +193,10 @@ c_printstr (struct ui_file *stream, struct type *type,
|
|||
const char *user_encoding, int force_ellipses,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
enum c_string_type str_type;
|
||||
const char *type_encoding;
|
||||
const char *encoding;
|
||||
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
|
@ -393,35 +205,10 @@ c_printstr (struct ui_file *stream, struct type *type,
|
|||
int width = TYPE_LENGTH (type);
|
||||
struct obstack wchar_buf, output;
|
||||
struct cleanup *cleanup;
|
||||
enum c_string_type str_type;
|
||||
const char *type_encoding;
|
||||
const char *encoding;
|
||||
struct wchar_iterator *iter;
|
||||
int finished = 0;
|
||||
int need_escape = 0;
|
||||
|
||||
if (length == -1)
|
||||
{
|
||||
unsigned long current_char = 1;
|
||||
|
||||
for (i = 0; current_char; ++i)
|
||||
{
|
||||
QUIT;
|
||||
current_char = extract_unsigned_integer (string + i * width,
|
||||
width, byte_order);
|
||||
}
|
||||
length = i;
|
||||
}
|
||||
|
||||
/* If the string was not truncated due to `set print elements', and
|
||||
the last byte of it is a null, we don't print that, in
|
||||
traditional C style. */
|
||||
if (!force_ellipses
|
||||
&& length > 0
|
||||
&& (extract_unsigned_integer (string + (length - 1) * width,
|
||||
width, byte_order) == 0))
|
||||
length--;
|
||||
|
||||
str_type = (classify_type (type, get_type_arch (type), &type_encoding)
|
||||
& ~C_CHAR);
|
||||
switch (str_type)
|
||||
|
@ -439,193 +226,10 @@ c_printstr (struct ui_file *stream, struct type *type,
|
|||
break;
|
||||
}
|
||||
|
||||
encoding = (user_encoding && *user_encoding)
|
||||
? user_encoding : type_encoding;
|
||||
encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("\"\"", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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 ("\\\", "));
|
||||
else
|
||||
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 ("\\\""));
|
||||
else
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\""));
|
||||
in_quotes = 1;
|
||||
need_escape = 0;
|
||||
}
|
||||
|
||||
while (reps-- > 0)
|
||||
{
|
||||
print_wchar (current_char, orig_buf,
|
||||
orig_len, width,
|
||||
byte_order, &wchar_buf,
|
||||
'"', &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 ("\\\""));
|
||||
else
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\""));
|
||||
in_quotes = 1;
|
||||
}
|
||||
need_escape = 0;
|
||||
print_wchar (gdb_WEOF, buf, buflen, width, byte_order,
|
||||
&wchar_buf, '"', &need_escape);
|
||||
break;
|
||||
|
||||
case wchar_iterate_incomplete:
|
||||
if (in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\\\","));
|
||||
else
|
||||
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 ("\\\""));
|
||||
else
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("\""));
|
||||
}
|
||||
|
||||
if (force_ellipses || !finished)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("..."));
|
||||
|
||||
/* OUTPUT is where we collect `char's for printing. */
|
||||
obstack_init (&output);
|
||||
make_cleanup_obstack_free (&output);
|
||||
|
||||
convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (),
|
||||
obstack_base (&wchar_buf),
|
||||
obstack_object_size (&wchar_buf),
|
||||
1, &output, translit_char);
|
||||
obstack_1grow (&output, '\0');
|
||||
|
||||
fputs_filtered (obstack_base (&output), stream);
|
||||
|
||||
do_cleanups (cleanup);
|
||||
generic_printstr (stream, type, string, length, encoding, force_ellipses,
|
||||
'"', 1, options);
|
||||
}
|
||||
|
||||
/* Obtain a C string from the inferior storing it in a newly allocated
|
||||
|
|
|
@ -8335,15 +8335,21 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
|
|||
break;
|
||||
case DW_ATE_unsigned:
|
||||
type_flags |= TYPE_FLAG_UNSIGNED;
|
||||
if (cu->language == language_fortran
|
||||
&& name
|
||||
&& strncmp (name, "character(", sizeof ("character(") - 1) == 0)
|
||||
code = TYPE_CODE_CHAR;
|
||||
break;
|
||||
case DW_ATE_signed_char:
|
||||
if (cu->language == language_ada || cu->language == language_m2
|
||||
|| cu->language == language_pascal)
|
||||
|| cu->language == language_pascal
|
||||
|| cu->language == language_fortran)
|
||||
code = TYPE_CODE_CHAR;
|
||||
break;
|
||||
case DW_ATE_unsigned_char:
|
||||
if (cu->language == language_ada || cu->language == language_m2
|
||||
|| cu->language == language_pascal)
|
||||
|| cu->language == language_pascal
|
||||
|| cu->language == language_fortran)
|
||||
code = TYPE_CODE_CHAR;
|
||||
type_flags |= TYPE_FLAG_UNSIGNED;
|
||||
break;
|
||||
|
|
151
gdb/f-lang.c
151
gdb/f-lang.c
|
@ -32,6 +32,7 @@
|
|||
#include "valprint.h"
|
||||
#include "value.h"
|
||||
#include "cp-support.h"
|
||||
#include "charset.h"
|
||||
|
||||
|
||||
/* Following is dubious stuff that had been in the xcoff reader. */
|
||||
|
@ -76,6 +77,33 @@ static void f_printchar (int c, struct type *type, struct ui_file * stream);
|
|||
static void f_emit_char (int c, struct type *type,
|
||||
struct ui_file * stream, int quoter);
|
||||
|
||||
/* Return the encoding that should be used for the character type
|
||||
TYPE. */
|
||||
|
||||
static const char *
|
||||
f_get_encoding (struct type *type)
|
||||
{
|
||||
const char *encoding;
|
||||
|
||||
switch (TYPE_LENGTH (type))
|
||||
{
|
||||
case 1:
|
||||
encoding = target_charset (get_type_arch (type));
|
||||
break;
|
||||
case 4:
|
||||
if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_BIG)
|
||||
encoding = "UTF-32BE";
|
||||
else
|
||||
encoding = "UTF-32LE";
|
||||
break;
|
||||
|
||||
default:
|
||||
error (_("unrecognized character type"));
|
||||
}
|
||||
|
||||
return encoding;
|
||||
}
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string whose delimiter is QUOTER. Note that that format for printing
|
||||
characters and strings is language specific.
|
||||
|
@ -85,48 +113,12 @@ static void f_emit_char (int c, struct type *type,
|
|||
static void
|
||||
f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
|
||||
{
|
||||
c &= 0xFF; /* Avoid sign bit follies. */
|
||||
const char *encoding = f_get_encoding (type);
|
||||
|
||||
if (PRINT_LITERAL_FORM (c))
|
||||
{
|
||||
if (c == '\\' || c == quoter)
|
||||
fputs_filtered ("\\", stream);
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\n':
|
||||
fputs_filtered ("\\n", stream);
|
||||
break;
|
||||
case '\b':
|
||||
fputs_filtered ("\\b", stream);
|
||||
break;
|
||||
case '\t':
|
||||
fputs_filtered ("\\t", stream);
|
||||
break;
|
||||
case '\f':
|
||||
fputs_filtered ("\\f", stream);
|
||||
break;
|
||||
case '\r':
|
||||
fputs_filtered ("\\r", stream);
|
||||
break;
|
||||
case '\033':
|
||||
fputs_filtered ("\\e", stream);
|
||||
break;
|
||||
case '\007':
|
||||
fputs_filtered ("\\a", stream);
|
||||
break;
|
||||
default:
|
||||
fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
generic_emit_char (c, type, stream, quoter, encoding);
|
||||
}
|
||||
|
||||
/* FIXME: This is a copy of the same function from c-exp.y. It should
|
||||
be replaced with a true F77version. */
|
||||
/* Implementation of la_printchar. */
|
||||
|
||||
static void
|
||||
f_printchar (int c, struct type *type, struct ui_file *stream)
|
||||
|
@ -148,83 +140,16 @@ f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string,
|
|||
unsigned int length, const char *encoding, int force_ellipses,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
const char *type_encoding = f_get_encoding (type);
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("''", gdb_stdout);
|
||||
return;
|
||||
}
|
||||
if (TYPE_LENGTH (type) == 4)
|
||||
fputs_filtered ("4_", stream);
|
||||
|
||||
for (i = 0; i < length && things_printed < options->print_max; ++i)
|
||||
{
|
||||
/* Position of the character we are examining
|
||||
to see whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
if (!encoding || !*encoding)
|
||||
encoding = type_encoding;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while (rep1 < length && string[rep1] == string[i])
|
||||
{
|
||||
++rep1;
|
||||
++reps;
|
||||
}
|
||||
|
||||
if (reps > options->repeat_count_threshold)
|
||||
{
|
||||
if (in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
fputs_filtered ("\\', ", stream);
|
||||
else
|
||||
fputs_filtered ("', ", stream);
|
||||
in_quotes = 0;
|
||||
}
|
||||
f_printchar (string[i], type, stream);
|
||||
fprintf_filtered (stream, " <repeats %u times>", reps);
|
||||
i = rep1 - 1;
|
||||
things_printed += options->repeat_count_threshold;
|
||||
need_comma = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
fputs_filtered ("\\'", stream);
|
||||
else
|
||||
fputs_filtered ("'", stream);
|
||||
in_quotes = 1;
|
||||
}
|
||||
LA_EMIT_CHAR (string[i], type, stream, '"');
|
||||
++things_printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_quotes)
|
||||
{
|
||||
if (options->inspect_it)
|
||||
fputs_filtered ("\\'", stream);
|
||||
else
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
if (force_ellipses || i < length)
|
||||
fputs_filtered ("...", stream);
|
||||
generic_printstr (stream, type, string, length, encoding,
|
||||
force_ellipses, '\'', 0, options);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -321,10 +321,6 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show,
|
|||
break;
|
||||
|
||||
case TYPE_CODE_CHAR:
|
||||
/* Override name "char" and make it "character". */
|
||||
fprintfi_filtered (level, stream, "character");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
/* There may be some character types that attempt to come
|
||||
through as TYPE_CODE_INT since dbxstclass.h is so
|
||||
|
|
|
@ -271,10 +271,23 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
|
|||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
fprintf_filtered (stream, "(");
|
||||
f77_print_array (type, valaddr, embedded_offset,
|
||||
address, stream, recurse, original_value, options);
|
||||
fprintf_filtered (stream, ")");
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_CHAR)
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
f77_print_array (type, valaddr, embedded_offset,
|
||||
address, stream, recurse, original_value, options);
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
struct type *ch_type = TYPE_TARGET_TYPE (type);
|
||||
|
||||
f77_get_dynamic_length_of_aggregate (type);
|
||||
LA_PRINT_STRING (stream, ch_type,
|
||||
valaddr + embedded_offset,
|
||||
TYPE_LENGTH (type) / TYPE_LENGTH (ch_type),
|
||||
NULL, 0, options);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
|
@ -363,6 +376,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
|
|||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
case TYPE_CODE_CHAR:
|
||||
if (options->format || options->output_format)
|
||||
{
|
||||
struct value_print_options opts = *options;
|
||||
|
@ -379,7 +393,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
|
|||
Since we don't know whether the value is really intended to
|
||||
be used as an integer or a character, print the character
|
||||
equivalent as well. */
|
||||
if (TYPE_LENGTH (type) == 1)
|
||||
if (TYPE_LENGTH (type) == 1 || TYPE_CODE (type) == TYPE_CODE_CHAR)
|
||||
{
|
||||
LONGEST c;
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2011-06-29 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* gdb.fortran/charset.exp: New file.
|
||||
* gdb.fortran/charset.f90: New file.
|
||||
|
||||
2011-06-29 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
PR testsuite/12040:
|
||||
|
|
45
gdb/testsuite/gdb.fortran/charset.exp
Normal file
45
gdb/testsuite/gdb.fortran/charset.exp
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Copyright 2011 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This file is part of the gdb testsuite. It contains tests for evaluating
|
||||
# Fortran subarray expression.
|
||||
|
||||
if { [skip_fortran_tests] } { return -1 }
|
||||
|
||||
set testfile "charset"
|
||||
set srcfile ${testfile}.f90
|
||||
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug additional_flags=-fbackslash f90}] } {
|
||||
return -1
|
||||
}
|
||||
|
||||
if ![runto MAIN__] {
|
||||
perror "Couldn't run to MAIN__"
|
||||
continue
|
||||
}
|
||||
|
||||
gdb_breakpoint [gdb_get_line_number "break-here"]
|
||||
gdb_continue_to_breakpoint "break-here"
|
||||
|
||||
gdb_test "print x" \
|
||||
" = 'j'" \
|
||||
"print fortran narrow character"
|
||||
|
||||
gdb_test "print c" \
|
||||
" = 4_'k'" \
|
||||
"print fortran wide character"
|
||||
|
||||
gdb_test "print str" \
|
||||
" = 4_'lmnop'" \
|
||||
"print fortran wide string"
|
10
gdb/testsuite/gdb.fortran/charset.f90
Normal file
10
gdb/testsuite/gdb.fortran/charset.f90
Normal file
|
@ -0,0 +1,10 @@
|
|||
character(kind=1) :: x
|
||||
character(kind=4) :: c
|
||||
character(kind=4,len=5) :: str
|
||||
x = 'j'
|
||||
c = 4_'k'
|
||||
str = 4_'lmnop'
|
||||
! break-here
|
||||
print *, c
|
||||
print *, str
|
||||
end
|
447
gdb/valprint.c
447
gdb/valprint.c
|
@ -36,6 +36,9 @@
|
|||
#include "dfp.h"
|
||||
#include "python/python.h"
|
||||
#include "ada-lang.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "charset.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -1466,6 +1469,450 @@ read_string (CORE_ADDR addr, int len, int width, unsigned int fetchlimit,
|
|||
return errcode;
|
||||
}
|
||||
|
||||
/* Return true if print_wchar can display W without resorting to a
|
||||
numeric escape, false otherwise. */
|
||||
|
||||
static int
|
||||
wchar_printable (gdb_wchar_t w)
|
||||
{
|
||||
return (gdb_iswprint (w)
|
||||
|| w == LCST ('\a') || w == LCST ('\b')
|
||||
|| w == LCST ('\f') || w == LCST ('\n')
|
||||
|| w == LCST ('\r') || w == LCST ('\t')
|
||||
|| w == LCST ('\v'));
|
||||
}
|
||||
|
||||
/* A helper function that converts the contents of STRING to wide
|
||||
characters and then appends them to OUTPUT. */
|
||||
|
||||
static void
|
||||
append_string_as_wide (const char *string,
|
||||
struct obstack *output)
|
||||
{
|
||||
for (; *string; ++string)
|
||||
{
|
||||
gdb_wchar_t w = gdb_btowc (*string);
|
||||
obstack_grow (output, &w, sizeof (gdb_wchar_t));
|
||||
}
|
||||
}
|
||||
|
||||
/* Print a wide character W to OUTPUT. ORIG is a pointer to the
|
||||
original (target) bytes representing the character, ORIG_LEN is the
|
||||
number of valid bytes. WIDTH is the number of bytes in a base
|
||||
characters of the type. OUTPUT is an obstack to which wide
|
||||
characters are emitted. QUOTER is a (narrow) character indicating
|
||||
the style of quotes surrounding the character to be printed.
|
||||
NEED_ESCAPE is an in/out flag which is used to track numeric
|
||||
escapes across calls. */
|
||||
|
||||
static void
|
||||
print_wchar (gdb_wint_t w, const gdb_byte *orig,
|
||||
int orig_len, int width,
|
||||
enum bfd_endian byte_order,
|
||||
struct obstack *output,
|
||||
int quoter, int *need_escapep)
|
||||
{
|
||||
int need_escape = *need_escapep;
|
||||
|
||||
*need_escapep = 0;
|
||||
if (gdb_iswprint (w) && (!need_escape || (!gdb_iswdigit (w)
|
||||
&& w != LCST ('8')
|
||||
&& w != LCST ('9'))))
|
||||
{
|
||||
gdb_wchar_t wchar = w;
|
||||
|
||||
if (w == gdb_btowc (quoter) || w == LCST ('\\'))
|
||||
obstack_grow_wstr (output, LCST ("\\"));
|
||||
obstack_grow (output, &wchar, sizeof (gdb_wchar_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (w)
|
||||
{
|
||||
case LCST ('\a'):
|
||||
obstack_grow_wstr (output, LCST ("\\a"));
|
||||
break;
|
||||
case LCST ('\b'):
|
||||
obstack_grow_wstr (output, LCST ("\\b"));
|
||||
break;
|
||||
case LCST ('\f'):
|
||||
obstack_grow_wstr (output, LCST ("\\f"));
|
||||
break;
|
||||
case LCST ('\n'):
|
||||
obstack_grow_wstr (output, LCST ("\\n"));
|
||||
break;
|
||||
case LCST ('\r'):
|
||||
obstack_grow_wstr (output, LCST ("\\r"));
|
||||
break;
|
||||
case LCST ('\t'):
|
||||
obstack_grow_wstr (output, LCST ("\\t"));
|
||||
break;
|
||||
case LCST ('\v'):
|
||||
obstack_grow_wstr (output, LCST ("\\v"));
|
||||
break;
|
||||
default:
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i + width <= orig_len; i += width)
|
||||
{
|
||||
char octal[30];
|
||||
ULONGEST value;
|
||||
|
||||
value = extract_unsigned_integer (&orig[i], width,
|
||||
byte_order);
|
||||
/* If the value fits in 3 octal digits, print it that
|
||||
way. Otherwise, print it as a hex escape. */
|
||||
if (value <= 0777)
|
||||
sprintf (octal, "\\%.3o", (int) (value & 0777));
|
||||
else
|
||||
sprintf (octal, "\\x%lx", (long) value);
|
||||
append_string_as_wide (octal, output);
|
||||
}
|
||||
/* If we somehow have extra bytes, print them now. */
|
||||
while (i < orig_len)
|
||||
{
|
||||
char octal[5];
|
||||
|
||||
sprintf (octal, "\\%.3o", orig[i] & 0xff);
|
||||
append_string_as_wide (octal, output);
|
||||
++i;
|
||||
}
|
||||
|
||||
*need_escapep = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a
|
||||
literal string whose delimiter is QUOTER. ENCODING names the
|
||||
encoding of C. */
|
||||
|
||||
void
|
||||
generic_emit_char (int c, struct type *type, struct ui_file *stream,
|
||||
int quoter, const char *encoding)
|
||||
{
|
||||
enum bfd_endian byte_order
|
||||
= gdbarch_byte_order (get_type_arch (type));
|
||||
struct obstack wchar_buf, output;
|
||||
struct cleanup *cleanups;
|
||||
gdb_byte *buf;
|
||||
struct wchar_iterator *iter;
|
||||
int need_escape = 0;
|
||||
|
||||
buf = alloca (TYPE_LENGTH (type));
|
||||
pack_long (buf, type, c);
|
||||
|
||||
iter = make_wchar_iterator (buf, TYPE_LENGTH (type),
|
||||
encoding, TYPE_LENGTH (type));
|
||||
cleanups = make_cleanup_wchar_iterator (iter);
|
||||
|
||||
/* This holds the printable form of the wchar_t data. */
|
||||
obstack_init (&wchar_buf);
|
||||
make_cleanup_obstack_free (&wchar_buf);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int num_chars;
|
||||
gdb_wchar_t *chars;
|
||||
const gdb_byte *buf;
|
||||
size_t buflen;
|
||||
int print_escape = 1;
|
||||
enum wchar_iterate_result result;
|
||||
|
||||
num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen);
|
||||
if (num_chars < 0)
|
||||
break;
|
||||
if (num_chars > 0)
|
||||
{
|
||||
/* If all characters are printable, print them. Otherwise,
|
||||
we're going to have to print an escape sequence. We
|
||||
check all characters because we want to print the target
|
||||
bytes in the escape sequence, and we don't know character
|
||||
boundaries there. */
|
||||
int i;
|
||||
|
||||
print_escape = 0;
|
||||
for (i = 0; i < num_chars; ++i)
|
||||
if (!wchar_printable (chars[i]))
|
||||
{
|
||||
print_escape = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!print_escape)
|
||||
{
|
||||
for (i = 0; i < num_chars; ++i)
|
||||
print_wchar (chars[i], buf, buflen,
|
||||
TYPE_LENGTH (type), byte_order,
|
||||
&wchar_buf, quoter, &need_escape);
|
||||
}
|
||||
}
|
||||
|
||||
/* This handles the NUM_CHARS == 0 case as well. */
|
||||
if (print_escape)
|
||||
print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type),
|
||||
byte_order, &wchar_buf, quoter, &need_escape);
|
||||
}
|
||||
|
||||
/* The output in the host encoding. */
|
||||
obstack_init (&output);
|
||||
make_cleanup_obstack_free (&output);
|
||||
|
||||
convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (),
|
||||
obstack_base (&wchar_buf),
|
||||
obstack_object_size (&wchar_buf),
|
||||
1, &output, translit_char);
|
||||
obstack_1grow (&output, '\0');
|
||||
|
||||
fputs_filtered (obstack_base (&output), stream);
|
||||
|
||||
do_cleanups (cleanups);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
printing stops early if the number hits print_max; repeat counts
|
||||
are printed as appropriate. Print ellipses at the end if we had to
|
||||
stop before printing LENGTH characters, or if FORCE_ELLIPSES.
|
||||
QUOTE_CHAR is the character to print at each end of the string. If
|
||||
C_STYLE_TERMINATOR is true, and the last character is 0, then it is
|
||||
omitted. */
|
||||
|
||||
void
|
||||
generic_printstr (struct ui_file *stream, struct type *type,
|
||||
const gdb_byte *string, unsigned int length,
|
||||
const char *encoding, int force_ellipses,
|
||||
int quote_char, int c_style_terminator,
|
||||
const struct value_print_options *options)
|
||||
{
|
||||
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);
|
||||
|
||||
if (length == -1)
|
||||
{
|
||||
unsigned long current_char = 1;
|
||||
|
||||
for (i = 0; current_char; ++i)
|
||||
{
|
||||
QUIT;
|
||||
current_char = extract_unsigned_integer (string + i * width,
|
||||
width, byte_order);
|
||||
}
|
||||
length = i;
|
||||
}
|
||||
|
||||
/* If the string was not truncated due to `set print elements', and
|
||||
the last byte of it is a null, we don't print that, in
|
||||
traditional C style. */
|
||||
if (c_style_terminator
|
||||
&& !force_ellipses
|
||||
&& length > 0
|
||||
&& (extract_unsigned_integer (string + (length - 1) * width,
|
||||
width, byte_order) == 0))
|
||||
length--;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("\"\"", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
if (force_ellipses || !finished)
|
||||
obstack_grow_wstr (&wchar_buf, LCST ("..."));
|
||||
|
||||
/* OUTPUT is where we collect `char's for printing. */
|
||||
obstack_init (&output);
|
||||
make_cleanup_obstack_free (&output);
|
||||
|
||||
convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (),
|
||||
obstack_base (&wchar_buf),
|
||||
obstack_object_size (&wchar_buf),
|
||||
1, &output, translit_char);
|
||||
obstack_1grow (&output, '\0');
|
||||
|
||||
fputs_filtered (obstack_base (&output), stream);
|
||||
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
|
||||
/* Print a string from the inferior, starting at ADDR and printing up to LEN
|
||||
characters, of WIDTH bytes a piece, to STREAM. If LEN is -1, printing
|
||||
stops at the first null byte, otherwise printing proceeds (including null
|
||||
|
|
|
@ -158,4 +158,13 @@ extern void val_print_unavailable (struct ui_file *stream);
|
|||
|
||||
extern void val_print_invalid_address (struct ui_file *stream);
|
||||
|
||||
extern void generic_emit_char (int c, struct type *type, struct ui_file *stream,
|
||||
int quoter, const char *encoding);
|
||||
|
||||
extern void generic_printstr (struct ui_file *stream, struct type *type,
|
||||
const gdb_byte *string, unsigned int length,
|
||||
const char *encoding, int force_ellipses,
|
||||
int quote_char, int c_style_terminator,
|
||||
const struct value_print_options *options);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue