0e9f083f4c
This removes gdb_string.h. This patch is purely mechanical. I created it by running the two commands: git rm common/gdb_string.h perl -pi -e's/"gdb_string.h"/<string.h>/;' *.[chyl] */*.[chyl] 2013-11-18 Tom Tromey <tromey@redhat.com> * common/gdb_string.h: Remove. * aarch64-tdep.c: Use string.h, not gdb_string.h. * ada-exp.y: Use string.h, not gdb_string.h. * ada-lang.c: Use string.h, not gdb_string.h. * ada-lex.l: Use string.h, not gdb_string.h. * ada-typeprint.c: Use string.h, not gdb_string.h. * ada-valprint.c: Use string.h, not gdb_string.h. * aix-thread.c: Use string.h, not gdb_string.h. * alpha-linux-tdep.c: Use string.h, not gdb_string.h. * alpha-mdebug-tdep.c: Use string.h, not gdb_string.h. * alpha-nat.c: Use string.h, not gdb_string.h. * alpha-osf1-tdep.c: Use string.h, not gdb_string.h. * alpha-tdep.c: Use string.h, not gdb_string.h. * alphanbsd-tdep.c: Use string.h, not gdb_string.h. * amd64-dicos-tdep.c: Use string.h, not gdb_string.h. * amd64-linux-nat.c: Use string.h, not gdb_string.h. * amd64-linux-tdep.c: Use string.h, not gdb_string.h. * amd64-nat.c: Use string.h, not gdb_string.h. * amd64-sol2-tdep.c: Use string.h, not gdb_string.h. * amd64fbsd-tdep.c: Use string.h, not gdb_string.h. * amd64obsd-tdep.c: Use string.h, not gdb_string.h. * arch-utils.c: Use string.h, not gdb_string.h. * arm-linux-nat.c: Use string.h, not gdb_string.h. * arm-linux-tdep.c: Use string.h, not gdb_string.h. * arm-tdep.c: Use string.h, not gdb_string.h. * arm-wince-tdep.c: Use string.h, not gdb_string.h. * armbsd-tdep.c: Use string.h, not gdb_string.h. * armnbsd-nat.c: Use string.h, not gdb_string.h. * armnbsd-tdep.c: Use string.h, not gdb_string.h. * armobsd-tdep.c: Use string.h, not gdb_string.h. * avr-tdep.c: Use string.h, not gdb_string.h. * ax-gdb.c: Use string.h, not gdb_string.h. * ax-general.c: Use string.h, not gdb_string.h. * bcache.c: Use string.h, not gdb_string.h. * bfin-tdep.c: Use string.h, not gdb_string.h. * breakpoint.c: Use string.h, not gdb_string.h. * build-id.c: Use string.h, not gdb_string.h. * buildsym.c: Use string.h, not gdb_string.h. * c-exp.y: Use string.h, not gdb_string.h. * c-lang.c: Use string.h, not gdb_string.h. * c-typeprint.c: Use string.h, not gdb_string.h. * c-valprint.c: Use string.h, not gdb_string.h. * charset.c: Use string.h, not gdb_string.h. * cli-out.c: Use string.h, not gdb_string.h. * cli/cli-cmds.c: Use string.h, not gdb_string.h. * cli/cli-decode.c: Use string.h, not gdb_string.h. * cli/cli-dump.c: Use string.h, not gdb_string.h. * cli/cli-interp.c: Use string.h, not gdb_string.h. * cli/cli-logging.c: Use string.h, not gdb_string.h. * cli/cli-script.c: Use string.h, not gdb_string.h. * cli/cli-setshow.c: Use string.h, not gdb_string.h. * cli/cli-utils.c: Use string.h, not gdb_string.h. * coffread.c: Use string.h, not gdb_string.h. * common/common-utils.c: Use string.h, not gdb_string.h. * common/filestuff.c: Use string.h, not gdb_string.h. * common/linux-procfs.c: Use string.h, not gdb_string.h. * common/linux-ptrace.c: Use string.h, not gdb_string.h. * common/signals.c: Use string.h, not gdb_string.h. * common/vec.h: Use string.h, not gdb_string.h. * core-regset.c: Use string.h, not gdb_string.h. * corefile.c: Use string.h, not gdb_string.h. * corelow.c: Use string.h, not gdb_string.h. * cp-abi.c: Use string.h, not gdb_string.h. * cp-support.c: Use string.h, not gdb_string.h. * cp-valprint.c: Use string.h, not gdb_string.h. * cris-tdep.c: Use string.h, not gdb_string.h. * d-lang.c: Use string.h, not gdb_string.h. * dbxread.c: Use string.h, not gdb_string.h. * dcache.c: Use string.h, not gdb_string.h. * demangle.c: Use string.h, not gdb_string.h. * dicos-tdep.c: Use string.h, not gdb_string.h. * disasm.c: Use string.h, not gdb_string.h. * doublest.c: Use string.h, not gdb_string.h. * dsrec.c: Use string.h, not gdb_string.h. * dummy-frame.c: Use string.h, not gdb_string.h. * dwarf2-frame.c: Use string.h, not gdb_string.h. * dwarf2loc.c: Use string.h, not gdb_string.h. * dwarf2read.c: Use string.h, not gdb_string.h. * elfread.c: Use string.h, not gdb_string.h. * environ.c: Use string.h, not gdb_string.h. * eval.c: Use string.h, not gdb_string.h. * event-loop.c: Use string.h, not gdb_string.h. * exceptions.c: Use string.h, not gdb_string.h. * exec.c: Use string.h, not gdb_string.h. * expprint.c: Use string.h, not gdb_string.h. * f-exp.y: Use string.h, not gdb_string.h. * f-lang.c: Use string.h, not gdb_string.h. * f-typeprint.c: Use string.h, not gdb_string.h. * f-valprint.c: Use string.h, not gdb_string.h. * fbsd-nat.c: Use string.h, not gdb_string.h. * findcmd.c: Use string.h, not gdb_string.h. * findvar.c: Use string.h, not gdb_string.h. * fork-child.c: Use string.h, not gdb_string.h. * frame.c: Use string.h, not gdb_string.h. * frv-linux-tdep.c: Use string.h, not gdb_string.h. * frv-tdep.c: Use string.h, not gdb_string.h. * gdb.c: Use string.h, not gdb_string.h. * gdb_bfd.c: Use string.h, not gdb_string.h. * gdbarch.c: Use string.h, not gdb_string.h. * gdbtypes.c: Use string.h, not gdb_string.h. * gnu-nat.c: Use string.h, not gdb_string.h. * gnu-v2-abi.c: Use string.h, not gdb_string.h. * gnu-v3-abi.c: Use string.h, not gdb_string.h. * go-exp.y: Use string.h, not gdb_string.h. * go-lang.c: Use string.h, not gdb_string.h. * go32-nat.c: Use string.h, not gdb_string.h. * hppa-hpux-tdep.c: Use string.h, not gdb_string.h. * hppa-linux-nat.c: Use string.h, not gdb_string.h. * hppanbsd-tdep.c: Use string.h, not gdb_string.h. * hppaobsd-tdep.c: Use string.h, not gdb_string.h. * i386-cygwin-tdep.c: Use string.h, not gdb_string.h. * i386-dicos-tdep.c: Use string.h, not gdb_string.h. * i386-linux-nat.c: Use string.h, not gdb_string.h. * i386-linux-tdep.c: Use string.h, not gdb_string.h. * i386-nto-tdep.c: Use string.h, not gdb_string.h. * i386-sol2-tdep.c: Use string.h, not gdb_string.h. * i386-tdep.c: Use string.h, not gdb_string.h. * i386bsd-tdep.c: Use string.h, not gdb_string.h. * i386gnu-nat.c: Use string.h, not gdb_string.h. * i386nbsd-tdep.c: Use string.h, not gdb_string.h. * i386obsd-tdep.c: Use string.h, not gdb_string.h. * i387-tdep.c: Use string.h, not gdb_string.h. * ia64-libunwind-tdep.c: Use string.h, not gdb_string.h. * ia64-linux-nat.c: Use string.h, not gdb_string.h. * inf-child.c: Use string.h, not gdb_string.h. * inf-ptrace.c: Use string.h, not gdb_string.h. * inf-ttrace.c: Use string.h, not gdb_string.h. * infcall.c: Use string.h, not gdb_string.h. * infcmd.c: Use string.h, not gdb_string.h. * inflow.c: Use string.h, not gdb_string.h. * infrun.c: Use string.h, not gdb_string.h. * interps.c: Use string.h, not gdb_string.h. * iq2000-tdep.c: Use string.h, not gdb_string.h. * irix5-nat.c: Use string.h, not gdb_string.h. * jv-exp.y: Use string.h, not gdb_string.h. * jv-lang.c: Use string.h, not gdb_string.h. * jv-typeprint.c: Use string.h, not gdb_string.h. * jv-valprint.c: Use string.h, not gdb_string.h. * language.c: Use string.h, not gdb_string.h. * linux-fork.c: Use string.h, not gdb_string.h. * linux-nat.c: Use string.h, not gdb_string.h. * lm32-tdep.c: Use string.h, not gdb_string.h. * m2-exp.y: Use string.h, not gdb_string.h. * m2-typeprint.c: Use string.h, not gdb_string.h. * m32c-tdep.c: Use string.h, not gdb_string.h. * m32r-linux-nat.c: Use string.h, not gdb_string.h. * m32r-linux-tdep.c: Use string.h, not gdb_string.h. * m32r-rom.c: Use string.h, not gdb_string.h. * m32r-tdep.c: Use string.h, not gdb_string.h. * m68hc11-tdep.c: Use string.h, not gdb_string.h. * m68k-tdep.c: Use string.h, not gdb_string.h. * m68kbsd-tdep.c: Use string.h, not gdb_string.h. * m68klinux-nat.c: Use string.h, not gdb_string.h. * m68klinux-tdep.c: Use string.h, not gdb_string.h. * m88k-tdep.c: Use string.h, not gdb_string.h. * macrocmd.c: Use string.h, not gdb_string.h. * main.c: Use string.h, not gdb_string.h. * mdebugread.c: Use string.h, not gdb_string.h. * mem-break.c: Use string.h, not gdb_string.h. * memattr.c: Use string.h, not gdb_string.h. * memory-map.c: Use string.h, not gdb_string.h. * mep-tdep.c: Use string.h, not gdb_string.h. * mi/mi-cmd-break.c: Use string.h, not gdb_string.h. * mi/mi-cmd-disas.c: Use string.h, not gdb_string.h. * mi/mi-cmd-env.c: Use string.h, not gdb_string.h. * mi/mi-cmd-stack.c: Use string.h, not gdb_string.h. * mi/mi-cmd-var.c: Use string.h, not gdb_string.h. * mi/mi-cmds.c: Use string.h, not gdb_string.h. * mi/mi-console.c: Use string.h, not gdb_string.h. * mi/mi-getopt.c: Use string.h, not gdb_string.h. * mi/mi-interp.c: Use string.h, not gdb_string.h. * mi/mi-main.c: Use string.h, not gdb_string.h. * mi/mi-parse.c: Use string.h, not gdb_string.h. * microblaze-rom.c: Use string.h, not gdb_string.h. * microblaze-tdep.c: Use string.h, not gdb_string.h. * mingw-hdep.c: Use string.h, not gdb_string.h. * minidebug.c: Use string.h, not gdb_string.h. * minsyms.c: Use string.h, not gdb_string.h. * mips-irix-tdep.c: Use string.h, not gdb_string.h. * mips-linux-tdep.c: Use string.h, not gdb_string.h. * mips-tdep.c: Use string.h, not gdb_string.h. * mips64obsd-tdep.c: Use string.h, not gdb_string.h. * mipsnbsd-tdep.c: Use string.h, not gdb_string.h. * mipsread.c: Use string.h, not gdb_string.h. * mn10300-linux-tdep.c: Use string.h, not gdb_string.h. * mn10300-tdep.c: Use string.h, not gdb_string.h. * monitor.c: Use string.h, not gdb_string.h. * moxie-tdep.c: Use string.h, not gdb_string.h. * mt-tdep.c: Use string.h, not gdb_string.h. * nbsd-tdep.c: Use string.h, not gdb_string.h. * nios2-linux-tdep.c: Use string.h, not gdb_string.h. * nto-procfs.c: Use string.h, not gdb_string.h. * nto-tdep.c: Use string.h, not gdb_string.h. * objc-lang.c: Use string.h, not gdb_string.h. * objfiles.c: Use string.h, not gdb_string.h. * opencl-lang.c: Use string.h, not gdb_string.h. * osabi.c: Use string.h, not gdb_string.h. * osdata.c: Use string.h, not gdb_string.h. * p-exp.y: Use string.h, not gdb_string.h. * p-lang.c: Use string.h, not gdb_string.h. * p-typeprint.c: Use string.h, not gdb_string.h. * parse.c: Use string.h, not gdb_string.h. * posix-hdep.c: Use string.h, not gdb_string.h. * ppc-linux-nat.c: Use string.h, not gdb_string.h. * ppc-sysv-tdep.c: Use string.h, not gdb_string.h. * ppcfbsd-tdep.c: Use string.h, not gdb_string.h. * ppcnbsd-tdep.c: Use string.h, not gdb_string.h. * ppcobsd-tdep.c: Use string.h, not gdb_string.h. * printcmd.c: Use string.h, not gdb_string.h. * procfs.c: Use string.h, not gdb_string.h. * prologue-value.c: Use string.h, not gdb_string.h. * python/py-auto-load.c: Use string.h, not gdb_string.h. * python/py-gdb-readline.c: Use string.h, not gdb_string.h. * ravenscar-thread.c: Use string.h, not gdb_string.h. * regcache.c: Use string.h, not gdb_string.h. * registry.c: Use string.h, not gdb_string.h. * remote-fileio.c: Use string.h, not gdb_string.h. * remote-m32r-sdi.c: Use string.h, not gdb_string.h. * remote-mips.c: Use string.h, not gdb_string.h. * remote-sim.c: Use string.h, not gdb_string.h. * remote.c: Use string.h, not gdb_string.h. * reverse.c: Use string.h, not gdb_string.h. * rs6000-aix-tdep.c: Use string.h, not gdb_string.h. * ser-base.c: Use string.h, not gdb_string.h. * ser-go32.c: Use string.h, not gdb_string.h. * ser-mingw.c: Use string.h, not gdb_string.h. * ser-pipe.c: Use string.h, not gdb_string.h. * ser-tcp.c: Use string.h, not gdb_string.h. * ser-unix.c: Use string.h, not gdb_string.h. * serial.c: Use string.h, not gdb_string.h. * sh-tdep.c: Use string.h, not gdb_string.h. * sh64-tdep.c: Use string.h, not gdb_string.h. * shnbsd-tdep.c: Use string.h, not gdb_string.h. * skip.c: Use string.h, not gdb_string.h. * sol-thread.c: Use string.h, not gdb_string.h. * solib-dsbt.c: Use string.h, not gdb_string.h. * solib-frv.c: Use string.h, not gdb_string.h. * solib-osf.c: Use string.h, not gdb_string.h. * solib-spu.c: Use string.h, not gdb_string.h. * solib-target.c: Use string.h, not gdb_string.h. * solib.c: Use string.h, not gdb_string.h. * somread.c: Use string.h, not gdb_string.h. * source.c: Use string.h, not gdb_string.h. * sparc-nat.c: Use string.h, not gdb_string.h. * sparc-sol2-tdep.c: Use string.h, not gdb_string.h. * sparc-tdep.c: Use string.h, not gdb_string.h. * sparc64-tdep.c: Use string.h, not gdb_string.h. * sparc64fbsd-tdep.c: Use string.h, not gdb_string.h. * sparc64nbsd-tdep.c: Use string.h, not gdb_string.h. * sparcnbsd-tdep.c: Use string.h, not gdb_string.h. * spu-linux-nat.c: Use string.h, not gdb_string.h. * spu-multiarch.c: Use string.h, not gdb_string.h. * spu-tdep.c: Use string.h, not gdb_string.h. * stabsread.c: Use string.h, not gdb_string.h. * stack.c: Use string.h, not gdb_string.h. * std-regs.c: Use string.h, not gdb_string.h. * symfile.c: Use string.h, not gdb_string.h. * symmisc.c: Use string.h, not gdb_string.h. * symtab.c: Use string.h, not gdb_string.h. * target.c: Use string.h, not gdb_string.h. * thread.c: Use string.h, not gdb_string.h. * tilegx-linux-nat.c: Use string.h, not gdb_string.h. * tilegx-tdep.c: Use string.h, not gdb_string.h. * top.c: Use string.h, not gdb_string.h. * tracepoint.c: Use string.h, not gdb_string.h. * tui/tui-command.c: Use string.h, not gdb_string.h. * tui/tui-data.c: Use string.h, not gdb_string.h. * tui/tui-disasm.c: Use string.h, not gdb_string.h. * tui/tui-file.c: Use string.h, not gdb_string.h. * tui/tui-layout.c: Use string.h, not gdb_string.h. * tui/tui-out.c: Use string.h, not gdb_string.h. * tui/tui-regs.c: Use string.h, not gdb_string.h. * tui/tui-source.c: Use string.h, not gdb_string.h. * tui/tui-stack.c: Use string.h, not gdb_string.h. * tui/tui-win.c: Use string.h, not gdb_string.h. * tui/tui-windata.c: Use string.h, not gdb_string.h. * tui/tui-winsource.c: Use string.h, not gdb_string.h. * typeprint.c: Use string.h, not gdb_string.h. * ui-file.c: Use string.h, not gdb_string.h. * ui-out.c: Use string.h, not gdb_string.h. * user-regs.c: Use string.h, not gdb_string.h. * utils.c: Use string.h, not gdb_string.h. * v850-tdep.c: Use string.h, not gdb_string.h. * valarith.c: Use string.h, not gdb_string.h. * valops.c: Use string.h, not gdb_string.h. * valprint.c: Use string.h, not gdb_string.h. * value.c: Use string.h, not gdb_string.h. * varobj.c: Use string.h, not gdb_string.h. * vax-tdep.c: Use string.h, not gdb_string.h. * vaxnbsd-tdep.c: Use string.h, not gdb_string.h. * vaxobsd-tdep.c: Use string.h, not gdb_string.h. * windows-nat.c: Use string.h, not gdb_string.h. * xcoffread.c: Use string.h, not gdb_string.h. * xml-support.c: Use string.h, not gdb_string.h. * xstormy16-tdep.c: Use string.h, not gdb_string.h. * xtensa-linux-nat.c: Use string.h, not gdb_string.h.
1134 lines
31 KiB
C
1134 lines
31 KiB
C
/* Support for printing Ada values for GDB, the GNU debugger.
|
||
|
||
Copyright (C) 1986-2013 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 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/>. */
|
||
|
||
#include "defs.h"
|
||
#include <ctype.h>
|
||
#include <string.h>
|
||
#include "symtab.h"
|
||
#include "gdbtypes.h"
|
||
#include "expression.h"
|
||
#include "value.h"
|
||
#include "demangle.h"
|
||
#include "valprint.h"
|
||
#include "language.h"
|
||
#include "annotate.h"
|
||
#include "ada-lang.h"
|
||
#include "c-lang.h"
|
||
#include "infcall.h"
|
||
#include "exceptions.h"
|
||
#include "objfiles.h"
|
||
|
||
static void print_record (struct type *, const gdb_byte *, int,
|
||
struct ui_file *,
|
||
int,
|
||
const struct value *,
|
||
const struct value_print_options *);
|
||
|
||
static int print_field_values (struct type *, const gdb_byte *,
|
||
int,
|
||
struct ui_file *, int,
|
||
const struct value *,
|
||
const struct value_print_options *,
|
||
int, struct type *, int);
|
||
|
||
static void adjust_type_signedness (struct type *);
|
||
|
||
static void ada_val_print_1 (struct type *, const gdb_byte *, int, CORE_ADDR,
|
||
struct ui_file *, int,
|
||
const struct value *,
|
||
const struct value_print_options *);
|
||
|
||
|
||
/* Make TYPE unsigned if its range of values includes no negatives. */
|
||
static void
|
||
adjust_type_signedness (struct type *type)
|
||
{
|
||
if (type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE
|
||
&& TYPE_LOW_BOUND (type) >= 0)
|
||
TYPE_UNSIGNED (type) = 1;
|
||
}
|
||
|
||
/* Assuming TYPE is a simple array type, prints its lower bound on STREAM,
|
||
if non-standard (i.e., other than 1 for numbers, other than lower bound
|
||
of index type for enumerated type). Returns 1 if something printed,
|
||
otherwise 0. */
|
||
|
||
static int
|
||
print_optional_low_bound (struct ui_file *stream, struct type *type,
|
||
const struct value_print_options *options)
|
||
{
|
||
struct type *index_type;
|
||
LONGEST low_bound;
|
||
LONGEST high_bound;
|
||
|
||
if (options->print_array_indexes)
|
||
return 0;
|
||
|
||
if (!get_array_bounds (type, &low_bound, &high_bound))
|
||
return 0;
|
||
|
||
/* If this is an empty array, then don't print the lower bound.
|
||
That would be confusing, because we would print the lower bound,
|
||
followed by... nothing! */
|
||
if (low_bound > high_bound)
|
||
return 0;
|
||
|
||
index_type = TYPE_INDEX_TYPE (type);
|
||
|
||
if (TYPE_CODE (index_type) == TYPE_CODE_RANGE)
|
||
{
|
||
/* We need to know what the base type is, in order to do the
|
||
appropriate check below. Otherwise, if this is a subrange
|
||
of an enumerated type, where the underlying value of the
|
||
first element is typically 0, we might test the low bound
|
||
against the wrong value. */
|
||
index_type = TYPE_TARGET_TYPE (index_type);
|
||
}
|
||
|
||
switch (TYPE_CODE (index_type))
|
||
{
|
||
case TYPE_CODE_BOOL:
|
||
if (low_bound == 0)
|
||
return 0;
|
||
break;
|
||
case TYPE_CODE_ENUM:
|
||
if (low_bound == TYPE_FIELD_ENUMVAL (index_type, 0))
|
||
return 0;
|
||
break;
|
||
case TYPE_CODE_UNDEF:
|
||
index_type = NULL;
|
||
/* FALL THROUGH */
|
||
default:
|
||
if (low_bound == 1)
|
||
return 0;
|
||
break;
|
||
}
|
||
|
||
ada_print_scalar (index_type, low_bound, stream);
|
||
fprintf_filtered (stream, " => ");
|
||
return 1;
|
||
}
|
||
|
||
/* Version of val_print_array_elements for GNAT-style packed arrays.
|
||
Prints elements of packed array of type TYPE at bit offset
|
||
BITOFFSET from VALADDR on STREAM. Formats according to OPTIONS and
|
||
separates with commas. RECURSE is the recursion (nesting) level.
|
||
TYPE must have been decoded (as by ada_coerce_to_simple_array). */
|
||
|
||
static void
|
||
val_print_packed_array_elements (struct type *type, const gdb_byte *valaddr,
|
||
int offset,
|
||
int bitoffset, struct ui_file *stream,
|
||
int recurse,
|
||
const struct value *val,
|
||
const struct value_print_options *options)
|
||
{
|
||
unsigned int i;
|
||
unsigned int things_printed = 0;
|
||
unsigned len;
|
||
struct type *elttype, *index_type;
|
||
unsigned eltlen;
|
||
unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0);
|
||
struct value *mark = value_mark ();
|
||
LONGEST low = 0;
|
||
|
||
elttype = TYPE_TARGET_TYPE (type);
|
||
eltlen = TYPE_LENGTH (check_typedef (elttype));
|
||
index_type = TYPE_INDEX_TYPE (type);
|
||
|
||
{
|
||
LONGEST high;
|
||
|
||
if (get_discrete_bounds (index_type, &low, &high) < 0)
|
||
len = 1;
|
||
else
|
||
len = high - low + 1;
|
||
}
|
||
|
||
i = 0;
|
||
annotate_array_section_begin (i, elttype);
|
||
|
||
while (i < len && things_printed < options->print_max)
|
||
{
|
||
struct value *v0, *v1;
|
||
int i0;
|
||
|
||
if (i != 0)
|
||
{
|
||
if (options->prettyformat_arrays)
|
||
{
|
||
fprintf_filtered (stream, ",\n");
|
||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||
}
|
||
else
|
||
{
|
||
fprintf_filtered (stream, ", ");
|
||
}
|
||
}
|
||
wrap_here (n_spaces (2 + 2 * recurse));
|
||
maybe_print_array_index (index_type, i + low, stream, options);
|
||
|
||
i0 = i;
|
||
v0 = ada_value_primitive_packed_val (NULL, valaddr + offset,
|
||
(i0 * bitsize) / HOST_CHAR_BIT,
|
||
(i0 * bitsize) % HOST_CHAR_BIT,
|
||
bitsize, elttype);
|
||
while (1)
|
||
{
|
||
i += 1;
|
||
if (i >= len)
|
||
break;
|
||
v1 = ada_value_primitive_packed_val (NULL, valaddr + offset,
|
||
(i * bitsize) / HOST_CHAR_BIT,
|
||
(i * bitsize) % HOST_CHAR_BIT,
|
||
bitsize, elttype);
|
||
if (!value_available_contents_eq (v0, value_embedded_offset (v0),
|
||
v1, value_embedded_offset (v1),
|
||
eltlen))
|
||
break;
|
||
}
|
||
|
||
if (i - i0 > options->repeat_count_threshold)
|
||
{
|
||
struct value_print_options opts = *options;
|
||
|
||
opts.deref_ref = 0;
|
||
val_print (elttype, value_contents_for_printing (v0),
|
||
value_embedded_offset (v0), 0, stream,
|
||
recurse + 1, v0, &opts, current_language);
|
||
annotate_elt_rep (i - i0);
|
||
fprintf_filtered (stream, _(" <repeats %u times>"), i - i0);
|
||
annotate_elt_rep_end ();
|
||
|
||
}
|
||
else
|
||
{
|
||
int j;
|
||
struct value_print_options opts = *options;
|
||
|
||
opts.deref_ref = 0;
|
||
for (j = i0; j < i; j += 1)
|
||
{
|
||
if (j > i0)
|
||
{
|
||
if (options->prettyformat_arrays)
|
||
{
|
||
fprintf_filtered (stream, ",\n");
|
||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||
}
|
||
else
|
||
{
|
||
fprintf_filtered (stream, ", ");
|
||
}
|
||
wrap_here (n_spaces (2 + 2 * recurse));
|
||
maybe_print_array_index (index_type, j + low,
|
||
stream, options);
|
||
}
|
||
val_print (elttype, value_contents_for_printing (v0),
|
||
value_embedded_offset (v0), 0, stream,
|
||
recurse + 1, v0, &opts, current_language);
|
||
annotate_elt ();
|
||
}
|
||
}
|
||
things_printed += i - i0;
|
||
}
|
||
annotate_array_section_end ();
|
||
if (i < len)
|
||
{
|
||
fprintf_filtered (stream, "...");
|
||
}
|
||
|
||
value_free_to_mark (mark);
|
||
}
|
||
|
||
static struct type *
|
||
printable_val_type (struct type *type, const gdb_byte *valaddr)
|
||
{
|
||
return ada_to_fixed_type (ada_aligned_type (type), valaddr, 0, NULL, 1);
|
||
}
|
||
|
||
/* Print the character C on STREAM as part of the contents of a literal
|
||
string whose delimiter is QUOTER. TYPE_LEN is the length in bytes
|
||
of the character. */
|
||
|
||
void
|
||
ada_emit_char (int c, struct type *type, struct ui_file *stream,
|
||
int quoter, int type_len)
|
||
{
|
||
/* If this character fits in the normal ASCII range, and is
|
||
a printable character, then print the character as if it was
|
||
an ASCII character, even if this is a wide character.
|
||
The UCHAR_MAX check is necessary because the isascii function
|
||
requires that its argument have a value of an unsigned char,
|
||
or EOF (EOF is obviously not printable). */
|
||
if (c <= UCHAR_MAX && isascii (c) && isprint (c))
|
||
{
|
||
if (c == quoter && c == '"')
|
||
fprintf_filtered (stream, "\"\"");
|
||
else
|
||
fprintf_filtered (stream, "%c", c);
|
||
}
|
||
else
|
||
fprintf_filtered (stream, "[\"%0*x\"]", type_len * 2, c);
|
||
}
|
||
|
||
/* Character #I of STRING, given that TYPE_LEN is the size in bytes
|
||
of a character. */
|
||
|
||
static int
|
||
char_at (const gdb_byte *string, int i, int type_len,
|
||
enum bfd_endian byte_order)
|
||
{
|
||
if (type_len == 1)
|
||
return string[i];
|
||
else
|
||
return (int) extract_unsigned_integer (string + type_len * i,
|
||
type_len, byte_order);
|
||
}
|
||
|
||
/* Wrapper around memcpy to make it legal argument to ui_file_put. */
|
||
static void
|
||
ui_memcpy (void *dest, const char *buffer, long len)
|
||
{
|
||
memcpy (dest, buffer, (size_t) len);
|
||
((char *) dest)[len] = '\0';
|
||
}
|
||
|
||
/* Print a floating-point value of type TYPE, pointed to in GDB by
|
||
VALADDR, on STREAM. Use Ada formatting conventions: there must be
|
||
a decimal point, and at least one digit before and after the
|
||
point. We use GNAT format for NaNs and infinities. */
|
||
static void
|
||
ada_print_floating (const gdb_byte *valaddr, struct type *type,
|
||
struct ui_file *stream)
|
||
{
|
||
char buffer[64];
|
||
char *s, *result;
|
||
struct ui_file *tmp_stream = mem_fileopen ();
|
||
struct cleanup *cleanups = make_cleanup_ui_file_delete (tmp_stream);
|
||
|
||
print_floating (valaddr, type, tmp_stream);
|
||
ui_file_put (tmp_stream, ui_memcpy, buffer);
|
||
do_cleanups (cleanups);
|
||
|
||
result = buffer;
|
||
|
||
/* Modify for Ada rules. */
|
||
|
||
s = strstr (result, "inf");
|
||
if (s == NULL)
|
||
s = strstr (result, "Inf");
|
||
if (s == NULL)
|
||
s = strstr (result, "INF");
|
||
if (s != NULL)
|
||
strcpy (s, "Inf");
|
||
|
||
if (s == NULL)
|
||
{
|
||
s = strstr (result, "nan");
|
||
if (s == NULL)
|
||
s = strstr (result, "NaN");
|
||
if (s == NULL)
|
||
s = strstr (result, "Nan");
|
||
if (s != NULL)
|
||
{
|
||
s[0] = s[2] = 'N';
|
||
if (result[0] == '-')
|
||
result += 1;
|
||
}
|
||
}
|
||
|
||
if (s == NULL && strchr (result, '.') == NULL)
|
||
{
|
||
s = strchr (result, 'e');
|
||
if (s == NULL)
|
||
fprintf_filtered (stream, "%s.0", result);
|
||
else
|
||
fprintf_filtered (stream, "%.*s.0%s", (int) (s-result), result, s);
|
||
return;
|
||
}
|
||
fprintf_filtered (stream, "%s", result);
|
||
}
|
||
|
||
void
|
||
ada_printchar (int c, struct type *type, struct ui_file *stream)
|
||
{
|
||
fputs_filtered ("'", stream);
|
||
ada_emit_char (c, type, stream, '\'', TYPE_LENGTH (type));
|
||
fputs_filtered ("'", stream);
|
||
}
|
||
|
||
/* [From print_type_scalar in typeprint.c]. Print VAL on STREAM in a
|
||
form appropriate for TYPE, if non-NULL. If TYPE is NULL, print VAL
|
||
like a default signed integer. */
|
||
|
||
void
|
||
ada_print_scalar (struct type *type, LONGEST val, struct ui_file *stream)
|
||
{
|
||
unsigned int i;
|
||
unsigned len;
|
||
|
||
if (!type)
|
||
{
|
||
print_longest (stream, 'd', 0, val);
|
||
return;
|
||
}
|
||
|
||
type = ada_check_typedef (type);
|
||
|
||
switch (TYPE_CODE (type))
|
||
{
|
||
|
||
case TYPE_CODE_ENUM:
|
||
len = TYPE_NFIELDS (type);
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
if (TYPE_FIELD_ENUMVAL (type, i) == val)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (i < len)
|
||
{
|
||
fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
|
||
}
|
||
else
|
||
{
|
||
print_longest (stream, 'd', 0, val);
|
||
}
|
||
break;
|
||
|
||
case TYPE_CODE_INT:
|
||
print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
|
||
break;
|
||
|
||
case TYPE_CODE_CHAR:
|
||
LA_PRINT_CHAR (val, type, stream);
|
||
break;
|
||
|
||
case TYPE_CODE_BOOL:
|
||
fprintf_filtered (stream, val ? "true" : "false");
|
||
break;
|
||
|
||
case TYPE_CODE_RANGE:
|
||
ada_print_scalar (TYPE_TARGET_TYPE (type), val, stream);
|
||
return;
|
||
|
||
case TYPE_CODE_UNDEF:
|
||
case TYPE_CODE_PTR:
|
||
case TYPE_CODE_ARRAY:
|
||
case TYPE_CODE_STRUCT:
|
||
case TYPE_CODE_UNION:
|
||
case TYPE_CODE_FUNC:
|
||
case TYPE_CODE_FLT:
|
||
case TYPE_CODE_VOID:
|
||
case TYPE_CODE_SET:
|
||
case TYPE_CODE_STRING:
|
||
case TYPE_CODE_ERROR:
|
||
case TYPE_CODE_MEMBERPTR:
|
||
case TYPE_CODE_METHODPTR:
|
||
case TYPE_CODE_METHOD:
|
||
case TYPE_CODE_REF:
|
||
warning (_("internal error: unhandled type in ada_print_scalar"));
|
||
break;
|
||
|
||
default:
|
||
error (_("Invalid type code in symbol table."));
|
||
}
|
||
gdb_flush (stream);
|
||
}
|
||
|
||
/* Print the character string STRING, printing at most LENGTH characters.
|
||
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.
|
||
TYPE_LEN is the length (1 or 2) of the character type. */
|
||
|
||
static void
|
||
printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string,
|
||
unsigned int length, int force_ellipses, int type_len,
|
||
const struct value_print_options *options)
|
||
{
|
||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (elttype));
|
||
unsigned int i;
|
||
unsigned int things_printed = 0;
|
||
int in_quotes = 0;
|
||
int need_comma = 0;
|
||
|
||
if (length == 0)
|
||
{
|
||
fputs_filtered ("\"\"", stream);
|
||
return;
|
||
}
|
||
|
||
for (i = 0; i < length && things_printed < options->print_max; i += 1)
|
||
{
|
||
/* 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;
|
||
|
||
QUIT;
|
||
|
||
if (need_comma)
|
||
{
|
||
fputs_filtered (", ", stream);
|
||
need_comma = 0;
|
||
}
|
||
|
||
rep1 = i + 1;
|
||
reps = 1;
|
||
while (rep1 < length
|
||
&& char_at (string, rep1, type_len, byte_order)
|
||
== char_at (string, i, type_len, byte_order))
|
||
{
|
||
rep1 += 1;
|
||
reps += 1;
|
||
}
|
||
|
||
if (reps > options->repeat_count_threshold)
|
||
{
|
||
if (in_quotes)
|
||
{
|
||
fputs_filtered ("\", ", stream);
|
||
in_quotes = 0;
|
||
}
|
||
fputs_filtered ("'", stream);
|
||
ada_emit_char (char_at (string, i, type_len, byte_order),
|
||
elttype, stream, '\'', type_len);
|
||
fputs_filtered ("'", stream);
|
||
fprintf_filtered (stream, _(" <repeats %u times>"), reps);
|
||
i = rep1 - 1;
|
||
things_printed += options->repeat_count_threshold;
|
||
need_comma = 1;
|
||
}
|
||
else
|
||
{
|
||
if (!in_quotes)
|
||
{
|
||
fputs_filtered ("\"", stream);
|
||
in_quotes = 1;
|
||
}
|
||
ada_emit_char (char_at (string, i, type_len, byte_order),
|
||
elttype, stream, '"', type_len);
|
||
things_printed += 1;
|
||
}
|
||
}
|
||
|
||
/* Terminate the quotes if necessary. */
|
||
if (in_quotes)
|
||
fputs_filtered ("\"", stream);
|
||
|
||
if (force_ellipses || i < length)
|
||
fputs_filtered ("...", stream);
|
||
}
|
||
|
||
void
|
||
ada_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)
|
||
{
|
||
printstr (stream, type, string, length, force_ellipses, TYPE_LENGTH (type),
|
||
options);
|
||
}
|
||
|
||
|
||
/* See val_print for a description of the various parameters of this
|
||
function; they are identical. */
|
||
|
||
void
|
||
ada_val_print (struct type *type, const gdb_byte *valaddr,
|
||
int embedded_offset, CORE_ADDR address,
|
||
struct ui_file *stream, int recurse,
|
||
const struct value *val,
|
||
const struct value_print_options *options)
|
||
{
|
||
volatile struct gdb_exception except;
|
||
|
||
/* XXX: this catches QUIT/ctrl-c as well. Isn't that busted? */
|
||
TRY_CATCH (except, RETURN_MASK_ALL)
|
||
{
|
||
ada_val_print_1 (type, valaddr, embedded_offset, address,
|
||
stream, recurse, val, options);
|
||
}
|
||
}
|
||
|
||
/* Assuming TYPE is a simple array, print the value of this array located
|
||
at VALADDR + OFFSET. See ada_val_print for a description of the various
|
||
parameters of this function; they are identical. */
|
||
|
||
static void
|
||
ada_val_print_array (struct type *type, const gdb_byte *valaddr,
|
||
int offset, CORE_ADDR address,
|
||
struct ui_file *stream, int recurse,
|
||
const struct value *val,
|
||
const struct value_print_options *options)
|
||
{
|
||
/* For an array of chars, print with string syntax. */
|
||
if (ada_is_string_type (type)
|
||
&& (options->format == 0 || options->format == 's'))
|
||
{
|
||
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
|
||
struct type *elttype = TYPE_TARGET_TYPE (type);
|
||
unsigned int eltlen;
|
||
unsigned int len;
|
||
|
||
/* We know that ELTTYPE cannot possibly be null, because we found
|
||
that TYPE is a string-like type. Similarly, the size of ELTTYPE
|
||
should also be non-null, since it's a character-like type. */
|
||
gdb_assert (elttype != NULL);
|
||
gdb_assert (TYPE_LENGTH (elttype) != 0);
|
||
|
||
eltlen = TYPE_LENGTH (elttype);
|
||
len = TYPE_LENGTH (type) / eltlen;
|
||
|
||
if (options->prettyformat_arrays)
|
||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||
|
||
/* If requested, look for the first null char and only print
|
||
elements up to it. */
|
||
if (options->stop_print_at_null)
|
||
{
|
||
int temp_len;
|
||
|
||
/* Look for a NULL char. */
|
||
for (temp_len = 0;
|
||
(temp_len < len
|
||
&& temp_len < options->print_max
|
||
&& char_at (valaddr + offset,
|
||
temp_len, eltlen, byte_order) != 0);
|
||
temp_len += 1);
|
||
len = temp_len;
|
||
}
|
||
|
||
printstr (stream, elttype, valaddr + offset, len, 0, eltlen, options);
|
||
}
|
||
else
|
||
{
|
||
fprintf_filtered (stream, "(");
|
||
print_optional_low_bound (stream, type, options);
|
||
if (TYPE_FIELD_BITSIZE (type, 0) > 0)
|
||
val_print_packed_array_elements (type, valaddr, offset,
|
||
0, stream, recurse, val, options);
|
||
else
|
||
val_print_array_elements (type, valaddr, offset, address,
|
||
stream, recurse, val, options, 0);
|
||
fprintf_filtered (stream, ")");
|
||
}
|
||
}
|
||
|
||
/* See the comment on ada_val_print. This function differs in that it
|
||
does not catch evaluation errors (leaving that to ada_val_print). */
|
||
|
||
static void
|
||
ada_val_print_1 (struct type *type, const gdb_byte *valaddr,
|
||
int offset, CORE_ADDR address,
|
||
struct ui_file *stream, int recurse,
|
||
const struct value *original_value,
|
||
const struct value_print_options *options)
|
||
{
|
||
int i;
|
||
struct type *elttype;
|
||
int offset_aligned;
|
||
|
||
type = ada_check_typedef (type);
|
||
|
||
if (ada_is_array_descriptor_type (type)
|
||
|| (ada_is_constrained_packed_array_type (type)
|
||
&& TYPE_CODE (type) != TYPE_CODE_PTR))
|
||
{
|
||
struct value *mark = value_mark ();
|
||
struct value *val;
|
||
|
||
val = value_from_contents_and_address (type, valaddr + offset, address);
|
||
/* If this is a reference, coerce it now. This helps taking care
|
||
of the case where ADDRESS is meaningless because original_value
|
||
was not an lval. */
|
||
val = coerce_ref (val);
|
||
if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) /* array access type. */
|
||
val = ada_coerce_to_simple_array_ptr (val);
|
||
else
|
||
val = ada_coerce_to_simple_array (val);
|
||
if (val == NULL)
|
||
{
|
||
gdb_assert (TYPE_CODE (type) == TYPE_CODE_TYPEDEF);
|
||
fprintf_filtered (stream, "0x0");
|
||
}
|
||
else
|
||
ada_val_print_1 (value_type (val),
|
||
value_contents_for_printing (val),
|
||
value_embedded_offset (val),
|
||
value_address (val), stream, recurse,
|
||
val, options);
|
||
value_free_to_mark (mark);
|
||
return;
|
||
}
|
||
|
||
offset_aligned = offset + ada_aligned_value_addr (type, valaddr) - valaddr;
|
||
type = printable_val_type (type, valaddr + offset_aligned);
|
||
|
||
switch (TYPE_CODE (type))
|
||
{
|
||
default:
|
||
c_val_print (type, valaddr, offset, address, stream,
|
||
recurse, original_value, options);
|
||
break;
|
||
|
||
case TYPE_CODE_PTR:
|
||
{
|
||
c_val_print (type, valaddr, offset, address,
|
||
stream, recurse, original_value, options);
|
||
|
||
if (ada_is_tag_type (type))
|
||
{
|
||
struct value *val =
|
||
value_from_contents_and_address (type,
|
||
valaddr + offset_aligned,
|
||
address + offset_aligned);
|
||
const char *name = ada_tag_name (val);
|
||
|
||
if (name != NULL)
|
||
fprintf_filtered (stream, " (%s)", name);
|
||
}
|
||
return;
|
||
}
|
||
|
||
case TYPE_CODE_INT:
|
||
case TYPE_CODE_RANGE:
|
||
if (ada_is_fixed_point_type (type))
|
||
{
|
||
LONGEST v = unpack_long (type, valaddr + offset_aligned);
|
||
|
||
fprintf_filtered (stream, TYPE_LENGTH (type) < 4 ? "%.11g" : "%.17g",
|
||
(double) ada_fixed_to_float (type, v));
|
||
return;
|
||
}
|
||
else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
|
||
{
|
||
struct type *target_type = TYPE_TARGET_TYPE (type);
|
||
|
||
if (TYPE_LENGTH (type) != TYPE_LENGTH (target_type))
|
||
{
|
||
/* Obscure case of range type that has different length from
|
||
its base type. Perform a conversion, or we will get a
|
||
nonsense value. Actually, we could use the same
|
||
code regardless of lengths; I'm just avoiding a cast. */
|
||
struct value *v1
|
||
= value_from_contents_and_address (type, valaddr + offset, 0);
|
||
struct value *v = value_cast (target_type, v1);
|
||
|
||
ada_val_print_1 (target_type,
|
||
value_contents_for_printing (v),
|
||
value_embedded_offset (v), 0,
|
||
stream, recurse + 1, v, options);
|
||
}
|
||
else
|
||
ada_val_print_1 (TYPE_TARGET_TYPE (type),
|
||
valaddr, offset,
|
||
address, stream, recurse,
|
||
original_value, options);
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
int format = (options->format ? options->format
|
||
: options->output_format);
|
||
|
||
if (format)
|
||
{
|
||
struct value_print_options opts = *options;
|
||
|
||
opts.format = format;
|
||
val_print_scalar_formatted (type, valaddr, offset_aligned,
|
||
original_value, &opts, 0, stream);
|
||
}
|
||
else if (ada_is_system_address_type (type))
|
||
{
|
||
/* FIXME: We want to print System.Address variables using
|
||
the same format as for any access type. But for some
|
||
reason GNAT encodes the System.Address type as an int,
|
||
so we have to work-around this deficiency by handling
|
||
System.Address values as a special case. */
|
||
|
||
struct gdbarch *gdbarch = get_type_arch (type);
|
||
struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
|
||
CORE_ADDR addr = extract_typed_address (valaddr + offset_aligned,
|
||
ptr_type);
|
||
|
||
fprintf_filtered (stream, "(");
|
||
type_print (type, "", stream, -1);
|
||
fprintf_filtered (stream, ") ");
|
||
fputs_filtered (paddress (gdbarch, addr), stream);
|
||
}
|
||
else
|
||
{
|
||
val_print_type_code_int (type, valaddr + offset_aligned, stream);
|
||
if (ada_is_character_type (type))
|
||
{
|
||
LONGEST c;
|
||
|
||
fputs_filtered (" ", stream);
|
||
c = unpack_long (type, valaddr + offset_aligned);
|
||
ada_printchar (c, type, stream);
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|
||
case TYPE_CODE_ENUM:
|
||
{
|
||
unsigned int len;
|
||
LONGEST val;
|
||
|
||
if (options->format)
|
||
{
|
||
val_print_scalar_formatted (type, valaddr, offset_aligned,
|
||
original_value, options, 0, stream);
|
||
break;
|
||
}
|
||
len = TYPE_NFIELDS (type);
|
||
val = unpack_long (type, valaddr + offset_aligned);
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
QUIT;
|
||
if (val == TYPE_FIELD_ENUMVAL (type, i))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if (i < len)
|
||
{
|
||
const char *name = ada_enum_name (TYPE_FIELD_NAME (type, i));
|
||
|
||
if (name[0] == '\'')
|
||
fprintf_filtered (stream, "%ld %s", (long) val, name);
|
||
else
|
||
fputs_filtered (name, stream);
|
||
}
|
||
else
|
||
{
|
||
print_longest (stream, 'd', 0, val);
|
||
}
|
||
break;
|
||
}
|
||
|
||
case TYPE_CODE_FLT:
|
||
if (options->format)
|
||
{
|
||
c_val_print (type, valaddr, offset, address, stream,
|
||
recurse, original_value, options);
|
||
return;
|
||
}
|
||
else
|
||
ada_print_floating (valaddr + offset, type, stream);
|
||
break;
|
||
|
||
case TYPE_CODE_UNION:
|
||
case TYPE_CODE_STRUCT:
|
||
if (ada_is_bogus_array_descriptor (type))
|
||
{
|
||
fprintf_filtered (stream, "(...?)");
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
print_record (type, valaddr, offset_aligned,
|
||
stream, recurse, original_value, options);
|
||
return;
|
||
}
|
||
|
||
case TYPE_CODE_ARRAY:
|
||
ada_val_print_array (type, valaddr, offset_aligned,
|
||
address, stream, recurse, original_value,
|
||
options);
|
||
return;
|
||
|
||
case TYPE_CODE_REF:
|
||
/* For references, the debugger is expected to print the value as
|
||
an address if DEREF_REF is null. But printing an address in place
|
||
of the object value would be confusing to an Ada programmer.
|
||
So, for Ada values, we print the actual dereferenced value
|
||
regardless. */
|
||
elttype = check_typedef (TYPE_TARGET_TYPE (type));
|
||
|
||
if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
|
||
{
|
||
CORE_ADDR deref_val_int;
|
||
struct value *deref_val;
|
||
|
||
deref_val = coerce_ref_if_computed (original_value);
|
||
if (deref_val)
|
||
{
|
||
if (ada_is_tagged_type (value_type (deref_val), 1))
|
||
deref_val = ada_tag_value_at_base_address (deref_val);
|
||
|
||
common_val_print (deref_val, stream, recurse + 1, options,
|
||
current_language);
|
||
break;
|
||
}
|
||
|
||
deref_val_int = unpack_pointer (type, valaddr + offset_aligned);
|
||
if (deref_val_int != 0)
|
||
{
|
||
deref_val =
|
||
ada_value_ind (value_from_pointer
|
||
(lookup_pointer_type (elttype),
|
||
deref_val_int));
|
||
|
||
if (ada_is_tagged_type (value_type (deref_val), 1))
|
||
deref_val = ada_tag_value_at_base_address (deref_val);
|
||
|
||
val_print (value_type (deref_val),
|
||
value_contents_for_printing (deref_val),
|
||
value_embedded_offset (deref_val),
|
||
value_address (deref_val), stream, recurse + 1,
|
||
deref_val, options, current_language);
|
||
}
|
||
else
|
||
fputs_filtered ("(null)", stream);
|
||
}
|
||
else
|
||
fputs_filtered ("???", stream);
|
||
|
||
break;
|
||
}
|
||
gdb_flush (stream);
|
||
}
|
||
|
||
static int
|
||
print_variant_part (struct type *type, int field_num,
|
||
const gdb_byte *valaddr, int offset,
|
||
struct ui_file *stream, int recurse,
|
||
const struct value *val,
|
||
const struct value_print_options *options,
|
||
int comma_needed,
|
||
struct type *outer_type, int outer_offset)
|
||
{
|
||
struct type *var_type = TYPE_FIELD_TYPE (type, field_num);
|
||
int which = ada_which_variant_applies (var_type, outer_type,
|
||
valaddr + outer_offset);
|
||
|
||
if (which < 0)
|
||
return 0;
|
||
else
|
||
return print_field_values
|
||
(TYPE_FIELD_TYPE (var_type, which),
|
||
valaddr,
|
||
offset + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT
|
||
+ TYPE_FIELD_BITPOS (var_type, which) / HOST_CHAR_BIT,
|
||
stream, recurse, val, options,
|
||
comma_needed, outer_type, outer_offset);
|
||
}
|
||
|
||
void
|
||
ada_value_print (struct value *val0, struct ui_file *stream,
|
||
const struct value_print_options *options)
|
||
{
|
||
struct value *val = ada_to_fixed_value (val0);
|
||
CORE_ADDR address = value_address (val);
|
||
struct type *type = ada_check_typedef (value_type (val));
|
||
struct value_print_options opts;
|
||
|
||
/* If it is a pointer, indicate what it points to. */
|
||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||
{
|
||
/* Hack: don't print (char *) for char strings. Their
|
||
type is indicated by the quoted string anyway. */
|
||
if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) != sizeof (char)
|
||
|| TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_INT
|
||
|| TYPE_UNSIGNED (TYPE_TARGET_TYPE (type)))
|
||
{
|
||
fprintf_filtered (stream, "(");
|
||
type_print (type, "", stream, -1);
|
||
fprintf_filtered (stream, ") ");
|
||
}
|
||
}
|
||
else if (ada_is_array_descriptor_type (type))
|
||
{
|
||
/* We do not print the type description unless TYPE is an array
|
||
access type (this is encoded by the compiler as a typedef to
|
||
a fat pointer - hence the check against TYPE_CODE_TYPEDEF). */
|
||
if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
|
||
{
|
||
fprintf_filtered (stream, "(");
|
||
type_print (type, "", stream, -1);
|
||
fprintf_filtered (stream, ") ");
|
||
}
|
||
}
|
||
else if (ada_is_bogus_array_descriptor (type))
|
||
{
|
||
fprintf_filtered (stream, "(");
|
||
type_print (type, "", stream, -1);
|
||
fprintf_filtered (stream, ") (...?)");
|
||
return;
|
||
}
|
||
|
||
opts = *options;
|
||
opts.deref_ref = 1;
|
||
val_print (type, value_contents_for_printing (val),
|
||
value_embedded_offset (val), address,
|
||
stream, 0, val, &opts, current_language);
|
||
}
|
||
|
||
static void
|
||
print_record (struct type *type, const gdb_byte *valaddr,
|
||
int offset,
|
||
struct ui_file *stream, int recurse,
|
||
const struct value *val,
|
||
const struct value_print_options *options)
|
||
{
|
||
type = ada_check_typedef (type);
|
||
|
||
fprintf_filtered (stream, "(");
|
||
|
||
if (print_field_values (type, valaddr, offset,
|
||
stream, recurse, val, options,
|
||
0, type, offset) != 0 && options->prettyformat)
|
||
{
|
||
fprintf_filtered (stream, "\n");
|
||
print_spaces_filtered (2 * recurse, stream);
|
||
}
|
||
|
||
fprintf_filtered (stream, ")");
|
||
}
|
||
|
||
/* Print out fields of value at VALADDR + OFFSET having structure type TYPE.
|
||
|
||
TYPE, VALADDR, OFFSET, STREAM, RECURSE, and OPTIONS have the same
|
||
meanings as in ada_print_value and ada_val_print.
|
||
|
||
OUTER_TYPE and OUTER_OFFSET give type and address of enclosing
|
||
record (used to get discriminant values when printing variant
|
||
parts).
|
||
|
||
COMMA_NEEDED is 1 if fields have been printed at the current recursion
|
||
level, so that a comma is needed before any field printed by this
|
||
call.
|
||
|
||
Returns 1 if COMMA_NEEDED or any fields were printed. */
|
||
|
||
static int
|
||
print_field_values (struct type *type, const gdb_byte *valaddr,
|
||
int offset, struct ui_file *stream, int recurse,
|
||
const struct value *val,
|
||
const struct value_print_options *options,
|
||
int comma_needed,
|
||
struct type *outer_type, int outer_offset)
|
||
{
|
||
int i, len;
|
||
|
||
len = TYPE_NFIELDS (type);
|
||
|
||
for (i = 0; i < len; i += 1)
|
||
{
|
||
if (ada_is_ignored_field (type, i))
|
||
continue;
|
||
|
||
if (ada_is_wrapper_field (type, i))
|
||
{
|
||
comma_needed =
|
||
print_field_values (TYPE_FIELD_TYPE (type, i),
|
||
valaddr,
|
||
(offset
|
||
+ TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT),
|
||
stream, recurse, val, options,
|
||
comma_needed, type, offset);
|
||
continue;
|
||
}
|
||
else if (ada_is_variant_part (type, i))
|
||
{
|
||
comma_needed =
|
||
print_variant_part (type, i, valaddr,
|
||
offset, stream, recurse, val,
|
||
options, comma_needed,
|
||
outer_type, outer_offset);
|
||
continue;
|
||
}
|
||
|
||
if (comma_needed)
|
||
fprintf_filtered (stream, ", ");
|
||
comma_needed = 1;
|
||
|
||
if (options->prettyformat)
|
||
{
|
||
fprintf_filtered (stream, "\n");
|
||
print_spaces_filtered (2 + 2 * recurse, stream);
|
||
}
|
||
else
|
||
{
|
||
wrap_here (n_spaces (2 + 2 * recurse));
|
||
}
|
||
|
||
annotate_field_begin (TYPE_FIELD_TYPE (type, i));
|
||
fprintf_filtered (stream, "%.*s",
|
||
ada_name_prefix_len (TYPE_FIELD_NAME (type, i)),
|
||
TYPE_FIELD_NAME (type, i));
|
||
annotate_field_name_end ();
|
||
fputs_filtered (" => ", stream);
|
||
annotate_field_value ();
|
||
|
||
if (TYPE_FIELD_PACKED (type, i))
|
||
{
|
||
struct value *v;
|
||
|
||
/* Bitfields require special handling, especially due to byte
|
||
order problems. */
|
||
if (HAVE_CPLUS_STRUCT (type) && TYPE_FIELD_IGNORE (type, i))
|
||
{
|
||
fputs_filtered (_("<optimized out or zero length>"), stream);
|
||
}
|
||
else
|
||
{
|
||
int bit_pos = TYPE_FIELD_BITPOS (type, i);
|
||
int bit_size = TYPE_FIELD_BITSIZE (type, i);
|
||
struct value_print_options opts;
|
||
|
||
adjust_type_signedness (TYPE_FIELD_TYPE (type, i));
|
||
v = ada_value_primitive_packed_val
|
||
(NULL, valaddr,
|
||
offset + bit_pos / HOST_CHAR_BIT,
|
||
bit_pos % HOST_CHAR_BIT,
|
||
bit_size, TYPE_FIELD_TYPE (type, i));
|
||
opts = *options;
|
||
opts.deref_ref = 0;
|
||
val_print (TYPE_FIELD_TYPE (type, i),
|
||
value_contents_for_printing (v),
|
||
value_embedded_offset (v), 0,
|
||
stream, recurse + 1, v,
|
||
&opts, current_language);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
struct value_print_options opts = *options;
|
||
|
||
opts.deref_ref = 0;
|
||
ada_val_print (TYPE_FIELD_TYPE (type, i),
|
||
valaddr,
|
||
(offset
|
||
+ TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT),
|
||
0, stream, recurse + 1, val, &opts);
|
||
}
|
||
annotate_field_end ();
|
||
}
|
||
|
||
return comma_needed;
|
||
}
|