#include "solist.h"
#include "solib.h"
#include "parser-defs.h"
+#include "charset.h"
#ifdef TUI
#include "tui/tui.h" /* For tui_active et.al. */
int count;
char format;
char size;
+
+ /* True if the value should be printed raw -- that is, bypassing
+ python-based formatters. */
+ unsigned char raw;
};
/* Last specified output format. */
-static char last_format = 'x';
+static char last_format = 0;
/* Last specified examination size. 'b', 'h', 'w' or `q'. */
val.format = '?';
val.size = '?';
val.count = 1;
+ val.raw = 0;
if (*p >= '0' && *p <= '9')
val.count = atoi (p);
{
if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
val.size = *p++;
+ else if (*p == 'r')
+ {
+ val.raw = 1;
+ p++;
+ }
else if (*p >= 'a' && *p <= 'z')
val.format = *p++;
else
int len = TYPE_LENGTH (type);
if (VALUE_LVAL (val) == lval_memory)
- next_address = VALUE_ADDRESS (val) + len;
+ next_address = value_address (val) + len;
if (size)
{
switch (options->format)
{
case 's':
- /* FIXME: Need to handle wchar_t's here... */
- next_address = VALUE_ADDRESS (val)
- + val_print_string (VALUE_ADDRESS (val), -1, 1, stream,
- options);
+ {
+ struct type *elttype = value_type (val);
+ next_address = (value_address (val)
+ + val_print_string (elttype,
+ value_address (val), -1,
+ stream, options));
+ }
return;
case 'i':
/* We often wrap here if there are long symbolic names. */
wrap_here (" ");
- next_address = (VALUE_ADDRESS (val)
- + gdb_print_insn (VALUE_ADDRESS (val), stream,
+ next_address = (value_address (val)
+ + gdb_print_insn (value_address (val), stream,
&branch_delay_insns));
return;
}
print_hex_chars (stream, valaddr, len, byte_order);
return;
case 'c':
- print_char_chars (stream, valaddr, len, byte_order);
+ print_char_chars (stream, type, valaddr, len, byte_order);
return;
default:
break;
fmt.count = 1;
fmt.format = 0;
fmt.size = 0;
+ fmt.raw = 0;
}
if (exp && *exp)
get_formatted_print_options (&opts, format);
opts.inspect_it = inspect;
+ opts.raw = fmt.raw;
print_formatted (val, fmt.size, &opts, gdb_stdout);
printf_filtered ("\n");
struct value_print_options opts;
fmt.size = 0;
+ fmt.raw = 0;
if (exp && *exp == '/')
{
annotate_value_begin (value_type (val));
get_formatted_print_options (&opts, format);
+ opts.raw = fmt.raw;
print_formatted (val, fmt.size, &opts, gdb_stdout);
annotate_value_end ();
/* Don't print the offset if it is zero.
We assume there's no need to handle i18n of "sym + offset". */
if (offset)
- xasprintf (&loc_string, "%s + %u", msym_name, offset);
+ loc_string = xstrprintf ("%s + %u", msym_name, offset);
else
- xasprintf (&loc_string, "%s", msym_name);
+ loc_string = xstrprintf ("%s", msym_name);
/* Use a cleanup to free loc_string in case the user quits
a pagination request inside printf_filtered. */
struct cleanup *old_chain;
struct value *val;
- fmt.format = last_format;
+ fmt.format = last_format ? last_format : 'x';
fmt.size = last_size;
fmt.count = 1;
+ fmt.raw = 0;
if (exp && *exp == '/')
{
if (/* last_format == 'i' && */
TYPE_CODE (value_type (val)) == TYPE_CODE_FUNC
&& VALUE_LVAL (val) == lval_memory)
- next_address = VALUE_ADDRESS (val);
+ next_address = value_address (val);
else
next_address = value_as_address (val);
do_cleanups (old_chain);
then don't fetch it now; instead mark it by voiding the $__
variable. */
if (value_lazy (last_examine_value))
- set_internalvar (lookup_internalvar ("__"),
- allocate_value (builtin_type_void));
+ clear_internalvar (lookup_internalvar ("__"));
else
set_internalvar (lookup_internalvar ("__"), last_examine_value);
}
fmt.format = 0;
fmt.size = 0;
fmt.count = 0;
+ fmt.raw = 0;
}
innermost_block = NULL;
annotate_display_expression ();
get_formatted_print_options (&opts, d->format.format);
+ opts.raw = d->format.raw;
print_formatted (evaluate_expression (d->exp),
d->format.size, &opts, gdb_stdout);
printf_filtered ("\n");
display_uses_solib_p (const struct display *d,
const struct so_list *solib)
{
- int i;
+ int endpos;
struct expression *const exp = d->exp;
+ const union exp_element *const elts = exp->elts;
if (d->block != NULL
&& solib_contains_address_p (solib, d->block->startaddr))
return 1;
- for (i = 0; i < exp->nelts; )
+ for (endpos = exp->nelts; endpos > 0; )
{
- int args, oplen = 0;
- const union exp_element *const elts = exp->elts;
+ int i, args, oplen = 0;
+ exp->language_defn->la_exp_desc->operator_length (exp, endpos,
+ &oplen, &args);
+ gdb_assert (oplen > 0);
+
+ i = endpos - oplen;
if (elts[i].opcode == OP_VAR_VALUE)
{
const struct block *const block = elts[i + 1].block;
if (section && section->objfile == solib->objfile)
return 1;
}
- exp->language_defn->la_exp_desc->operator_length (exp, i + 1,
- &oplen, &args);
- gdb_assert (oplen > 0);
- i += oplen;
+ endpos -= oplen;
}
+
return 0;
}
enum argclass
{
- int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
+ int_arg, long_arg, long_long_arg, ptr_arg,
+ string_arg, wide_string_arg, wide_char_arg,
double_arg, long_double_arg, decfloat_arg
};
enum argclass *argclass;
break;
case 'c':
- this_argclass = int_arg;
- if (lcount || seen_h || seen_big_l)
+ this_argclass = lcount == 0 ? int_arg : wide_char_arg;
+ if (lcount > 1 || seen_h || seen_big_l)
bad = 1;
if (seen_prec || seen_zero || seen_space || seen_plus)
bad = 1;
break;
case 's':
- this_argclass = string_arg;
- if (lcount || seen_h || seen_big_l)
+ this_argclass = lcount == 0 ? string_arg : wide_string_arg;
+ if (lcount > 1 || seen_h || seen_big_l)
bad = 1;
if (seen_zero || seen_space || seen_plus)
bad = 1;
last_arg[length_before_ll + lcount];
current_substring += length_before_ll + 4;
}
+ else if (this_argclass == wide_string_arg
+ || this_argclass == wide_char_arg)
+ {
+ /* Convert %ls or %lc to %s. */
+ int length_before_ls = f - last_arg - 2;
+ strncpy (current_substring, last_arg, length_before_ls);
+ strcpy (current_substring + length_before_ls, "s");
+ current_substring += length_before_ls + 2;
+ }
else
{
strncpy (current_substring, last_arg, f - last_arg);
printf_filtered (current_substring, (char *) str);
}
break;
+ case wide_string_arg:
+ {
+ gdb_byte *str;
+ CORE_ADDR tem;
+ int j;
+ struct type *wctype = lookup_typename ("wchar_t", NULL, 0);
+ int wcwidth = TYPE_LENGTH (wctype);
+ gdb_byte *buf = alloca (wcwidth);
+ struct obstack output;
+ struct cleanup *inner_cleanup;
+
+ tem = value_as_address (val_args[i]);
+
+ /* This is a %s argument. Find the length of the string. */
+ for (j = 0;; j += wcwidth)
+ {
+ QUIT;
+ read_memory (tem + j, buf, wcwidth);
+ if (extract_unsigned_integer (buf, wcwidth) == 0)
+ break;
+ }
+
+ /* Copy the string contents into a string inside GDB. */
+ str = (gdb_byte *) alloca (j + wcwidth);
+ if (j != 0)
+ read_memory (tem, str, j);
+ memset (&str[j], 0, wcwidth);
+
+ obstack_init (&output);
+ inner_cleanup = make_cleanup_obstack_free (&output);
+
+ convert_between_encodings (target_wide_charset (),
+ host_charset (),
+ str, j, wcwidth,
+ &output, translit_char);
+ obstack_grow_str0 (&output, "");
+
+ printf_filtered (current_substring, obstack_base (&output));
+ do_cleanups (inner_cleanup);
+ }
+ break;
+ case wide_char_arg:
+ {
+ struct type *wctype = lookup_typename ("wchar_t", NULL, 0);
+ struct type *valtype;
+ struct obstack output;
+ struct cleanup *inner_cleanup;
+ const gdb_byte *bytes;
+
+ valtype = value_type (val_args[i]);
+ if (TYPE_LENGTH (valtype) != TYPE_LENGTH (wctype)
+ || TYPE_CODE (valtype) != TYPE_CODE_INT)
+ error (_("expected wchar_t argument for %%lc"));
+
+ bytes = value_contents (val_args[i]);
+
+ obstack_init (&output);
+ inner_cleanup = make_cleanup_obstack_free (&output);
+
+ convert_between_encodings (target_wide_charset (),
+ host_charset (),
+ bytes, TYPE_LENGTH (valtype),
+ TYPE_LENGTH (valtype),
+ &output, translit_char);
+ obstack_grow_str0 (&output, "");
+
+ printf_filtered (current_substring, obstack_base (&output));
+ do_cleanups (inner_cleanup);
+ }
+ break;
case double_arg:
{
struct type *type = value_type (val_args[i]);