/* Print values for GNU debugger GDB.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
This file is part of GDB.
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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "gdb_string.h"
#include "gdb_assert.h"
#include "block.h"
#include "disasm.h"
+#include "dfp.h"
#ifdef TUI
#include "tui/tui.h" /* For tui_active et.al. */
static CORE_ADDR next_address;
+/* Number of delay instructions following current disassembled insn. */
+
+static int branch_delay_insns;
+
/* Last address examined. */
static CORE_ADDR last_examine_address;
Do not end with a newline.
0 means print VAL according to its own type.
SIZE is the letter for the size of datum being printed.
- This is used to pad hex numbers so they line up. */
+ This is used to pad hex numbers so they line up. SIZE is 0
+ for print / output and set for examine. */
static void
print_formatted (struct value *val, int format, int size,
if (VALUE_LVAL (val) == lval_memory)
next_address = VALUE_ADDRESS (val) + len;
- switch (format)
+ if (size)
{
- case 's':
- /* FIXME: Need to handle wchar_t's here... */
- next_address = VALUE_ADDRESS (val)
- + val_print_string (VALUE_ADDRESS (val), -1, 1, stream);
- break;
-
- case 'i':
- /* The old comment says
- "Force output out, print_insn not using _filtered".
- I'm not completely sure what that means, I suspect most print_insn
- now do use _filtered, so I guess it's obsolete.
- --Yes, it does filter now, and so this is obsolete. -JB */
-
- /* We often wrap here if there are long symbolic names. */
- wrap_here (" ");
- next_address = VALUE_ADDRESS (val)
- + gdb_print_insn (VALUE_ADDRESS (val), stream);
- break;
+ switch (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);
+ return;
- default:
- if (format == 0
- || TYPE_CODE (type) == TYPE_CODE_ARRAY
- || TYPE_CODE (type) == TYPE_CODE_STRING
- || TYPE_CODE (type) == TYPE_CODE_STRUCT
- || TYPE_CODE (type) == TYPE_CODE_UNION
- || TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
- /* If format is 0, use the 'natural' format for that type of
- value. If the type is non-scalar, we have to use language
- rules to print it as a series of scalars. */
- value_print (val, stream, format, Val_pretty_default);
- else
- /* User specified format, so don't look to the the type to
- tell us what to do. */
- print_scalar_formatted (value_contents (val), type,
- format, size, stream);
+ 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,
+ &branch_delay_insns));
+ return;
+ }
}
+
+ if (format == 0 || format == 's'
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (type) == TYPE_CODE_STRING
+ || TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+ /* If format is 0, use the 'natural' format for that type of
+ value. If the type is non-scalar, we have to use language
+ rules to print it as a series of scalars. */
+ value_print (val, stream, format, Val_pretty_default);
+ else
+ /* User specified format, so don't look to the the type to
+ tell us what to do. */
+ print_scalar_formatted (value_contents (val), type,
+ format, size, stream);
}
/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
LONGEST val_long = 0;
unsigned int len = TYPE_LENGTH (type);
+ /* If we get here with a string format, try again without it. Go
+ all the way back to the language printers, which may call us
+ again. */
+ if (format == 's')
+ {
+ val_print (type, valaddr, 0, 0, stream, 0, 0, 0, Val_pretty_default);
+ return;
+ }
+
if (len > sizeof(LONGEST) &&
(TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_ENUM))
/* If the value is a pointer, and pointers and addresses are not the
same, then at this point, the value's length (in target bytes) is
- TARGET_ADDR_BIT/TARGET_CHAR_BIT, not TYPE_LENGTH (type). */
+ gdbarch_addr_bit/TARGET_CHAR_BIT, not TYPE_LENGTH (type). */
if (TYPE_CODE (type) == TYPE_CODE_PTR)
- len = TARGET_ADDR_BIT / TARGET_CHAR_BIT;
+ len = gdbarch_addr_bit (current_gdbarch) / TARGET_CHAR_BIT;
/* If we are printing it as unsigned, truncate it in case it is actually
a negative signed value (e.g. "print/u (short)-1" should print 65535
break;
case 'c':
- value_print (value_from_longest (builtin_type_true_char, val_long),
- stream, 0, Val_pretty_default);
+ if (TYPE_UNSIGNED (type))
+ {
+ struct type *utype;
+
+ utype = builtin_type (current_gdbarch)->builtin_true_unsigned_char;
+ value_print (value_from_longest (utype, val_long),
+ stream, 0, Val_pretty_default);
+ }
+ else
+ value_print (value_from_longest (builtin_type_true_char, val_long),
+ stream, 0, Val_pretty_default);
break;
case 'f':
{
struct minimal_symbol *msymbol;
struct symbol *symbol;
- struct symtab *symtab = 0;
CORE_ADDR name_location = 0;
asection *section = 0;
char *name_temp = "";
/* The msymbol is closer to the address than the symbol;
use the msymbol instead. */
symbol = 0;
- symtab = 0;
name_location = SYMBOL_VALUE_ADDRESS (msymbol);
if (do_demangle || asm_demangle)
name_temp = SYMBOL_PRINT_NAME (msymbol);
*filename = xstrdup (sal.symtab->filename);
*line = sal.line;
}
- else if (symtab && symbol && symbol->line)
- {
- *filename = xstrdup (symtab->filename);
- *line = symbol->line;
- }
- else if (symtab)
- {
- *filename = xstrdup (symtab->filename);
- *line = -1;
- }
}
return 0;
}
fputs_filtered (paddress (addr), stream);
else
{
- int addr_bit = TARGET_ADDR_BIT;
+ int addr_bit = gdbarch_addr_bit (current_gdbarch);
if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
addr &= ((CORE_ADDR) 1 << addr_bit) - 1;
release_value (last_examine_value);
print_formatted (last_examine_value, format, size, gdb_stdout);
+
+ /* Display any branch delay slots following the final insn. */
+ if (format == 'i' && count == 1)
+ count += branch_delay_insns;
}
printf_filtered ("\n");
gdb_flush (gdb_stdout);
if (fmt.count != 1)
error (_("Item count other than 1 is meaningless in \"%s\" command."),
cmdname);
- if (fmt.format == 'i' || fmt.format == 's')
+ if (fmt.format == 'i')
error (_("Format letter \"%c\" is meaningless in \"%s\" command."),
fmt.format, cmdname);
}
print_expression (d->exp, gdb_stdout);
annotate_display_expression_end ();
- if (d->format.count != 1)
+ if (d->format.count != 1 || d->format.format == 'i')
printf_filtered ("\n");
else
printf_filtered (" ");
enum argclass
{
int_arg, long_arg, long_long_arg, ptr_arg, string_arg,
- double_arg, long_double_arg
+ double_arg, long_double_arg, decfloat_arg
};
enum argclass *argclass;
enum argclass this_argclass;
bad = 1;
break;
+ /* DFP Decimal32 types. */
+ case 'H':
+ this_argclass = decfloat_arg;
+
+#ifndef PRINTF_HAS_DECFLOAT
+ if (lcount || seen_h || seen_big_l)
+ bad = 1;
+ if (seen_prec || seen_zero || seen_space || seen_plus)
+ bad = 1;
+#endif
+ break;
+
+ /* DFP Decimal64 and Decimal128 types. */
+ case 'D':
+ this_argclass = decfloat_arg;
+
+#ifndef PRINTF_HAS_DECFLOAT
+ if (lcount || seen_h || seen_big_l)
+ bad = 1;
+ if (seen_prec || seen_zero || seen_space || seen_plus)
+ bad = 1;
+#endif
+ /* Check for a Decimal128. */
+ if (*(f + 1) == 'D')
+ f++;
+
+ break;
+
case 'c':
this_argclass = int_arg;
if (lcount || seen_h || seen_big_l)
printf_filtered (current_substring, val);
break;
}
+
+ /* Handles decimal floating point values. */
+ case decfloat_arg:
+ {
+ char *eos;
+ char decstr[MAX_DECIMAL_STRING];
+ unsigned int dfp_len = TYPE_LENGTH (value_type (val_args[i]));
+ unsigned char *dfp_value_ptr = (unsigned char *) value_contents_all (val_args[i])
+ + value_offset (val_args[i]);
+
+#if defined (PRINTF_HAS_DECFLOAT)
+ printf_filtered (current_substring, dfp_value_ptr);
+#else
+ if (TYPE_CODE (value_type (val_args[i])) != TYPE_CODE_DECFLOAT)
+ error (_("Cannot convert parameter to decfloat."));
+
+ /* As a workaround until vasprintf has native support for DFP
+ we convert the DFP values to string and print them using
+ the %s format specifier. */
+ decimal_to_string (dfp_value_ptr, dfp_len, decstr);
+
+ /* Points to the end of the string so that we can go back
+ and check for DFP format specifiers. */
+ eos = current_substring + strlen (current_substring);
+
+ /* Replace %H, %D and %DD with %s's. */
+ while (*--eos != '%')
+ if (*eos == 'D' && *(eos - 1) == 'D')
+ {
+ *(eos - 1) = 's';
+
+ /* If we've found a %DD format specifier we need to go
+ through the whole string pulling back one character
+ since this format specifier has two chars. */
+ while (eos < last_arg)
+ {
+ *eos = *(eos + 1);
+ eos++;
+ }
+ }
+ else if (*eos == 'D' || *eos == 'H')
+ *eos = 's';
+
+ /* Print the DFP value. */
+ printf_filtered (current_substring, decstr);
+ break;
+#endif
+ }
+
+ case ptr_arg:
+ {
+ /* We avoid the host's %p because pointers are too
+ likely to be the wrong size. The only interesting
+ modifier for %p is a width; extract that, and then
+ handle %p as glibc would: %#x or a literal "(nil)". */
+
+ char *p, *fmt, *fmt_p;
+#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG)
+ long long val = value_as_long (val_args[i]);
+#else
+ long val = value_as_long (val_args[i]);
+#endif
+
+ fmt = alloca (strlen (current_substring) + 5);
+
+ /* Copy up to the leading %. */
+ p = current_substring;
+ fmt_p = fmt;
+ while (*p)
+ {
+ int is_percent = (*p == '%');
+ *fmt_p++ = *p++;
+ if (is_percent)
+ {
+ if (*p == '%')
+ *fmt_p++ = *p++;
+ else
+ break;
+ }
+ }
+
+ if (val != 0)
+ *fmt_p++ = '#';
+
+ /* Copy any width. */
+ while (*p >= '0' && *p < '9')
+ *fmt_p++ = *p++;
+
+ gdb_assert (*p == 'p' && *(p + 1) == '\0');
+ if (val != 0)
+ {
+#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG)
+ *fmt_p++ = 'l';
+#endif
+ *fmt_p++ = 'l';
+ *fmt_p++ = 'x';
+ *fmt_p++ = '\0';
+ printf_filtered (fmt, val);
+ }
+ else
+ {
+ *fmt_p++ = 's';
+ *fmt_p++ = '\0';
+ printf_filtered (fmt, "(nil)");
+ }
+
+ break;
+ }
default:
internal_error (__FILE__, __LINE__,
- _("failed internal consitency check"));
+ _("failed internal consistency check"));
}
/* Skip to the next substring. */
current_substring += strlen (current_substring) + 1;