/* Print values for GDB, the GNU debugger.
- Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005 Free Software
- Foundation, Inc.
+ Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
+ 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GDB.
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., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "gdb_string.h"
#include "valprint.h"
#include "floatformat.h"
#include "doublest.h"
+#include "exceptions.h"
#include <errno.h>
/* Prototypes for local functions */
-static int partial_memory_read (CORE_ADDR memaddr, char *myaddr,
+static int partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr,
int len, int *errnoptr);
static void show_print (char *, int);
}
int output_format = 0;
+/* By default we print arrays without printing the index of each element in
+ the array. This behavior can be changed by setting PRINT_ARRAY_INDEXES. */
+
+static int print_array_indexes = 0;
+static void
+show_print_array_indexes (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("Printing of array indexes is %s.\n"), value);
+}
+
/* Print repeat counts if there are more than this many repetitions of an
element in an array. Referenced by the low level language dependent
print routines. */
CORE_ADDR address, struct ui_file *stream, int format,
int deref_ref, int recurse, enum val_prettyprint pretty)
{
+ volatile struct gdb_exception except;
+ volatile enum val_prettyprint real_pretty = pretty;
+ int ret = 0;
+
struct type *real_type = check_typedef (type);
if (pretty == Val_pretty_default)
- {
- pretty = prettyprint_structs ? Val_prettyprint : Val_no_prettyprint;
- }
+ real_pretty = prettyprint_structs ? Val_prettyprint : Val_no_prettyprint;
QUIT;
return (0);
}
- return (LA_VAL_PRINT (type, valaddr, embedded_offset, address,
- stream, format, deref_ref, recurse, pretty));
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ ret = LA_VAL_PRINT (type, valaddr, embedded_offset, address,
+ stream, format, deref_ref, recurse, real_pretty);
+ }
+ if (except.reason < 0)
+ fprintf_filtered (stream, _("<error reading variable>"));
+
+ return ret;
}
/* Check whether the value VAL is printable. Return 1 if it is;
}
}
+void
+val_print_type_code_flags (struct type *type, const gdb_byte *valaddr,
+ struct ui_file *stream)
+{
+ ULONGEST val = unpack_long (type, valaddr);
+ int bitpos, nfields = TYPE_NFIELDS (type);
+
+ fputs_filtered ("[ ", stream);
+ for (bitpos = 0; bitpos < nfields; bitpos++)
+ {
+ if (TYPE_FIELD_BITPOS (type, bitpos) != -1
+ && (val & ((ULONGEST)1 << bitpos)))
+ {
+ if (TYPE_FIELD_NAME (type, bitpos))
+ fprintf_filtered (stream, "%s ", TYPE_FIELD_NAME (type, bitpos));
+ else
+ fprintf_filtered (stream, "#%d ", bitpos);
+ }
+ }
+ fputs_filtered ("]", stream);
+}
+
/* Print a number according to FORMAT which is one of d,u,x,o,b,h,w,g.
The raison d'etre of this function is to consolidate printing of
LONG_LONG's into this one function. The format chars b,h,w,g are
int inv;
const struct floatformat *fmt = NULL;
unsigned len = TYPE_LENGTH (type);
+ enum float_kind kind;
/* If it is a floating-point, check for obvious problems. */
if (TYPE_CODE (type) == TYPE_CODE_FLT)
fmt = floatformat_from_type (type);
- if (fmt != NULL && floatformat_is_nan (fmt, valaddr))
+ if (fmt != NULL)
{
- if (floatformat_is_negative (fmt, valaddr))
- fprintf_filtered (stream, "-");
- fprintf_filtered (stream, "nan(");
- fputs_filtered ("0x", stream);
- fputs_filtered (floatformat_mantissa (fmt, valaddr), stream);
- fprintf_filtered (stream, ")");
- return;
+ kind = floatformat_classify (fmt, valaddr);
+ if (kind == float_nan)
+ {
+ if (floatformat_is_negative (fmt, valaddr))
+ fprintf_filtered (stream, "-");
+ fprintf_filtered (stream, "nan(");
+ fputs_filtered ("0x", stream);
+ fputs_filtered (floatformat_mantissa (fmt, valaddr), stream);
+ fprintf_filtered (stream, ")");
+ return;
+ }
+ else if (kind == float_infinite)
+ {
+ if (floatformat_is_negative (fmt, valaddr))
+ fputs_filtered ("-", stream);
+ fputs_filtered ("inf", stream);
+ return;
+ }
}
/* NOTE: cagney/2002-01-15: The TYPE passed into print_floating()
assumptions about the host and target floating point format. */
/* NOTE: cagney/2002-02-03: Since the TYPE of what was passed in may
- not necessarially be a TYPE_CODE_FLT, the below ignores that and
+ not necessarily be a TYPE_CODE_FLT, the below ignores that and
instead uses the type's length to determine the precision of the
floating-point value being printed. */
/* FIXME: We should be not printing leading zeroes in most cases. */
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
{
for (p = valaddr;
p < valaddr + len;
carry = 0;
fputs_filtered ("0", stream);
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
{
for (p = valaddr;
p < valaddr + len;
#define CARRY_LEFT( x ) ((x) % TEN)
#define SHIFT( x ) ((x) << 4)
#define START_P \
- ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) ? valaddr : valaddr + len - 1)
+ ((gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) ? valaddr : valaddr + len - 1)
#define NOT_END_P \
- ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) ? (p < valaddr + len) : (p >= valaddr))
+ ((gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) ? (p < valaddr + len) : (p >= valaddr))
#define NEXT_P \
- ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG) ? p++ : p-- )
+ ((gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) ? p++ : p-- )
#define LOW_NIBBLE( x ) ( (x) & 0x00F)
#define HIGH_NIBBLE( x ) (((x) & 0x0F0) >> 4)
/* FIXME: We should be not printing leading zeroes in most cases. */
fputs_filtered ("0x", stream);
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
{
for (p = valaddr;
p < valaddr + len;
{
const gdb_byte *p;
- if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
{
p = valaddr;
while (p < valaddr + len - 1 && *p == 0)
}
}
+/* Return non-zero if the debugger should print the index of each element
+ when printing array values. */
+
+int
+print_array_indexes_p (void)
+{
+ return print_array_indexes;
+}
+
+/* Assuming TYPE is a simple, non-empty array type, compute its lower bound.
+ Save it into LOW_BOUND if not NULL.
+
+ Return 1 if the operation was successful. Return zero otherwise,
+ in which case the value of LOW_BOUND is unmodified.
+
+ Computing the array lower bound is pretty easy, but this function
+ does some additional verifications before returning the low bound.
+ If something incorrect is detected, it is better to return a status
+ rather than throwing an error, making it easier for the caller to
+ implement an error-recovery plan. For instance, it may decide to
+ warn the user that the bound was not found and then use a default
+ value instead. */
+
+int
+get_array_low_bound (struct type *type, long *low_bound)
+{
+ struct type *index = TYPE_INDEX_TYPE (type);
+ long low = 0;
+
+ if (index == NULL)
+ return 0;
+
+ if (TYPE_CODE (index) != TYPE_CODE_RANGE
+ && TYPE_CODE (index) != TYPE_CODE_ENUM)
+ return 0;
+
+ low = TYPE_LOW_BOUND (index);
+ if (low > TYPE_HIGH_BOUND (index))
+ return 0;
+
+ if (low_bound)
+ *low_bound = low;
+
+ return 1;
+}
+
+/* Print on STREAM using the given FORMAT the index for the element
+ at INDEX of an array whose index type is INDEX_TYPE. */
+
+void
+maybe_print_array_index (struct type *index_type, LONGEST index,
+ struct ui_file *stream, int format,
+ enum val_prettyprint pretty)
+{
+ struct value *index_value;
+
+ if (!print_array_indexes)
+ return;
+
+ index_value = value_from_longest (index_type, index);
+
+ LA_PRINT_ARRAY_INDEX (index_value, stream, format, pretty);
+}
+
/* Called by various <lang>_val_print routines to print elements of an
array in the form "<elem1>, <elem2>, <elem3>, ...".
{
unsigned int things_printed = 0;
unsigned len;
- struct type *elttype;
+ struct type *elttype, *index_type;
unsigned eltlen;
/* Position of the array element we are examining to see
whether it is repeated. */
unsigned int rep1;
/* Number of repetitions we have detected so far. */
unsigned int reps;
+ long low_bound_index = 0;
elttype = TYPE_TARGET_TYPE (type);
eltlen = TYPE_LENGTH (check_typedef (elttype));
len = TYPE_LENGTH (type) / eltlen;
+ index_type = TYPE_INDEX_TYPE (type);
+
+ /* Get the array low bound. This only makes sense if the array
+ has one or more element in it. */
+ if (len > 0 && !get_array_low_bound (type, &low_bound_index))
+ {
+ warning ("unable to get low bound of array, using zero as default");
+ low_bound_index = 0;
+ }
annotate_array_section_begin (i, elttype);
}
}
wrap_here (n_spaces (2 + 2 * recurse));
+ maybe_print_array_index (index_type, i + low_bound_index,
+ stream, format, pretty);
rep1 = i + 1;
reps = 1;
function be eliminated. */
static int
-partial_memory_read (CORE_ADDR memaddr, char *myaddr, int len, int *errnoptr)
+partial_memory_read (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int *errnoptr)
{
int nread; /* Number of bytes actually read. */
int errcode; /* Error from last read. */
unsigned int fetchlimit; /* Maximum number of chars to print. */
unsigned int nfetch; /* Chars to fetch / chars fetched. */
unsigned int chunksize; /* Size of each fetch, in chars. */
- char *buffer = NULL; /* Dynamically growable fetch buffer. */
- char *bufptr; /* Pointer to next available byte in buffer. */
- char *limit; /* First location past end of fetch buffer. */
+ gdb_byte *buffer = NULL; /* Dynamically growable fetch buffer. */
+ gdb_byte *bufptr; /* Pointer to next available byte in buffer. */
+ gdb_byte *limit; /* First location past end of fetch buffer. */
struct cleanup *old_chain = NULL; /* Top of the old cleanup chain. */
int found_nul; /* Non-zero if we found the nul char */
if (len > 0)
{
- buffer = (char *) xmalloc (len * width);
+ buffer = (gdb_byte *) xmalloc (len * width);
bufptr = buffer;
old_chain = make_cleanup (xfree, buffer);
nfetch = min (chunksize, fetchlimit - bufsize);
if (buffer == NULL)
- buffer = (char *) xmalloc (nfetch * width);
+ buffer = (gdb_byte *) xmalloc (nfetch * width);
else
{
discard_cleanups (old_chain);
- buffer = (char *) xrealloc (buffer, (nfetch + bufsize) * width);
+ buffer = (gdb_byte *) xrealloc (buffer, (nfetch + bufsize) * width);
}
old_chain = make_cleanup (xfree, buffer);
if (len == -1 && !found_nul)
{
- char *peekbuf;
+ gdb_byte *peekbuf;
/* We didn't find a null terminator we were looking for. Attempt
to peek at the next character. If not successful, or it is not
a null byte, then force ellipsis to be printed. */
- peekbuf = (char *) alloca (width);
+ peekbuf = (gdb_byte *) alloca (width);
if (target_read_memory (addr, peekbuf, width) == 0
&& extract_unsigned_integer (peekbuf, width) != 0)
Use 'show input-radix' or 'show output-radix' to independently show each."),
&showlist);
+ add_setshow_boolean_cmd ("array-indexes", class_support,
+ &print_array_indexes, _("\
+Set printing of array indexes."), _("\
+Show printing of array indexes"), NULL, NULL, show_print_array_indexes,
+ &setprintlist, &showprintlist);
+
/* Give people the defaults which they are used to. */
prettyprint_structs = 0;
prettyprint_arrays = 0;