diff options
author | Fred Fish <fnf@specifix.com> | 1992-12-18 20:21:32 +0000 |
---|---|---|
committer | Fred Fish <fnf@specifix.com> | 1992-12-18 20:21:32 +0000 |
commit | a8a69e6332cc7f83a608af394e757e00355f5550 (patch) | |
tree | 3cab52bf4425a2e1c821aeaeb9e61bb1db910962 | |
parent | 6c1cabd48fce2d5014ec869c477b4a8756332f42 (diff) | |
download | gdb-a8a69e6332cc7f83a608af394e757e00355f5550.zip gdb-a8a69e6332cc7f83a608af394e757e00355f5550.tar.gz gdb-a8a69e6332cc7f83a608af394e757e00355f5550.tar.bz2 |
* Makefile.in (VERSION): Bump to 4.7.4.
* Makefile.in (SFILES_MAINDIR): Add typeprint.c, c-typeprint.c,
m2-typeprint.c, c-valprint.c cp-valprint.c m2-valprint.c.
* Makefile.in (HFILES): Add valprint.h.
* Makefile.in (OBS): Add typeprint.o, c-typeprint.o,
m2-typeprint.o, c-valprint.o, cp-valprint.o m2-valprint.o.
* typeprint.c, typeprint.h: New files for language independent
type printing functions.
* c-typeprint.c, m2-typeprint.c: New files for language dependent
type printing functions and definitions.
* valprint.h: New include file for language independent value
printing definitions.
* c-valprint.c, cp-valprint.c, m2-valprint.c: New files for language
dependent value printing functions.
* c-exp.y (production ptype): Add range_type variable and use new
create_range_type function.
* c-exp.y (tokentab2, tokentab3), c-lang.c (c_op_print_tab),
infcmd.c (path_var_name), language.c (unk_op_print_tab),
m2-lang.c (m2_op_print_tab): Change from ANSI-obsolescent
"const static" to ANSI-conformant "static const".
* c-exp.y (c_create_fundamental_type): Remove unused nbytes.
* c-exp.y (c_language_defn, cplus_language_defn): Add c_print_type,
and c_val_print.
* c-lang.h (c_print_type, c_val_print): Add prototypes.
* coffread.c (decode_type): Add range_type variable and call to
new create_range_type function.
* complaints.c (complain): Remove unused val variable.
* complaints.c (_initialize_complaints): Make it void.
* convex-tdep.c (value_of_trapped_internalvar): Add range_type
variable and call new create_range_type function.
* defs.h (enum val_prettyprint): Move enum from value.h to here
so we can avoid having to include value.h just for prototypes that
need the enum (thanks ANSI).
* dwarfread.c (struct_type): Local anonymous_size variable is
only used if !BITS_BIG_ENDIAN.
* dwarfread.c (decode_subscript_data_item): Add rangetype
variable and call new create_range_type function.
* elfread.c (elf_symfile_read): Remove unused dbx and text_sect
variables.
* eval.c (evaluate_subexp): Remove unused local variable name
and the statement with no side effects that initializes it.
* expprint.c (print_subexp): Change local_printstr to
LA_PRINT_STRING.
* gdbtypes.c (create_range_type): New function that creates
a range type using code fragments from object file readers as
an example of what has to be initialized.
* gdbtypes.c (create_array_type): Removed index_type, low_bound,
and high_bound parameters, replaced with a single range_type
parameter. Change function body to use passed in range_type
rather than handcrafting one.
* gdbtypes.h (create_range_type): Add prototype.
* gdbtypes.h (create_array_type): Change prototype parameters.
* infrun.c (normal_stop): Remove unused local variables tem and c.
* infrun.c (hook_stop_stub): Return 0 rather than random value.
* language.c (unk_lang_print_type, unk_lang_val_print): Add
stub functions that call error if called.
* language.c (unknown_language_defn, auto_language_defn,
local_language_defn): Add initializers unk_lang_print_type and
unk_lang_val_print.
* language.h (struct language_defn): Reformat for larger
comments, add la_print_type and la_val_print members. Add
LA_PRINT_TYPE and LA_VAL_PRINT macros. Change local_printchar
to LA_PRINT_CHAR and local_printstr to LA_PRINT_STRING.
* m2-lang.c (m2_create_fundamental_type): Remove unused local
variable nbytes.
* m2-lang.c (m2_language_defn): Add initializers m2_print_type
and m2_val_print.
* m2-lang.h (m2_print_type, m2_val_print): Add prototypes.
* main.c (execute_command): Remove unused local variable cmdlines.
* main.c (echo_command), stabsread.c (read_type), printcmd.c
(clear_displays), symmisc.c (block_depth), values.c
(clear_value_history):
Make testing of truth value of assignment result explicit.
* mipsread.c (upgrade_type): Update FIXME to include future use
of create_range_type.
* printcmd.c (ptype_command, ptype_eval, whatis_command,
whatis_exp, maintenance_print_type): Move prototypes and functions
to new typeprint.c.
* printcmd.c (_initialize_printcmd): Move add_com calls for
ptype_command and whatis_command to new typeprint.c.
* ser-bsd.c (serial_open): Remove unused variable sgttyb.
* source.c (find_source_lines): Local variable c only used
when LSEEK_NOT_LINEAR is defined.
* stabsread.c (read_array_type): Use new create_range_type
function.
* stabsread.c (read_range_type): Add new index_type variable and
call new create_range_type function rather than handcrafting
range types.
* symmisc.c (type_print_1): Change usages to LA_PRINT_TYPE.
* symtab.c (typedef_print usages): Use c_typedef_print, renamed.
* symtab.c (type_print_base usages): Use c_type_print_base.
* symtab.c (type_print_varspec_prefix usages): Use
c_type_print_varspec_prefix.
* symtab.c (type_print_method_args usages): Use
cp_type_print_method_args.
* valprint.c: Completely ripped apart and the fragments used
to create c-valprint.c, cp-valprint.c, m2-valprint.c, and
valprint.h. Remaining stuff is language independent.
* value.h (struct fn_field): Forward declare for prototypes.
* value.h (type_print_1): Remove prototype.
* value.h (enum val_prettyprint): Moved to defs.h.
* value.h (typedef_print): Prototype renamed to c_typedef_print.
* value.h (baseclass_offset): Add prototype.
**** start-sanitize-chill ****
* Makefile.in (SFILES_MAINDIR): Add ch-typeprint.c, ch-valprint.c.
* Makefile.in (OBS): Add ch-typeprint.o, ch-valprint.o.
* ch-typeprint.c: New file for language dependent type printing.
* ch-valprint.c: New file for language dependent value printing.
* ch-exp.y (parse_number): Remove prototype and stub function.
* ch-exp.y (decode_integer_literal): Removed unused digits and
temp variables.
* ch-exp.y (convert_float): Completely ifdef out for now.
* ch-exp.y (tokentab2, tokentab3, tokentab4, tokentab5),
ch-lang.c (chill_op_print_tab):
Change from ANSI-obsolescent "const static" to ANSI-conformant
"static const".
* ch-exp.y (yylex): Add unhandled storage class enumeration
literals to switch statement for completeness.
* ch-lang.c (chill_create_fundamental_types): Remove unused
nbytes variable. Change dummy type to 2 bytes to match int.
Handle FT_VOID types gratuituously added to chill DWARF by
compiler. Change FT_CHAR case to generate an TYPE_CODE_CHAR
type rather than a one byte TYPE_CODE_INT type.
* ch-lang.c (chill_language_defn): Add chill_print_type and
chill_val_print.
* ch-lang.h (chill_print_type, chill_val_print): Add prototypes.
**** end-sanitize-chill ****
45 files changed, 3358 insertions, 2103 deletions
diff --git a/gdb/.Sanitize b/gdb/.Sanitize index 28ebf29..8cd5d48 100644 --- a/gdb/.Sanitize +++ b/gdb/.Sanitize @@ -16,7 +16,7 @@ Do-first: if ( echo $* | grep keep\-chill > /dev/null ) ; then - keep_these_too="ch-exp.y ch-lang.c ch-lang.h" + keep_these_too="ch-exp.y ch-lang.c ch-lang.h ch-typeprint.c ch-valprint.c" fi # All files listed between the "Things-to-keep:" line and the @@ -57,6 +57,8 @@ buildsym.h c-exp.y c-lang.c c-lang.h +c-typeprint.c +c-valprint.c call-cmds.h coffread.c command.c @@ -74,6 +76,7 @@ copying.c core.c coredep.c corelow.c +cp-valprint.c createtags dbxread.c defs.h @@ -135,6 +138,8 @@ language.h m2-exp.y m2-lang.c m2-lang.h +m2-typeprint.c +m2-valprint.c m68k-pinsn.c m68k-stub.c m68k-tdep.c @@ -298,6 +303,8 @@ tm-umax.h tm-vax.h tm-vx68.h tm-vx960.h +typeprint.c +typeprint.h ultra3-nat.c ultra3-xdep.c umax-xdep.c @@ -305,6 +312,7 @@ utils.c valarith.c valops.c valprint.c +valprint.h value.h values.c vax-pinsn.c @@ -400,6 +408,10 @@ else -e 's/ch-lang.h//g' \ -e 's/ch-lang.c//g' \ -e 's/ch-lang.o//g' \ + -e 's/ch-typeprint.c//g' \ + -e 's/ch-typeprint.o//g' \ + -e 's/ch-valprint.c//g' \ + -e 's/ch-valprint.o//g' \ < Makefile.in > new if [ -n "${safe}" -a ! -f .Recover/Makefile.in ] ; then echo Caching Makefile.in in .Recover... diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7992c75..bfb1cba 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,133 @@ +Fri Dec 18 10:32:25 1992 Fred Fish (fnf@cygnus.com) + + * Makefile.in (VERSION): Bump to 4.7.4. + * Makefile.in (SFILES_MAINDIR): Add typeprint.c, c-typeprint.c, + m2-typeprint.c, c-valprint.c cp-valprint.c m2-valprint.c. + * Makefile.in (HFILES): Add valprint.h. + * Makefile.in (OBS): Add typeprint.o, c-typeprint.o, + m2-typeprint.o, c-valprint.o, cp-valprint.o m2-valprint.o. + * typeprint.c, typeprint.h: New files for language independent + type printing functions. + * c-typeprint.c, m2-typeprint.c: New files for language dependent + type printing functions and definitions. + * valprint.h: New include file for language independent value + printing definitions. + * c-valprint.c, cp-valprint.c, m2-valprint.c: New files for language + dependent value printing functions. + * c-exp.y (production ptype): Add range_type variable and use new + create_range_type function. + * c-exp.y (tokentab2, tokentab3), c-lang.c (c_op_print_tab), + infcmd.c (path_var_name), language.c (unk_op_print_tab), + m2-lang.c (m2_op_print_tab): Change from ANSI-obsolescent + "const static" to ANSI-conformant "static const". + * c-exp.y (c_create_fundamental_type): Remove unused nbytes. + * c-exp.y (c_language_defn, cplus_language_defn): Add c_print_type, + and c_val_print. + * c-lang.h (c_print_type, c_val_print): Add prototypes. + * coffread.c (decode_type): Add range_type variable and call to + new create_range_type function. + * complaints.c (complain): Remove unused val variable. + * complaints.c (_initialize_complaints): Make it void. + * convex-tdep.c (value_of_trapped_internalvar): Add range_type + variable and call new create_range_type function. + * defs.h (enum val_prettyprint): Move enum from value.h to here + so we can avoid having to include value.h just for prototypes that + need the enum (thanks ANSI). + * dwarfread.c (struct_type): Local anonymous_size variable is + only used if !BITS_BIG_ENDIAN. + * dwarfread.c (decode_subscript_data_item): Add rangetype + variable and call new create_range_type function. + * elfread.c (elf_symfile_read): Remove unused dbx and text_sect + variables. + * eval.c (evaluate_subexp): Remove unused local variable name + and the statement with no side effects that initializes it. + * expprint.c (print_subexp): Change local_printstr to + LA_PRINT_STRING. + * gdbtypes.c (create_range_type): New function that creates + a range type using code fragments from object file readers as + an example of what has to be initialized. + * gdbtypes.c (create_array_type): Removed index_type, low_bound, + and high_bound parameters, replaced with a single range_type + parameter. Change function body to use passed in range_type + rather than handcrafting one. + * gdbtypes.h (create_range_type): Add prototype. + * gdbtypes.h (create_array_type): Change prototype parameters. + * infrun.c (normal_stop): Remove unused local variables tem and c. + * infrun.c (hook_stop_stub): Return 0 rather than random value. + * language.c (unk_lang_print_type, unk_lang_val_print): Add + stub functions that call error if called. + * language.c (unknown_language_defn, auto_language_defn, + local_language_defn): Add initializers unk_lang_print_type and + unk_lang_val_print. + * language.h (struct language_defn): Reformat for larger + comments, add la_print_type and la_val_print members. Add + LA_PRINT_TYPE and LA_VAL_PRINT macros. Change local_printchar + to LA_PRINT_CHAR and local_printstr to LA_PRINT_STRING. + * m2-lang.c (m2_create_fundamental_type): Remove unused local + variable nbytes. + * m2-lang.c (m2_language_defn): Add initializers m2_print_type + and m2_val_print. + * m2-lang.h (m2_print_type, m2_val_print): Add prototypes. + * main.c (execute_command): Remove unused local variable cmdlines. + * main.c (echo_command), stabsread.c (read_type), printcmd.c + (clear_displays), symmisc.c (block_depth), values.c + (clear_value_history): + Make testing of truth value of assignment result explicit. + * mipsread.c (upgrade_type): Update FIXME to include future use + of create_range_type. + * printcmd.c (ptype_command, ptype_eval, whatis_command, + whatis_exp, maintenance_print_type): Move prototypes and functions + to new typeprint.c. + * printcmd.c (_initialize_printcmd): Move add_com calls for + ptype_command and whatis_command to new typeprint.c. + * ser-bsd.c (serial_open): Remove unused variable sgttyb. + * source.c (find_source_lines): Local variable c only used + when LSEEK_NOT_LINEAR is defined. + * stabsread.c (read_array_type): Use new create_range_type + function. + * stabsread.c (read_range_type): Add new index_type variable and + call new create_range_type function rather than handcrafting + range types. + * symmisc.c (type_print_1): Change usages to LA_PRINT_TYPE. + * symtab.c (typedef_print usages): Use c_typedef_print, renamed. + * symtab.c (type_print_base usages): Use c_type_print_base. + * symtab.c (type_print_varspec_prefix usages): Use + c_type_print_varspec_prefix. + * symtab.c (type_print_method_args usages): Use + cp_type_print_method_args. + * valprint.c: Completely ripped apart and the fragments used + to create c-valprint.c, cp-valprint.c, m2-valprint.c, and + valprint.h. Remaining stuff is language independent. + * value.h (struct fn_field): Forward declare for prototypes. + * value.h (type_print_1): Remove prototype. + * value.h (enum val_prettyprint): Moved to defs.h. + * value.h (typedef_print): Prototype renamed to c_typedef_print. + * value.h (baseclass_offset): Add prototype. + **** start-sanitize-chill **** + * Makefile.in (SFILES_MAINDIR): Add ch-typeprint.c, ch-valprint.c. + * Makefile.in (OBS): Add ch-typeprint.o, ch-valprint.o. + * ch-typeprint.c: New file for language dependent type printing. + * ch-valprint.c: New file for language dependent value printing. + * ch-exp.y (parse_number): Remove prototype and stub function. + * ch-exp.y (decode_integer_literal): Removed unused digits and + temp variables. + * ch-exp.y (convert_float): Completely ifdef out for now. + * ch-exp.y (tokentab2, tokentab3, tokentab4, tokentab5), + ch-lang.c (chill_op_print_tab): + Change from ANSI-obsolescent "const static" to ANSI-conformant + "static const". + * ch-exp.y (yylex): Add unhandled storage class enumeration + literals to switch statement for completeness. + * ch-lang.c (chill_create_fundamental_types): Remove unused + nbytes variable. Change dummy type to 2 bytes to match int. + Handle FT_VOID types gratuituously added to chill DWARF by + compiler. Change FT_CHAR case to generate an TYPE_CODE_CHAR + type rather than a one byte TYPE_CODE_INT type. + * ch-lang.c (chill_language_defn): Add chill_print_type and + chill_val_print. + * ch-lang.h (chill_print_type, chill_val_print): Add prototypes. + **** end-sanitize-chill **** + Thu Dec 17 00:44:57 1992 John Gilmore (gnu@cygnus.com) Eliminate uses of NAMES_HAVE_UNDERSCORE, using diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 84dac05..1c75f09 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -166,7 +166,7 @@ CDEPS = ${XM_CDEPS} ${TM_CDEPS} ${NAT_CDEPS} \ ADD_FILES = ${REGEX} ${ALLOCA} ${XM_ADD_FILES} ${TM_ADD_FILES} ${NAT_ADD_FILES} ADD_DEPS = ${REGEX1} ${ALLOCA1} ${XM_ADD_FILES} ${TM_ADD_FILES} ${NAT_ADD_FILES} -VERSION = 4.7.3 +VERSION = 4.7.4 DIST=gdb LINT=/usr/5bin/lint @@ -202,7 +202,8 @@ SFILES_MAINDIR = \ dbxread.c coffread.c elfread.c dwarfread.c xcoffread.c stabsread.c \ ieee-float.c language.c parse.c buildsym.c objfiles.c \ minsyms.c mipsread.c maint.c ch-exp.y c-lang.c ch-lang.c m2-lang.c \ - complaints.c + complaints.c typeprint.c c-typeprint.c ch-typeprint.c m2-typeprint.c \ + c-valprint.c cp-valprint.c ch-valprint.c m2-valprint.c # Source files in subdirectories (which will be handled separately by # 'make gdb.tar.Z'). @@ -263,7 +264,8 @@ HFILES= breakpoint.h buildsym.h call-cmds.h command.h defs.h \ nm-sun2.h nm-sun3.h nm-sun386.h nm-sun4os4.h nm-trash.h \ nm-ultra3.h nm-hppab.h nm-hppah.h nm-umax.h nm-sysv4.h \ nm-apollo68b.h nm-apollo68v.h nm-vax.h nm-hp300bsd.h \ - nm-hp300hpux.h c-lang.h ch-lang.h m2-lang.h complaints.h + nm-hp300hpux.h c-lang.h ch-lang.h m2-lang.h complaints.h \ + valprint.h REMOTE_EXAMPLES = m68k-stub.c i386-stub.c sparc-stub.c rem-multi.shar @@ -303,7 +305,9 @@ OBS = version.o main.o blockframe.o breakpoint.o findvar.o stack.o source.o \ ieee-float.o putenv.o parse.o language.o $(YYOBJ) \ buildsym.o objfiles.o minsyms.o maint.o demangle.o \ dbxread.o coffread.o elfread.o dwarfread.o xcoffread.o mipsread.o \ - stabsread.o core.o c-lang.o ch-lang.o m2-lang.o complaints.o + stabsread.o core.o c-lang.o ch-lang.o m2-lang.o complaints.o \ + typeprint.o c-typeprint.o ch-typeprint.o m2-typeprint.o \ + c-valprint.o cp-valprint.o ch-valprint.o m2-valprint.o RAPP_OBS = rgdb.o rudp.o rserial.o serial.o udp.o $(XDEPFILES) diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 8273f6a..8d77232 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -705,6 +705,7 @@ ptype : typebase int done = 0; int array_size; struct type *follow_type = $1; + struct type *range_type; while (!done) switch (pop_type ()) @@ -721,10 +722,15 @@ ptype : typebase case tp_array: array_size = pop_type_int (); if (array_size != -1) - follow_type = - create_array_type ((struct type *) NULL, - follow_type, builtin_type_int, - 0, array_size - 1); + { + range_type = + create_range_type ((struct type *) NULL, + builtin_type_int, 0, + array_size - 1); + follow_type = + create_array_type ((struct type *) NULL, + follow_type, range_type); + } else follow_type = lookup_pointer_type (follow_type); break; @@ -1039,13 +1045,13 @@ struct token enum exp_opcode opcode; }; -const static struct token tokentab3[] = +static const struct token tokentab3[] = { {">>=", ASSIGN_MODIFY, BINOP_RSH}, {"<<=", ASSIGN_MODIFY, BINOP_LSH} }; -const static struct token tokentab2[] = +static const struct token tokentab2[] = { {"+=", ASSIGN_MODIFY, BINOP_ADD}, {"-=", ASSIGN_MODIFY, BINOP_SUB}, diff --git a/gdb/c-lang.c b/gdb/c-lang.c index bdeb8c7..5aa48a2 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -211,7 +211,6 @@ c_create_fundamental_type (objfile, typeid) int typeid; { register struct type *type = NULL; - register int nbytes; switch (typeid) { @@ -328,7 +327,7 @@ c_create_fundamental_type (objfile, typeid) /* Table mapping opcodes into strings for printing operators and precedences of the operators. */ -const static struct op_print c_op_print_tab[] = +static const struct op_print c_op_print_tab[] = { {",", BINOP_COMMA, PREC_COMMA, 0}, {"=", BINOP_ASSIGN, PREC_ASSIGN, 1}, @@ -418,6 +417,8 @@ const struct language_defn c_language_defn = { c_printchar, /* Print a character constant */ c_printstr, /* Function to print string constant */ c_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ &builtin_type_double, /* longest floating point type */ /*FIXME*/ @@ -440,6 +441,8 @@ const struct language_defn cplus_language_defn = { c_printchar, /* Print a character constant */ c_printstr, /* Function to print string constant */ c_create_fundamental_type, /* Create fundamental type in this language */ + c_print_type, /* Print a type using appropriate syntax */ + c_val_print, /* Print a value using appropriate syntax */ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ &builtin_type_double, /* longest floating point type */ /*FIXME*/ diff --git a/gdb/c-lang.h b/gdb/c-lang.h index 5a1661f..4c343a9 100644 --- a/gdb/c-lang.h +++ b/gdb/c-lang.h @@ -22,3 +22,10 @@ c_parse PARAMS ((void)); /* Defined in c-exp.y */ extern void c_error PARAMS ((char *)); /* Defined in c-exp.y */ + +extern void /* Defined in c-typeprint.c */ +c_print_type PARAMS ((struct type *, char *, FILE *, int, int)); + +extern int +c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, + int, enum val_prettyprint)); diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c new file mode 100644 index 0000000..503c22e --- /dev/null +++ b/gdb/c-typeprint.c @@ -0,0 +1,774 @@ +/* Support for printing C and C++ types for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "bfd.h" /* Binary File Description */ +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "value.h" +#include "gdbcore.h" +#include "target.h" +#include "command.h" +#include "gdbcmd.h" +#include "language.h" +#include "demangle.h" +#include "c-lang.h" +#include "typeprint.h" + +#include <string.h> +#include <errno.h> + +extern int demangle; /* whether to print C++ syms raw or source-form */ + +static void +c_type_print_args PARAMS ((struct type *, FILE *)); + +static void +c_type_print_varspec_suffix PARAMS ((struct type *, FILE *, int, int, int)); + +static void +cp_type_print_derivation_info PARAMS ((FILE *, struct type *)); + +void +c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); + +void +c_type_print_base PARAMS ((struct type *, FILE *, int, int)); + + +/* Print a description of a type in the format of a + typedef for the current language. + NEW is the new name for a type TYPE. */ + +void +c_typedef_print (type, new, stream) + struct type *type; + struct symbol *new; + FILE *stream; +{ + switch (current_language->la_language) + { +#ifdef _LANG_c + case language_c: + case language_cplus: + fprintf_filtered(stream, "typedef "); + type_print(type,"",stream,0); + if(TYPE_NAME ((SYMBOL_TYPE (new))) == 0 + || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (new))), + SYMBOL_NAME (new))) + fprintf_filtered(stream, " %s", SYMBOL_NAME(new)); + break; +#endif +#ifdef _LANG_m2 + case language_m2: + fprintf_filtered(stream, "TYPE "); + if(!TYPE_NAME(SYMBOL_TYPE(new)) || + strcmp (TYPE_NAME(SYMBOL_TYPE(new)), + SYMBOL_NAME(new))) + fprintf_filtered(stream, "%s = ", SYMBOL_NAME(new)); + else + fprintf_filtered(stream, "<builtin> = "); + type_print(type,"",stream,0); + break; +#endif +/* start-sanitize-chill */ +#ifdef _LANG_chill + case language_chill: + error ("Missing Chill support in function c_typedef_print."); /*FIXME*/ +#endif +/* end-sanitize-chill */ + default: + error("Language not supported."); + } + fprintf_filtered(stream, ";\n"); +} + + +/* LEVEL is the depth to indent lines by. */ + +void +c_print_type (type, varstring, stream, show, level) + struct type *type; + char *varstring; + FILE *stream; + int show; + int level; +{ + register enum type_code code; + char *demangled = NULL; + int demangled_args; + + c_type_print_base (type, stream, show, level); + code = TYPE_CODE (type); + if ((varstring != NULL && *varstring != '\0') + || + /* Need a space if going to print stars or brackets; + but not if we will print just a type name. */ + ((show > 0 || TYPE_NAME (type) == 0) + && + (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC + || code == TYPE_CODE_METHOD + || code == TYPE_CODE_ARRAY + || code == TYPE_CODE_MEMBER + || code == TYPE_CODE_REF))) + fputs_filtered (" ", stream); + c_type_print_varspec_prefix (type, stream, show, 0); + + /* See if the name has a C++ demangled equivalent, and if so, print that + instead. */ + + if (demangle) + { + demangled = cplus_demangle (varstring, DMGL_ANSI | DMGL_PARAMS); + } + fputs_filtered ((demangled != NULL) ? demangled : varstring, stream); + + /* For demangled function names, we have the arglist as part of the name, + so don't print an additional pair of ()'s */ + + demangled_args = (demangled != NULL) && (code == TYPE_CODE_FUNC); + c_type_print_varspec_suffix (type, stream, show, 0, demangled_args); + + if (demangled != NULL) + { + free (demangled); + } +} + +/* Print the C++ method arguments ARGS to the file STREAM. */ + +void +cp_type_print_method_args (args, prefix, varstring, staticp, stream) + struct type **args; + char *prefix; + char *varstring; + int staticp; + FILE *stream; +{ + int i; + + fputs_demangled (prefix, stream, DMGL_ANSI | DMGL_PARAMS); + fputs_demangled (varstring, stream, DMGL_ANSI | DMGL_PARAMS); + fputs_filtered (" (", stream); + if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID) + { + i = !staticp; /* skip the class variable */ + while (1) + { + type_print (args[i++], "", stream, 0); + if (!args[i]) + { + fprintf_filtered (stream, " ..."); + break; + } + else if (args[i]->code != TYPE_CODE_VOID) + { + fprintf_filtered (stream, ", "); + } + else break; + } + } + fprintf_filtered (stream, ")"); +} + +/* If TYPE is a derived type, then print out derivation information. + Print only the actual base classes of this type, not the base classes + of the base classes. I.E. for the derivation hierarchy: + + class A { int a; }; + class B : public A {int b; }; + class C : public B {int c; }; + + Print the type of class C as: + + class C : public B { + int c; + } + + Not as the following (like gdb used to), which is not legal C++ syntax for + derived types and may be confused with the multiple inheritance form: + + class C : public B : public A { + int c; + } + + In general, gdb should try to print the types as closely as possible to + the form that they appear in the source code. */ + +static void +cp_type_print_derivation_info (stream, type) + FILE *stream; + struct type *type; +{ + char *name; + int i; + + for (i = 0; i < TYPE_N_BASECLASSES (type); i++) + { + fputs_filtered (i == 0 ? ": " : ", ", stream); + fprintf_filtered (stream, "%s%s ", + BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private", + BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : ""); + name = type_name_no_tag (TYPE_BASECLASS (type, i)); + fprintf_filtered (stream, "%s", name ? name : "(null)"); + } + if (i > 0) + { + fputs_filtered (" ", stream); + } +} + +/* Print any asterisks or open-parentheses needed before the + variable name (to describe its type). + + On outermost call, pass 0 for PASSED_A_PTR. + On outermost call, SHOW > 0 means should ignore + any typename for TYPE and show its details. + SHOW is always zero on recursive calls. */ + +void +c_type_print_varspec_prefix (type, stream, show, passed_a_ptr) + struct type *type; + FILE *stream; + int show; + int passed_a_ptr; +{ + char *name; + if (type == 0) + return; + + if (TYPE_NAME (type) && show <= 0) + return; + + QUIT; + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_PTR: + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); + fprintf_filtered (stream, "*"); + break; + + case TYPE_CODE_MEMBER: + if (passed_a_ptr) + fprintf_filtered (stream, "("); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + fprintf_filtered (stream, " "); + name = type_name_no_tag (TYPE_DOMAIN_TYPE (type)); + if (name) + fputs_filtered (name, stream); + else + c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); + fprintf_filtered (stream, "::"); + break; + + case TYPE_CODE_METHOD: + if (passed_a_ptr) + fprintf (stream, "("); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + if (passed_a_ptr) + { + fprintf_filtered (stream, " "); + c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); + fprintf_filtered (stream, "::"); + } + break; + + case TYPE_CODE_REF: + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); + fprintf_filtered (stream, "&"); + break; + + case TYPE_CODE_FUNC: + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + if (passed_a_ptr) + fprintf_filtered (stream, "("); + break; + + case TYPE_CODE_ARRAY: + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + if (passed_a_ptr) + fprintf_filtered (stream, "("); + break; + + case TYPE_CODE_UNDEF: + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_ENUM: + case TYPE_CODE_INT: + case TYPE_CODE_FLT: + case TYPE_CODE_VOID: + case TYPE_CODE_ERROR: + case TYPE_CODE_CHAR: + case TYPE_CODE_BOOL: + case TYPE_CODE_SET: + case TYPE_CODE_RANGE: + case TYPE_CODE_PASCAL_ARRAY: + /* These types need no prefix. They are listed here so that + gcc -Wall will reveal any types that haven't been handled. */ + break; + } +} + +static void +c_type_print_args (type, stream) + struct type *type; + FILE *stream; +{ + int i; + struct type **args; + + fprintf_filtered (stream, "("); + args = TYPE_ARG_TYPES (type); + if (args != NULL) + { + if (args[1] == NULL) + { + fprintf_filtered (stream, "..."); + } + else + { + for (i = 1; + args[i] != NULL && args[i]->code != TYPE_CODE_VOID; + i++) + { + c_print_type (args[i], "", stream, -1, 0); + if (args[i+1] == NULL) + { + fprintf_filtered (stream, "..."); + } + else if (args[i+1]->code != TYPE_CODE_VOID) + { + fprintf_filtered (stream, ","); + wrap_here (" "); + } + } + } + } + fprintf_filtered (stream, ")"); +} + +/* Print any array sizes, function arguments or close parentheses + needed after the variable name (to describe its type). + Args work like c_type_print_varspec_prefix. */ + +static void +c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) + struct type *type; + FILE *stream; + int show; + int passed_a_ptr; + int demangled_args; +{ + if (type == 0) + return; + + if (TYPE_NAME (type) && show <= 0) + return; + + QUIT; + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + + fprintf_filtered (stream, "["); + if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) + fprintf_filtered (stream, "%d", + (TYPE_LENGTH (type) + / TYPE_LENGTH (TYPE_TARGET_TYPE (type)))); + fprintf_filtered (stream, "]"); + + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); + break; + + case TYPE_CODE_MEMBER: + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); + break; + + case TYPE_CODE_METHOD: + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); + if (passed_a_ptr) + { + c_type_print_args (type, stream); + } + break; + + case TYPE_CODE_PTR: + case TYPE_CODE_REF: + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0); + break; + + case TYPE_CODE_FUNC: + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, + passed_a_ptr, 0); + if (passed_a_ptr) + fprintf_filtered (stream, ")"); + if (!demangled_args) + fprintf_filtered (stream, "()"); + break; + + case TYPE_CODE_UNDEF: + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + case TYPE_CODE_ENUM: + case TYPE_CODE_INT: + case TYPE_CODE_FLT: + case TYPE_CODE_VOID: + case TYPE_CODE_ERROR: + case TYPE_CODE_CHAR: + case TYPE_CODE_BOOL: + case TYPE_CODE_SET: + case TYPE_CODE_RANGE: + case TYPE_CODE_PASCAL_ARRAY: + /* These types do not need a suffix. They are listed so that + gcc -Wall will report types that may not have been considered. */ + break; + } +} + +/* Print the name of the type (or the ultimate pointer target, + function value or array element), or the description of a + structure or union. + + SHOW nonzero means don't print this type as just its name; + show its real definition even if it has a name. + SHOW zero means print just typename or struct tag if there is one + SHOW negative means abbreviate structure elements. + SHOW is decremented for printing of structure elements. + + LEVEL is the depth to indent by. + We increase it for some recursive calls. */ + +void +c_type_print_base (type, stream, show, level) + struct type *type; + FILE *stream; + int show; + int level; +{ + char *name; + register int i; + register int len; + register int lastval; + char *mangled_name; + char *demangled_name; + enum {s_none, s_public, s_private, s_protected} section_type; + QUIT; + + wrap_here (" "); + if (type == NULL) + { + fputs_filtered ("<type unknown>", stream); + return; + } + + /* When SHOW is zero or less, and there is a valid type name, then always + just print the type name directly from the type. */ + + if ((show <= 0) && (TYPE_NAME (type) != NULL)) + { + fputs_filtered (TYPE_NAME (type), stream); + return; + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_PTR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_REF: + case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: + c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); + break; + + case TYPE_CODE_STRUCT: + fprintf_filtered (stream, + HAVE_CPLUS_STRUCT (type) ? "class " : "struct "); + goto struct_union; + + case TYPE_CODE_UNION: + fprintf_filtered (stream, "union "); + struct_union: + if ((name = type_name_no_tag (type)) != NULL) + { + fputs_filtered (name, stream); + fputs_filtered (" ", stream); + wrap_here (" "); + } + if (show < 0) + fprintf_filtered (stream, "{...}"); + else + { + check_stub_type (type); + + cp_type_print_derivation_info (stream, type); + + fprintf_filtered (stream, "{\n"); + if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) + { + if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) + fprintfi_filtered (level + 4, stream, "<incomplete type>\n"); + else + fprintfi_filtered (level + 4, stream, "<no data fields>\n"); + } + + /* Start off with no specific section type, so we can print + one for the first field we find, and use that section type + thereafter until we find another type. */ + + section_type = s_none; + + /* If there is a base class for this type, + do not print the field that it occupies. */ + + len = TYPE_NFIELDS (type); + for (i = TYPE_N_BASECLASSES (type); i < len; i++) + { + QUIT; + /* Don't print out virtual function table. */ + if ((TYPE_FIELD_NAME (type, i))[5] == CPLUS_MARKER && + !strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5)) + continue; + + /* If this is a C++ class we can print the various C++ section + labels. */ + + if (HAVE_CPLUS_STRUCT (type)) + { + if (TYPE_FIELD_PROTECTED (type, i)) + { + if (section_type != s_protected) + { + section_type = s_protected; + fprintfi_filtered (level + 2, stream, + "protected:\n"); + } + } + else if (TYPE_FIELD_PRIVATE (type, i)) + { + if (section_type != s_private) + { + section_type = s_private; + fprintfi_filtered (level + 2, stream, "private:\n"); + } + } + else + { + if (section_type != s_public) + { + section_type = s_public; + fprintfi_filtered (level + 2, stream, "public:\n"); + } + } + } + + print_spaces_filtered (level + 4, stream); + if (TYPE_FIELD_STATIC (type, i)) + { + fprintf_filtered (stream, "static "); + } + c_print_type (TYPE_FIELD_TYPE (type, i), + TYPE_FIELD_NAME (type, i), + stream, show - 1, level + 4); + if (!TYPE_FIELD_STATIC (type, i) + && TYPE_FIELD_PACKED (type, i)) + { + /* It is a bitfield. This code does not attempt + to look at the bitpos and reconstruct filler, + unnamed fields. This would lead to misleading + results if the compiler does not put out fields + for such things (I don't know what it does). */ + fprintf_filtered (stream, " : %d", + TYPE_FIELD_BITSIZE (type, i)); + } + fprintf_filtered (stream, ";\n"); + } + + /* If there are both fields and methods, put a space between. */ + len = TYPE_NFN_FIELDS (type); + if (len && section_type != s_none) + fprintf_filtered (stream, "\n"); + + /* C++: print out the methods */ + + for (i = 0; i < len; i++) + { + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); + int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); + char *method_name = TYPE_FN_FIELDLIST_NAME (type, i); + int is_constructor = name && strcmp(method_name, name) == 0; + for (j = 0; j < len2; j++) + { + QUIT; + if (TYPE_FN_FIELD_PROTECTED (f, j)) + { + if (section_type != s_protected) + { + section_type = s_protected; + fprintfi_filtered (level + 2, stream, + "protected:\n"); + } + } + else if (TYPE_FN_FIELD_PRIVATE (f, j)) + { + if (section_type != s_private) + { + section_type = s_private; + fprintfi_filtered (level + 2, stream, "private:\n"); + } + } + else + { + if (section_type != s_public) + { + section_type = s_public; + fprintfi_filtered (level + 2, stream, "public:\n"); + } + } + + print_spaces_filtered (level + 4, stream); + if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) + fprintf_filtered (stream, "virtual "); + else if (TYPE_FN_FIELD_STATIC_P (f, j)) + fprintf_filtered (stream, "static "); + if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0) + { + /* Keep GDB from crashing here. */ + fprintf (stream, "<undefined type> %s;\n", + TYPE_FN_FIELD_PHYSNAME (f, j)); + break; + } + else if (!is_constructor) + { + type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), + "", stream, 0); + fputs_filtered (" ", stream); + } + if (TYPE_FN_FIELD_STUB (f, j)) + { + /* Build something we can demangle. */ + mangled_name = gdb_mangle_name (type, i, j); + demangled_name = + cplus_demangle (mangled_name, + DMGL_ANSI | DMGL_PARAMS); + if (demangled_name == NULL) + fprintf_filtered (stream, "<badly mangled name %s>", + mangled_name); + else + { + fprintf_filtered (stream, "%s", + strchr (demangled_name, ':') + 2); + free (demangled_name); + } + free (mangled_name); + } + else if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER) + cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1, + "~", method_name, 0, stream); + else + cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "", + method_name, + TYPE_FN_FIELD_STATIC_P (f, j), + stream); + + fprintf_filtered (stream, ";\n"); + } + } + + fprintfi_filtered (level, stream, "}"); + } + break; + + case TYPE_CODE_ENUM: + fprintf_filtered (stream, "enum "); + if ((name = type_name_no_tag (type)) != NULL) + { + fputs_filtered (name, stream); + fputs_filtered (" ", stream); + } + wrap_here (" "); + if (show < 0) + fprintf_filtered (stream, "{...}"); + else + { + fprintf_filtered (stream, "{"); + len = TYPE_NFIELDS (type); + lastval = 0; + for (i = 0; i < len; i++) + { + QUIT; + if (i) fprintf_filtered (stream, ", "); + wrap_here (" "); + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + if (lastval != TYPE_FIELD_BITPOS (type, i)) + { + fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i)); + lastval = TYPE_FIELD_BITPOS (type, i); + } + lastval++; + } + fprintf_filtered (stream, "}"); + } + break; + + case TYPE_CODE_VOID: + fprintf_filtered (stream, "void"); + break; + + case TYPE_CODE_UNDEF: + fprintf_filtered (stream, "struct <unknown>"); + break; + + case TYPE_CODE_ERROR: + fprintf_filtered (stream, "<unknown type>"); + break; + + case TYPE_CODE_RANGE: + /* This should not occur */ + fprintf_filtered (stream, "<range type>"); + break; + + default: + /* Handle types not explicitly handled by the other cases, + such as fundamental types. For these, just print whatever + the type name is, as recorded in the type itself. If there + is no type name, then complain. */ + if (TYPE_NAME (type) != NULL) + { + fputs_filtered (TYPE_NAME (type), stream); + } + else + { + error ("Invalid type code (%d) in symbol table.", TYPE_CODE (type)); + } + break; + } +} + diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c new file mode 100644 index 0000000..91d9a57 --- /dev/null +++ b/gdb/c-valprint.c @@ -0,0 +1,542 @@ +/* Support for printing C values for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "value.h" +#include "demangle.h" +#include "valprint.h" +#include "language.h" + +/* BEGIN-FIXME */ + +extern int vtblprint; /* Controls printing of vtbl's */ +extern int demangle; /* whether to print C++ syms raw or src-form */ + +extern void +cp_print_class_member PARAMS ((char *, struct type *, FILE *, char *)); + +extern int +cp_is_vtbl_ptr_type PARAMS ((struct type *)); + +extern void +cp_print_value_fields PARAMS ((struct type *, char *, FILE *, int, int, + enum val_prettyprint, struct type **)); + +extern int +cp_is_vtbl_member PARAMS ((struct type *)); + +/* END-FIXME */ + + +/* BEGIN-FIXME: Hooks into c-typeprint.c */ + +extern void +c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); + +extern void +cp_type_print_method_args PARAMS ((struct type **, char *, char *, int, + FILE *)); +/* END-FIXME */ + + +extern struct obstack dont_print_obstack; + + +/* Print data of type TYPE located at VALADDR (within GDB), which came from + the inferior at address ADDRESS, onto stdio stream STREAM according to + FORMAT (a letter or 0 for natural format). The data at VALADDR is in + target byte order. + + If the data are a string pointer, returns the number of string characters + printed. + + If DEREF_REF is nonzero, then dereference references, otherwise just print + them like pointers. + + The PRETTY parameter controls prettyprinting. */ + +int +c_val_print (type, valaddr, address, stream, format, deref_ref, recurse, + pretty) + struct type *type; + char *valaddr; + CORE_ADDR address; + FILE *stream; + int format; + int deref_ref; + int recurse; + enum val_prettyprint pretty; +{ + register unsigned int i; + unsigned len; + struct type *elttype; + unsigned eltlen; + LONGEST val; + unsigned char c; + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) + { + elttype = TYPE_TARGET_TYPE (type); + eltlen = TYPE_LENGTH (elttype); + len = TYPE_LENGTH (type) / eltlen; + if (prettyprint_arrays) + { + print_spaces_filtered (2 + 2 * recurse, stream); + } + fprintf_filtered (stream, "{"); + /* For an array of chars, print with string syntax. */ + if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT + && (format == 0 || format == 's') ) + { + LA_PRINT_STRING (stream, valaddr, len, 0); + } + else + { + /* If this is a virtual function table, print the 0th + entry specially, and the rest of the members normally. */ + if (cp_is_vtbl_ptr_type (elttype)) + { + i = 1; + fprintf_filtered (stream, "%d vtable entries", len - 1); + } + else + { + i = 0; + } + val_print_array_elements (type, valaddr, address, stream, + format, deref_ref, recurse, pretty, i); + } + fprintf_filtered (stream, "}"); + break; + } + /* Array of unspecified length: treat like pointer to first elt. */ + valaddr = (char *) &address; + + case TYPE_CODE_PTR: + if (format && format != 's') + { + print_scalar_formatted (valaddr, type, format, 0, stream); + break; + } + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) + { + struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); + struct fn_field *f; + int j, len2; + char *kind = ""; + CORE_ADDR addr; + + addr = unpack_pointer (lookup_pointer_type (builtin_type_void), + valaddr); + if (METHOD_PTR_IS_VIRTUAL(addr)) + { + int offset = METHOD_PTR_TO_VOFFSET(addr); + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) + { + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) + { + QUIT; + if (TYPE_FN_FIELD_VOFFSET (f, j) == offset) + { + kind = "virtual "; + goto common; + } + } + } + } + else + { + struct symbol *sym = find_pc_function (addr); + if (sym == 0) + { + error ("invalid pointer to member function"); + } + len = TYPE_NFN_FIELDS (domain); + for (i = 0; i < len; i++) + { + f = TYPE_FN_FIELDLIST1 (domain, i); + len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); + + for (j = 0; j < len2; j++) + { + QUIT; + if (!strcmp (SYMBOL_NAME (sym), + TYPE_FN_FIELD_PHYSNAME (f, j))) + { + goto common; + } + } + } + } + common: + if (i < len) + { + fprintf_filtered (stream, "&"); + c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); + fprintf (stream, kind); + if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' + && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER) + cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", + TYPE_FN_FIELDLIST_NAME (domain, i), + 0, stream); + else + cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "", + TYPE_FN_FIELDLIST_NAME (domain, i), + 0, stream); + break; + } + fprintf_filtered (stream, "("); + type_print (type, "", stream, -1); + fprintf_filtered (stream, ") %d", (int) addr >> 3); + } + else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) + { + cp_print_class_member (valaddr, + TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), + stream, "&"); + } + else + { + CORE_ADDR addr = unpack_pointer (type, valaddr); + elttype = TYPE_TARGET_TYPE (type); + + if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) + { + /* Try to print what function it points to. */ + print_address_demangle (addr, stream, demangle); + /* Return value is irrelevant except for string pointers. */ + return (0); + } + + if (addressprint && format != 's') + { + fprintf_filtered (stream, "0x%x", addr); + } + + /* For a pointer to char or unsigned char, also print the string + pointed to, unless pointer is null. */ + i = 0; /* Number of characters printed. */ + if (TYPE_LENGTH (elttype) == 1 && + TYPE_CODE (elttype) == TYPE_CODE_INT && + (format == 0 || format == 's') && + addr != 0 && + /* If print_max is UINT_MAX, the alloca below will fail. + In that case don't try to print the string. */ + print_max < UINT_MAX) + { + int first_addr_err = 0; + int errcode = 0; + + /* Get first character. */ + errcode = target_read_memory (addr, (char *)&c, 1); + if (errcode != 0) + { + /* First address out of bounds. */ + first_addr_err = 1; + } + else + { + /* A real string. */ + char *string = (char *) alloca (print_max); + + /* If the loop ends by us hitting print_max characters, + we need to have elipses at the end. */ + int force_ellipses = 1; + + /* This loop always fetches print_max characters, even + though LA_PRINT_STRING might want to print more or fewer + (with repeated characters). This is so that + we don't spend forever fetching if we print + a long string consisting of the same character + repeated. Also so we can do it all in one memory + operation, which is faster. However, this will be + slower if print_max is set high, e.g. if you set + print_max to 1000, not only will it take a long + time to fetch short strings, but if you are near + the end of the address space, it might not work. */ + QUIT; + errcode = target_read_memory (addr, string, print_max); + if (errcode != 0) + { + /* Try reading just one character. If that succeeds, + assume we hit the end of the address space, but + the initial part of the string is probably safe. */ + char x[1]; + errcode = target_read_memory (addr, x, 1); + } + if (errcode != 0) + force_ellipses = 0; + else + for (i = 0; i < print_max; i++) + if (string[i] == '\0') + { + force_ellipses = 0; + break; + } + QUIT; + + if (addressprint) + { + fputs_filtered (" ", stream); + } + LA_PRINT_STRING (stream, string, i, force_ellipses); + } + + if (errcode != 0) + { + if (errcode == EIO) + { + fprintf_filtered (stream, + (" <Address 0x%x out of bounds>" + + first_addr_err), + addr + i); + } + else + { + error ("Error reading memory address 0x%x: %s.", + addr + i, safe_strerror (errcode)); + } + } + + fflush (stream); + } + else if (cp_is_vtbl_member(type)) + { + /* print vtbl's nicely */ + CORE_ADDR vt_address = unpack_pointer (type, valaddr); + + struct minimal_symbol *msymbol = + lookup_minimal_symbol_by_pc (vt_address); + if ((msymbol != NULL) && (vt_address == msymbol -> address)) + { + fputs_filtered (" <", stream); + fputs_demangled (msymbol -> name, stream, + DMGL_ANSI | DMGL_PARAMS); + fputs_filtered (">", stream); + } + if (vtblprint) + { + value vt_val; + + vt_val = value_at (TYPE_TARGET_TYPE (type), vt_address); + val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), + VALUE_ADDRESS (vt_val), stream, format, + deref_ref, recurse + 1, pretty); + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 + 2 * recurse, stream); + } + } + } + + /* Return number of characters printed, plus one for the + terminating null if we have "reached the end". */ + return (i + (print_max && i != print_max)); + } + break; + + case TYPE_CODE_MEMBER: + error ("not implemented: member type in c_val_print"); + break; + + case TYPE_CODE_REF: + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) + { + cp_print_class_member (valaddr, + TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), + stream, ""); + break; + } + if (addressprint) + { + fprintf_filtered (stream, "@0x%lx", + unpack_long (builtin_type_int, valaddr)); + if (deref_ref) + fputs_filtered (": ", stream); + } + /* De-reference the reference. */ + if (deref_ref) + { + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) + { + value deref_val = + value_at + (TYPE_TARGET_TYPE (type), + unpack_pointer (lookup_pointer_type (builtin_type_void), + valaddr)); + val_print (VALUE_TYPE (deref_val), + VALUE_CONTENTS (deref_val), + VALUE_ADDRESS (deref_val), stream, format, + deref_ref, recurse + 1, pretty); + } + else + fputs_filtered ("???", stream); + } + break; + + case TYPE_CODE_UNION: + if (recurse && !unionprint) + { + fprintf_filtered (stream, "{...}"); + break; + } + /* Fall through. */ + case TYPE_CODE_STRUCT: + if (vtblprint && cp_is_vtbl_ptr_type(type)) + { + /* Print the unmangled name if desired. */ + print_address_demangle(*((int *) (valaddr + /* FIXME bytesex */ + TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8)), + stream, demangle); + break; + } + cp_print_value_fields (type, valaddr, stream, format, recurse, pretty, + 0); + break; + + case TYPE_CODE_ENUM: + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + break; + } + len = TYPE_NFIELDS (type); + val = unpack_long (builtin_type_int, valaddr); + for (i = 0; i < len; i++) + { + QUIT; + if (val == TYPE_FIELD_BITPOS (type, i)) + { + break; + } + } + if (i < len) + { + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + } + else + { +#ifdef LONG_LONG + fprintf_filtered (stream, "%lld", val); +#else + fprintf_filtered (stream, "%ld", val); +#endif + } + break; + + case TYPE_CODE_FUNC: + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + break; + } + /* FIXME, we should consider, at least for ANSI C language, eliminating + the distinction made between FUNCs and POINTERs to FUNCs. */ + fprintf_filtered (stream, "{"); + type_print (type, "", stream, -1); + fprintf_filtered (stream, "} "); + /* Try to print what function it points to, and its address. */ + print_address_demangle (address, stream, demangle); + break; + + case TYPE_CODE_INT: + format = format ? format : output_format; + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + val_print_type_code_int (type, valaddr, stream); + /* C and C++ has no single byte int type, char is used instead. + 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) + { + fputs_filtered (" ", stream); + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), + stream); + } + } + break; + + case TYPE_CODE_CHAR: + format = format ? format : output_format; + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d", + unpack_long (type, valaddr)); + fputs_filtered (" ", stream); + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), stream); + } + break; + + case TYPE_CODE_FLT: + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + print_floating (valaddr, type, stream); + } + break; + + case TYPE_CODE_VOID: + fprintf_filtered (stream, "void"); + break; + + case TYPE_CODE_ERROR: + fprintf_filtered (stream, "<error type>"); + break; + + case TYPE_CODE_RANGE: + /* FIXME, we should not ever have to print one of these yet. */ + fprintf_filtered (stream, "<range type>"); + break; + + case TYPE_CODE_UNDEF: + /* This happens (without TYPE_FLAG_STUB set) on systems which don't use + dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar" + and no complete type for struct foo in that file. */ + fprintf_filtered (stream, "<incomplete type>"); + break; + + default: + error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type)); + } + fflush (stream); + return (0); +} diff --git a/gdb/ch-exp.y b/gdb/ch-exp.y index ec73158..ce2bbfe 100644 --- a/gdb/ch-exp.y +++ b/gdb/ch-exp.y @@ -135,10 +135,6 @@ yyparse PARAMS ((void)); int *ivec; } -%{ -static int parse_number PARAMS ((void)); -%} - %token <voidval> FIXME %token <typed_val> INTEGER_LITERAL @@ -874,8 +870,6 @@ decode_integer_literal (valptr, tokptrptr) char *tokptr = *tokptrptr; int base = 0; int ival = 0; - int digits = 0; - int temp; int explicit_base = 0; /* Look for an explicit base specifier, which is optional. */ @@ -1042,9 +1036,9 @@ match_integer_literal () } } +#if 0 static void convert_float () { -#if 0 extern double strtod (); double d; char tmp[256]; @@ -1075,8 +1069,8 @@ static void convert_float () ; } yylval.dval = d; -#endif } +#endif /* Take care of parsing a number (anything that starts with a digit). Set yylval and return the token type; update lexptr. @@ -1084,35 +1078,30 @@ static void convert_float () /*** Needs some error checking for the float case ***/ -static int -parse_number () -{ -} - struct token { char *operator; int token; }; -const static struct token tokentab5[] = +static const struct token tokentab5[] = { { "ANDIF", ANDIF } }; -const static struct token tokentab4[] = +static const struct token tokentab4[] = { { "ORIF", ORIF } }; -const static struct token tokentab3[] = +static const struct token tokentab3[] = { { "NOT", NOT }, { "XOR", LOGXOR }, { "AND", LOGAND } }; -const static struct token tokentab2[] = +static const struct token tokentab2[] = { { "//", SLASH_SLASH }, { "/=", NOTEQUAL }, @@ -1265,6 +1254,18 @@ yylex () case LOC_STATIC: /* Found a global or local static variable. */ return (LOCATION_NAME); + case LOC_UNDEF: + case LOC_CONST: + case LOC_REGISTER: + case LOC_ARG: + case LOC_REF_ARG: + case LOC_REGPARM: + case LOC_LOCAL: + case LOC_TYPEDEF: + case LOC_LABEL: + case LOC_CONST_BYTES: + case LOC_LOCAL_ARG: + break; } } else if (!have_full_symbols () && !have_partial_symbols ()) diff --git a/gdb/ch-lang.c b/gdb/ch-lang.c index 9e28fbd..f512b4f 100644 --- a/gdb/ch-lang.c +++ b/gdb/ch-lang.c @@ -164,7 +164,6 @@ chill_create_fundamental_type (objfile, typeid) int typeid; { register struct type *type = NULL; - register int nbytes; switch (typeid) { @@ -173,16 +172,20 @@ chill_create_fundamental_type (objfile, typeid) language, create the equivalent of a C integer type with the name "<?type?>". When all the dust settles from the type reconstruction work, this should probably become an error. */ - type = init_type (TYPE_CODE_INT, - TARGET_INT_BIT / TARGET_CHAR_BIT, - 0, "<?type?>", objfile); + type = init_type (TYPE_CODE_INT, 2, 0, "<?type?>", objfile); warning ("internal error: no chill fundamental type %d", typeid); break; + case FT_VOID: + /* FIXME: Currently the GNU Chill compiler emits some DWARF entries for + typedefs, unrelated to anything directly in the code being compiled, + that have some FT_VOID types. Just fake it for now. */ + type = init_type (TYPE_CODE_VOID, 0, 0, "<?VOID?>", objfile); + break; case FT_BOOLEAN: type = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED, "BOOL", objfile); break; case FT_CHAR: - type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile); + type = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile); break; case FT_SIGNED_CHAR: type = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_SIGNED, "BYTE", objfile); @@ -215,7 +218,7 @@ chill_create_fundamental_type (objfile, typeid) /* Table of operators and their precedences for printing expressions. */ -const static struct op_print chill_op_print_tab[] = { +static const struct op_print chill_op_print_tab[] = { {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0}, {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0}, {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0}, @@ -265,6 +268,8 @@ const struct language_defn chill_language_defn = { chill_printchar, /* print a character constant */ chill_printstr, /* function to print a string constant */ chill_create_fundamental_type,/* Create fundamental type in this language */ + chill_print_type, /* Print a type using appropriate syntax */ + chill_val_print, /* Print a value using appropriate syntax */ &BUILTIN_TYPE_LONGEST, /* longest signed integral type */ &BUILTIN_TYPE_UNSIGNED_LONGEST,/* longest unsigned integral type */ &builtin_type_chill_real, /* longest floating point type */ diff --git a/gdb/ch-lang.h b/gdb/ch-lang.h index 1d9b556..13579d9 100644 --- a/gdb/ch-lang.h +++ b/gdb/ch-lang.h @@ -22,3 +22,10 @@ chill_parse PARAMS ((void)); /* Defined in ch-exp.y */ extern void chill_error PARAMS ((char *)); /* Defined in ch-exp.y */ + +extern void /* Defined in ch-typeprint.c */ +chill_print_type PARAMS ((struct type *, char *, FILE *, int, int)); + +extern int +chill_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, + int, enum val_prettyprint)); diff --git a/gdb/ch-typeprint.c b/gdb/ch-typeprint.c new file mode 100644 index 0000000..cd3dd36 --- /dev/null +++ b/gdb/ch-typeprint.c @@ -0,0 +1,155 @@ +/* Support for printing Chill types for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "bfd.h" /* Binary File Description */ +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "value.h" +#include "gdbcore.h" +#include "target.h" +#include "command.h" +#include "gdbcmd.h" +#include "language.h" +#include "demangle.h" +#include "ch-lang.h" + +#include <string.h> +#include <errno.h> + +void +chill_print_type_base PARAMS ((struct type *, FILE *, int, int)); + +void +chill_print_type (type, varstring, stream, show, level) + struct type *type; + char *varstring; + FILE *stream; + int show; + int level; +{ + struct type *index_type; + struct type *range_type; + LONGEST low_bound; + LONGEST high_bound; + + if (varstring != NULL && *varstring != '\0') + { + fputs_filtered (varstring, stream); + fputs_filtered (" ", stream); + } + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + range_type = TYPE_FIELD_TYPE (type, 0); + index_type = TYPE_TARGET_TYPE (range_type); + low_bound = TYPE_FIELD_BITPOS (range_type, 0); + high_bound = TYPE_FIELD_BITPOS (range_type, 1); + fputs_filtered ("array (", stream); + print_type_scalar (index_type, low_bound, stream); + fputs_filtered (":", stream); + print_type_scalar (index_type, high_bound, stream); + fputs_filtered (") ", stream); + chill_print_type (TYPE_TARGET_TYPE (type), "", stream, show, level); + break; + default: + chill_print_type_base (type, stream, show, level); + break; + } +} + +/* Print the name of the type (or the ultimate pointer target, + function value or array element). + + SHOW nonzero means don't print this type as just its name; + show its real definition even if it has a name. + SHOW zero means print just typename or tag if there is one + SHOW negative means abbreviate structure elements. + SHOW is decremented for printing of structure elements. + + LEVEL is the depth to indent by. + We increase it for some recursive calls. */ + +void +chill_print_type_base (type, stream, show, level) + struct type *type; + FILE *stream; + int show; + int level; +{ + QUIT; + + wrap_here (" "); + if (type == NULL) + { + fputs_filtered ("<type unknown>", stream); + return; + } + + /* When SHOW is zero or less, and there is a valid type name, then always + just print the type name directly from the type. */ + + if ((show <= 0) && (TYPE_NAME (type) != NULL)) + { + fputs_filtered (TYPE_NAME (type), stream); + return; + } + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + case TYPE_CODE_PTR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_REF: + case TYPE_CODE_FUNC: + chill_print_type_base (TYPE_TARGET_TYPE (type), stream, show, level); + break; + + case TYPE_CODE_VOID: + case TYPE_CODE_UNDEF: + case TYPE_CODE_ERROR: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + case TYPE_CODE_UNION: + case TYPE_CODE_STRUCT: + case TYPE_CODE_METHOD: + error ("missing language support in chill_print_type_base"); + break; + + default: + + /* Handle types not explicitly handled by the other cases, + such as fundamental types. For these, just print whatever + the type name is, as recorded in the type itself. If there + is no type name, then complain. */ + + if (TYPE_NAME (type) != NULL) + { + fputs_filtered (TYPE_NAME (type), stream); + } + else + { + error ("Unrecognized type code (%d) in symbol table.", + TYPE_CODE (type)); + } + break; + } +} diff --git a/gdb/ch-valprint.c b/gdb/ch-valprint.c new file mode 100644 index 0000000..8ffa1af --- /dev/null +++ b/gdb/ch-valprint.c @@ -0,0 +1,166 @@ +/* Support for printing Chill values for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "valprint.h" +#include "expression.h" +#include "language.h" + + +/* Print data of type TYPE located at VALADDR (within GDB), which came from + the inferior at address ADDRESS, onto stdio stream STREAM according to + FORMAT (a letter or 0 for natural format). The data at VALADDR is in + target byte order. + + If the data are a string pointer, returns the number of string characters + printed. + + If DEREF_REF is nonzero, then dereference references, otherwise just print + them like pointers. + + The PRETTY parameter controls prettyprinting. */ + +int +chill_val_print (type, valaddr, address, stream, format, deref_ref, recurse, + pretty) + struct type *type; + char *valaddr; + CORE_ADDR address; + FILE *stream; + int format; + int deref_ref; + int recurse; + enum val_prettyprint pretty; +{ + unsigned len; + struct type *elttype; + unsigned eltlen; + LONGEST val; + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_ARRAY: + if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) + { + elttype = TYPE_TARGET_TYPE (type); + eltlen = TYPE_LENGTH (elttype); + len = TYPE_LENGTH (type) / eltlen; + if (prettyprint_arrays) + { + print_spaces_filtered (2 + 2 * recurse, stream); + } + fprintf_filtered (stream, "["); + /* For an array of chars, print with string syntax. */ + if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT + && (format == 0 || format == 's') ) + { + LA_PRINT_STRING (stream, valaddr, len, 0); + } + else + { + val_print_array_elements (type, valaddr, address, stream, + format, deref_ref, recurse, pretty, 0); + } + fprintf_filtered (stream, "]"); + } + else + { + error ("unimplemented in chill_val_print; unspecified array length"); + } + break; + + case TYPE_CODE_INT: + format = format ? format : output_format; + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + val_print_type_code_int (type, valaddr, stream); + } + break; + + case TYPE_CODE_CHAR: + format = format ? format : output_format; + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), + stream); + } + break; + + case TYPE_CODE_FLT: + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + print_floating (valaddr, type, stream); + } + break; + + case TYPE_CODE_BOOL: + format = format ? format : output_format; + if (format) + { + print_scalar_formatted (valaddr, type, format, 0, stream); + } + else + { + val = unpack_long (builtin_type_chill_bool, valaddr); + fprintf_filtered (stream, val ? "TRUE" : "FALSE"); + } + break; + + case TYPE_CODE_UNDEF: + /* This happens (without TYPE_FLAG_STUB set) on systems which don't use + dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar" + and no complete type for struct foo in that file. */ + fprintf_filtered (stream, "<incomplete type>"); + break; + + case TYPE_CODE_PTR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_REF: + case TYPE_CODE_UNION: + case TYPE_CODE_STRUCT: + case TYPE_CODE_ENUM: + case TYPE_CODE_FUNC: + case TYPE_CODE_VOID: + case TYPE_CODE_ERROR: + case TYPE_CODE_RANGE: + error ("Unimplemented chill_val_print support for type %d", + TYPE_CODE (type)); + break; + + default: + error ("Invalid Chill type code %d in symbol table.", TYPE_CODE (type)); + } + fflush (stream); + return (0); +} diff --git a/gdb/coffread.c b/gdb/coffread.c index 6e35c5b..62e20d3 100644 --- a/gdb/coffread.c +++ b/gdb/coffread.c @@ -1777,7 +1777,7 @@ decode_type (cs, c_type, aux) { int i, n; register unsigned short *dim; - struct type *base_type, *index_type; + struct type *base_type, *index_type, *range_type; /* Define an array type. */ /* auxent refers to array, not base type */ @@ -1794,8 +1794,10 @@ decode_type (cs, c_type, aux) base_type = decode_type (cs, new_c_type, aux); index_type = lookup_fundamental_type (current_objfile, FT_INTEGER); - type = create_array_type ((struct type *) NULL, base_type, - index_type, 0, n - 1); + range_type = + create_range_type ((struct type *) NULL, index_type, 0, n - 1); + type = + create_array_type ((struct type *) NULL, base_type, range_type); } return type; } diff --git a/gdb/complaints.c b/gdb/complaints.c index b8ab240..49b9e59 100644 --- a/gdb/complaints.c +++ b/gdb/complaints.c @@ -64,7 +64,6 @@ complain (va_alist) { va_list args; struct complaint *complaint; - char *val; va_start (args); complaint = va_arg (args, struct complaint *); @@ -142,6 +141,7 @@ clear_complaints (sym_reading, noisy) complaint_series = sym_reading ? 1 + noisy : 0; } +void _initialize_complaints () { add_show_from_set diff --git a/gdb/convex-tdep.c b/gdb/convex-tdep.c index a374a80..cf95776 100644 --- a/gdb/convex-tdep.c +++ b/gdb/convex-tdep.c @@ -332,6 +332,7 @@ value_of_trapped_internalvar (var) char *name = var->name; value val; struct type *type; + struct type *range_type; long len = *read_vector_register (VL_REGNUM); if (len <= 0 || len > 128) len = 128; @@ -350,8 +351,10 @@ value_of_trapped_internalvar (var) long vm[4]; long i, *p; bcopy (read_vector_register_1 (VM_REGNUM), vm, sizeof vm); - type = create_array_type ((struct type *) NULL, builtin_type_int, - builtin_type_int, 0, len - 1); + range_type = + create_range_type ((struct type *) NULL, builtin_type_int, 0, len - 1); + type = + create_array_type ((struct type *) NULL, builtin_type_int, range_type); val = allocate_value (type); p = (long *) VALUE_CONTENTS (val); for (i = 0; i < len; i++) @@ -359,8 +362,11 @@ value_of_trapped_internalvar (var) } else if (name[0] == 'V') { - type = create_array_type ((struct type *) NULL, builtin_type_long_long, - builtin_type_int, 0, len - 1); + range_type = + create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1); + type = + create_array_type ((struct type *) NULL, builtin_type_long_long, + range_type); val = allocate_value (type); bcopy (read_vector_register_1 (name[1] - '0'), VALUE_CONTENTS (val), TYPE_LENGTH (type)); @@ -368,8 +374,11 @@ value_of_trapped_internalvar (var) else if (name[0] == 'v') { long *p1, *p2; - type = create_array_type ((struct type *) NULL, builtin_type_long, - builtin_type_int, 0, len - 1); + range_type = + create_range_type ((struct type *) NULL, builtin_type_int 0, len - 1); + type = + create_array_type ((struct type *) NULL, builtin_type_long, + range_type); val = allocate_value (type); p1 = read_vector_register_1 (name[1] - '0'); p2 = (long *) VALUE_CONTENTS (val); diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c new file mode 100644 index 0000000..5222f7b --- /dev/null +++ b/gdb/cp-valprint.c @@ -0,0 +1,369 @@ +/* Support for printing C++ values for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "value.h" +#include "command.h" +#include "gdbcmd.h" + +int vtblprint; /* Controls printing of vtbl's */ +int objectprint; /* Controls looking up an object's derived type + using what we find in its vtables. */ +struct obstack dont_print_obstack; + +static void +cplus_print_value PARAMS ((struct type *, char *, FILE *, int, int, + enum val_prettyprint, struct type **)); + +/* BEGIN-FIXME: Hooks into typeprint.c, find a better home for prototypes. */ + +extern void +c_type_print_base PARAMS ((struct type *, FILE *, int, int)); + +extern void +c_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); + +extern void +cp_type_print_method_args PARAMS ((struct type **, char *, char *, int, + FILE *)); + +extern struct obstack dont_print_obstack; + +/* END-FIXME */ + + +/* BEGIN-FIXME: Hooks into c-valprint.c */ + +extern int +c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, int, + enum val_prettyprint)); +/* END-FIXME */ + + +/* Return truth value for assertion that TYPE is of the type + "pointer to virtual function". */ + +int +cp_is_vtbl_ptr_type(type) + struct type *type; +{ + char *typename = type_name_no_tag (type); + static const char vtbl_ptr_name[] = + { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; + + return (typename != NULL && !strcmp(typename, vtbl_ptr_name)); +} + +/* Return truth value for the assertion that TYPE is of the type + "pointer to virtual function table". */ + +int +cp_is_vtbl_member(type) + struct type *type; +{ + if (TYPE_CODE (type) == TYPE_CODE_PTR) + type = TYPE_TARGET_TYPE (type); + else + return 0; + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY + && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT) + /* Virtual functions tables are full of pointers to virtual functions. */ + return cp_is_vtbl_ptr_type (TYPE_TARGET_TYPE (type)); + return 0; +} + +/* Mutually recursive subroutines of cplus_print_value and c_val_print to + print out a structure's fields: cp_print_value_fields and cplus_print_value. + + TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the + same meanings as in cplus_print_value and c_val_print. + + DONT_PRINT is an array of baseclass types that we + should not print, or zero if called from top level. */ + +void +cp_print_value_fields (type, valaddr, stream, format, recurse, pretty, + dont_print) + struct type *type; + char *valaddr; + FILE *stream; + int format; + int recurse; + enum val_prettyprint pretty; + struct type **dont_print; +{ + int i, len, n_baseclasses; + + check_stub_type (type); + + fprintf_filtered (stream, "{"); + len = TYPE_NFIELDS (type); + n_baseclasses = TYPE_N_BASECLASSES (type); + + /* Print out baseclasses such that we don't print + duplicates of virtual baseclasses. */ + if (n_baseclasses > 0) + cplus_print_value (type, valaddr, stream, format, recurse+1, pretty, + dont_print); + + if (!len && n_baseclasses == 1) + fprintf_filtered (stream, "<No data fields>"); + else + { + extern int inspect_it; + int fields_seen = 0; + + for (i = n_baseclasses; i < len; i++) + { + /* Check if static field */ + if (TYPE_FIELD_STATIC (type, i)) + continue; + if (fields_seen) + fprintf_filtered (stream, ", "); + else if (n_baseclasses > 0) + { + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 + 2 * recurse, stream); + fputs_filtered ("members of ", stream); + fputs_filtered (type_name_no_tag (type), stream); + fputs_filtered (": ", stream); + } + } + fields_seen = 1; + + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 + 2 * recurse, stream); + } + else + { + wrap_here (n_spaces (2 + 2 * recurse)); + } + if (inspect_it) + { + if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR) + fputs_filtered ("\"( ptr \"", stream); + else + fputs_filtered ("\"( nodef \"", stream); + fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); + fputs_filtered ("\" \"", stream); + fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); + fputs_filtered ("\") \"", stream); + } + else + { + fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); + fputs_filtered (" = ", stream); + } + if (TYPE_FIELD_PACKED (type, i)) + { + value v; + + /* Bitfields require special handling, especially due to byte + order problems. */ + v = value_from_longest (TYPE_FIELD_TYPE (type, i), + unpack_field_as_long (type, valaddr, i)); + + c_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, + stream, format, 0, recurse + 1, pretty); + } + else + { + c_val_print (TYPE_FIELD_TYPE (type, i), + valaddr + TYPE_FIELD_BITPOS (type, i) / 8, + 0, stream, format, 0, recurse + 1, pretty); + } + } + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 * recurse, stream); + } + } + fprintf_filtered (stream, "}"); +} + +/* Special val_print routine to avoid printing multiple copies of virtual + baseclasses. */ + +static void +cplus_print_value (type, valaddr, stream, format, recurse, pretty, dont_print) + struct type *type; + char *valaddr; + FILE *stream; + int format; + int recurse; + enum val_prettyprint pretty; + struct type **dont_print; +{ + struct obstack tmp_obstack; + struct type **last_dont_print + = (struct type **)obstack_next_free (&dont_print_obstack); + int i, n_baseclasses = TYPE_N_BASECLASSES (type); + + if (dont_print == 0) + { + /* If we're at top level, carve out a completely fresh + chunk of the obstack and use that until this particular + invocation returns. */ + tmp_obstack = dont_print_obstack; + /* Bump up the high-water mark. Now alpha is omega. */ + obstack_finish (&dont_print_obstack); + } + + for (i = 0; i < n_baseclasses; i++) + { + char *baddr; + int err; + + if (BASETYPE_VIA_VIRTUAL (type, i)) + { + struct type **first_dont_print + = (struct type **)obstack_base (&dont_print_obstack); + + int j = (struct type **)obstack_next_free (&dont_print_obstack) + - first_dont_print; + + while (--j >= 0) + if (TYPE_BASECLASS (type, i) == first_dont_print[j]) + goto flush_it; + + obstack_ptr_grow (&dont_print_obstack, TYPE_BASECLASS (type, i)); + } + + /* Fix to use baseclass_offset instead. FIXME */ + baddr = baseclass_addr (type, i, valaddr, 0, &err); + if (err == 0 && baddr == 0) + error ("could not find virtual baseclass `%s'\n", + type_name_no_tag (TYPE_BASECLASS (type, i))); + + if (pretty) + { + fprintf_filtered (stream, "\n"); + print_spaces_filtered (2 * recurse, stream); + } + fputs_filtered ("<", stream); + fputs_filtered (type_name_no_tag (TYPE_BASECLASS (type, i)), stream); + fputs_filtered ("> = ", stream); + if (err != 0) + fprintf_filtered (stream, "<invalid address 0x%x>", baddr); + else + cp_print_value_fields (TYPE_BASECLASS (type, i), baddr, stream, format, + recurse, pretty, + (struct type **) obstack_base (&dont_print_obstack)); + fputs_filtered (", ", stream); + + flush_it: + ; + } + + if (dont_print == 0) + { + /* Free the space used to deal with the printing + of this type from top level. */ + obstack_free (&dont_print_obstack, last_dont_print); + /* Reset watermark so that we can continue protecting + ourselves from whatever we were protecting ourselves. */ + dont_print_obstack = tmp_obstack; + } +} + +void +cp_print_class_member (valaddr, domain, stream, prefix) + char *valaddr; + struct type *domain; + FILE *stream; + char *prefix; +{ + + /* VAL is a byte offset into the structure type DOMAIN. + Find the name of the field for that offset and + print it. */ + int extra = 0; + int bits = 0; + register unsigned int i; + unsigned len = TYPE_NFIELDS (domain); + /* @@ Make VAL into bit offset */ + LONGEST val = unpack_long (builtin_type_int, valaddr) << 3; + for (i = TYPE_N_BASECLASSES (domain); i < len; i++) + { + int bitpos = TYPE_FIELD_BITPOS (domain, i); + QUIT; + if (val == bitpos) + break; + if (val < bitpos && i != 0) + { + /* Somehow pointing into a field. */ + i -= 1; + extra = (val - TYPE_FIELD_BITPOS (domain, i)); + if (extra & 0x7) + bits = 1; + else + extra >>= 3; + break; + } + } + if (i < len) + { + char *name; + fprintf_filtered (stream, prefix); + name = type_name_no_tag (domain); + if (name) + fputs_filtered (name, stream); + else + c_type_print_base (domain, stream, 0, 0); + fprintf_filtered (stream, "::"); + fputs_filtered (TYPE_FIELD_NAME (domain, i), stream); + if (extra) + fprintf_filtered (stream, " + %d bytes", extra); + if (bits) + fprintf_filtered (stream, " (offset in bits)"); + } + else + fprintf_filtered (stream, "%d", val >> 3); +} + +void +_initialize_cp_valprint () +{ + add_show_from_set + (add_set_cmd ("vtbl", class_support, var_boolean, (char *)&vtblprint, + "Set printing of C++ virtual function tables.", + &setprintlist), + &showprintlist); + + add_show_from_set + (add_set_cmd ("object", class_support, var_boolean, (char *)&objectprint, + "Set printing of object's derived type based on vtable info.", + &setprintlist), + &showprintlist); + + /* Give people the defaults which they are used to. */ + objectprint = 0; + vtblprint = 0; + obstack_begin (&dont_print_obstack, 32 * sizeof (struct type *)); +} @@ -358,6 +358,20 @@ enum language language_m2 /* Modula-2 */ }; +/* Possibilities for prettyprint parameters to routines which print + things. Like enum language, this should be in value.h, but needs + to be here for the same reason. FIXME: If we can eliminate this + as an arg to LA_VAL_PRINT, then we can probably move it back to + value.h. */ + +enum val_prettyprint +{ + Val_no_prettyprint = 0, + Val_prettyprint, + /* Use the default setting which the user has specified. */ + Val_pretty_default +}; + /* Host machine definition. This will be a symlink to one of the xm-*.h files, built by the `configure' script. */ diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index 5e22da5..3054ddf 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -1031,7 +1031,9 @@ struct_type (dip, thisdie, enddie, objfile) char *tpart1; struct dieinfo mbr; char *nextdie; +#if !BITS_BIG_ENDIAN int anonymous_size; +#endif if ((type = lookup_utype (dip -> die_ref)) == NULL) { @@ -1353,6 +1355,7 @@ decode_subscript_data_item (scan, end) struct type *typep = NULL; /* Array type we are building */ struct type *nexttype; /* Type of each element (may be array) */ struct type *indextype; /* Type of this index */ + struct type *rangetype; unsigned int format; unsigned short fundtype; unsigned long lowbound; @@ -1384,8 +1387,9 @@ decode_subscript_data_item (scan, end) complain (&subscript_data_items, DIE_ID, DIE_NAME); nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); } - typep = create_array_type ((struct type *) NULL, nexttype, indextype, - lowbound, highbound); + rangetype = create_range_type ((struct type *) NULL, indextype, + lowbound, highbound); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); break; case FMT_FT_C_X: case FMT_FT_X_C: @@ -1395,13 +1399,15 @@ decode_subscript_data_item (scan, end) case FMT_UT_X_C: case FMT_UT_X_X: complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format); - typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); - typep = create_array_type ((struct type *) NULL, typep, typep, 0, 1); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); break; default: complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format); - typep = dwarf_fundamental_type (current_objfile, FT_INTEGER); - typep = create_array_type ((struct type *) NULL, typep, typep, 0, 1); + nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER); + rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0); + typep = create_array_type ((struct type *) NULL, nexttype, rangetype); break; } return (typep); diff --git a/gdb/elfread.c b/gdb/elfread.c index 8c21243..5135e10 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -432,9 +432,7 @@ elf_symfile_read (objfile, section_offsets, mainline) { bfd *abfd = objfile->obfd; struct elfinfo ei; - struct dbx_symfile_info *dbx; struct cleanup *back_to; - asection *text_sect; CORE_ADDR offset; init_minimal_symbol_collection (); @@ -174,22 +174,22 @@ evaluate_subexp (expect_type, exp, pos, noside) switch (op) { case OP_SCOPE: - tem = strlen (&exp->elts[pc + 2].string); - (*pos) += 3 + ((tem + sizeof (union exp_element)) + tem = longest_to_int (exp->elts[pc + 2].longconst); + (*pos) += 4 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type, 0, exp->elts[pc + 1].type, - &exp->elts[pc + 2].string, + &exp->elts[pc + 3].string, expect_type); if (arg1 == NULL) - error ("There is no field named %s", &exp->elts[pc + 2].string); + error ("There is no field named %s", &exp->elts[pc + 3].string); return arg1; case OP_LONG: (*pos) += 3; return value_from_longest (exp->elts[pc + 1].type, - exp->elts[pc + 2].longconst); + exp->elts[pc + 2].longconst); case OP_DOUBLE: (*pos) += 3; @@ -237,22 +237,24 @@ evaluate_subexp (expect_type, exp, pos, noside) (*pos) += 2; return value_of_register (longest_to_int (exp->elts[pc + 1].longconst)); + /* start-sanitize-chill */ case OP_BOOL: (*pos) += 2; return value_from_longest (builtin_type_chill_bool, exp->elts[pc + 1].longconst); + /* end-sanitize-chill */ case OP_INTERNALVAR: (*pos) += 2; return value_of_internalvar (exp->elts[pc + 1].internalvar); case OP_STRING: - tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + ((tem + sizeof (union exp_element)) + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); if (noside == EVAL_SKIP) goto nosideret; - return value_string (&exp->elts[pc + 1].string, tem); + return value_string (&exp->elts[pc + 2].string, tem); case TERNOP_COND: /* Skip third and second args to evaluate the first one. */ @@ -347,8 +349,8 @@ evaluate_subexp (expect_type, exp, pos, noside) nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1; /* First, evaluate the structure into arg2 */ pc2 = (*pos)++; - tem2 = strlen (&exp->elts[pc2 + 1].string); - *pos += 2 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element); + tem2 = longest_to_int (exp->elts[pc2 + 1].longconst); + *pos += 3 + (tem2 + sizeof (union exp_element)) / sizeof (union exp_element); if (noside == EVAL_SKIP) goto nosideret; @@ -383,7 +385,7 @@ evaluate_subexp (expect_type, exp, pos, noside) argvec[1] = arg2; argvec[0] = - value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 1].string, + value_struct_elt (&temp, argvec+1, &exp->elts[pc2 + 2].string, &static_memfuncp, op == STRUCTOP_STRUCT ? "structure" : "structure pointer"); @@ -428,40 +430,40 @@ evaluate_subexp (expect_type, exp, pos, noside) return call_function_by_hand (argvec[0], nargs, argvec + 1); case STRUCTOP_STRUCT: - tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + ((tem + sizeof (union exp_element)) + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + ((tem + sizeof (union exp_element)) / sizeof (union exp_element)); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1), - &exp->elts[pc + 1].string, + &exp->elts[pc + 2].string, 0), lval_memory); else { value temp = arg1; - return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 1].string, + return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string, (int *) 0, "structure"); } case STRUCTOP_PTR: - tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside); if (noside == EVAL_SKIP) goto nosideret; if (noside == EVAL_AVOID_SIDE_EFFECTS) return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)), - &exp->elts[pc + 1].string, + &exp->elts[pc + 2].string, 0), lval_memory); else { value temp = arg1; - return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 1].string, + return value_struct_elt (&temp, (value *)0, &exp->elts[pc + 2].string, (int *) 0, "structure pointer"); } @@ -804,9 +806,8 @@ evaluate_subexp (expect_type, exp, pos, noside) { if (op == OP_SCOPE) { - char *name = &exp->elts[pc+3].string; - int temm = strlen (name); - (*pos) += 2 + (temm + sizeof (union exp_element)) / sizeof (union exp_element); + int temm = longest_to_int (exp->elts[pc+3].longconst); + (*pos) += 3 + (temm + sizeof (union exp_element)) / sizeof (union exp_element); } else evaluate_subexp (expect_type, exp, pos, EVAL_SKIP); diff --git a/gdb/expprint.c b/gdb/expprint.c index d71a1c0..38df56d 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -76,20 +76,20 @@ print_subexp (exp, pos, stream, prec) case OP_SCOPE: myprec = PREC_PREFIX; assoc = 0; - (*pos) += 2; + (*pos) += 3; print_subexp (exp, pos, stream, (enum precedence) ((int) myprec + assoc)); fputs_filtered (" :: ", stream); - nargs = strlen (&exp->elts[pc + 2].string); - (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element); + nargs = longest_to_int (exp->elts[pc + 2].longconst); + (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element); - fputs_filtered (&exp->elts[pc + 2].string, stream); + fputs_filtered (&exp->elts[pc + 3].string, stream); return; case OP_LONG: (*pos) += 3; value_print (value_from_longest (exp->elts[pc + 1].type, - exp->elts[pc + 2].longconst), + exp->elts[pc + 2].longconst), stream, 0, Val_no_prettyprint); return; @@ -145,12 +145,13 @@ print_subexp (exp, pos, stream, prec) return; case OP_STRING: - nargs = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element); - /* local_printstr will print using the current repeat count threshold. + nargs = longest_to_int (exp -> elts[pc + 1].longconst); + (*pos) += 3 + (nargs + sizeof (union exp_element)) + / sizeof (union exp_element); + /* LA_PRINT_STRING will print using the current repeat count threshold. If necessary, we can temporarily set it to zero, or pass it as an - additional parameter to local_printstr. -fnf */ - local_printstr (stream, &exp->elts[pc + 1].string, nargs, 0); + additional parameter to LA_PRINT_STRING. -fnf */ + LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 0); return; case TERNOP_COND: @@ -170,20 +171,20 @@ print_subexp (exp, pos, stream, prec) return; case STRUCTOP_STRUCT: - tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered (".", stream); - fputs_filtered (&exp->elts[pc + 1].string, stream); + fputs_filtered (&exp->elts[pc + 2].string, stream); return; /* Will not occur for Modula-2 */ case STRUCTOP_PTR: - tem = strlen (&exp->elts[pc + 1].string); - (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); + tem = longest_to_int (exp->elts[pc + 1].longconst); + (*pos) += 3 + (tem + sizeof (union exp_element)) / sizeof (union exp_element); print_subexp (exp, pos, stream, PREC_SUFFIX); fputs_filtered ("->", stream); - fputs_filtered (&exp->elts[pc + 1].string, stream); + fputs_filtered (&exp->elts[pc + 2].string, stream); return; case BINOP_SUBSCRIPT: diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 392fec3..94b2567 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -291,53 +291,78 @@ allocate_stub_method (type) return (mtype); } +/* Create a range type using either a blank type supplied in RESULT_TYPE, + or creating a new type. Indices will be of type INDEX_TYPE, and will + range from LOW_BOUND to HIGH_BOUND, inclusive. + + FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make + sure it is TYPE_CODE_UNDEF before we bash it into a range type? */ + +struct type * +create_range_type (result_type, index_type, low_bound, high_bound) + struct type *result_type; + struct type *index_type; + int low_bound; + int high_bound; +{ + if (result_type == NULL) + { + result_type = alloc_type (TYPE_OBJFILE (index_type)); + } + TYPE_CODE (result_type) = TYPE_CODE_RANGE; + TYPE_TARGET_TYPE (result_type) = index_type; + TYPE_LENGTH (result_type) = TYPE_LENGTH (index_type); + TYPE_NFIELDS (result_type) = 2; + TYPE_FIELDS (result_type) = (struct field *) + TYPE_ALLOC (result_type, 2 * sizeof (struct field)); + memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field)); + TYPE_FIELD_BITPOS (result_type, 0) = low_bound; + TYPE_FIELD_BITPOS (result_type, 1) = high_bound; + TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int; /* FIXME */ + TYPE_FIELD_TYPE (result_type, 1) = builtin_type_int; /* FIXME */ + + return (result_type); +} + + /* Create an array type using either a blank type supplied in RESULT_TYPE, or creating a new type. Elements will be of type ELEMENT_TYPE, the - indices will be of type INDEX_TYPE, and will range from LOW_BOUND - to HIGH_BOUND, inclusive. + indices will be of type RANGE_TYPE. FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make sure it is TYPE_CODE_UNDEF before we bash it into an array type? */ struct type * -create_array_type (result_type, element_type, index_type, low_bound, - high_bound) +create_array_type (result_type, element_type, range_type) struct type *result_type; struct type *element_type; - struct type *index_type; - int low_bound; - int high_bound; + struct type *range_type; { - struct type *range_type; + int low_bound; + int high_bound; - /* Create a blank type if we are not given one to bash on. */ + if (TYPE_CODE (range_type) != TYPE_CODE_RANGE) + { + /* FIXME: We only handle range types at the moment. Complain and + create a dummy range type to use. */ + warning ("internal error: array index type must be a range type"); + range_type = lookup_fundamental_type (TYPE_OBJFILE (range_type), + FT_INTEGER); + range_type = create_range_type ((struct type *) NULL, range_type, 0, 0); + } if (result_type == NULL) { result_type = alloc_type (TYPE_OBJFILE (element_type)); } - - /* Create a range type. */ - range_type = alloc_type (TYPE_OBJFILE (element_type)); - TYPE_CODE (range_type) = TYPE_CODE_RANGE; - TYPE_TARGET_TYPE (range_type) = index_type; - TYPE_LENGTH (range_type) = sizeof (int); /* This should never be needed. */ - TYPE_NFIELDS (range_type) = 2; - TYPE_FIELDS (range_type) = (struct field *) - TYPE_ALLOC (range_type, 2 * sizeof (struct field)); - memset (TYPE_FIELDS (range_type), 0, 2 * sizeof (struct field)); - TYPE_FIELD_BITPOS (range_type, 0) = low_bound; - TYPE_FIELD_BITPOS (range_type, 1) = high_bound; - TYPE_FIELD_TYPE (range_type, 0) = builtin_type_int; /* FIXME */ - TYPE_FIELD_TYPE (range_type, 1) = builtin_type_int; /* FIXME */ - - /* Create the array type. */ TYPE_CODE (result_type) = TYPE_CODE_ARRAY; TYPE_TARGET_TYPE (result_type) = element_type; + low_bound = TYPE_FIELD_BITPOS (range_type, 0); + high_bound = TYPE_FIELD_BITPOS (range_type, 1); TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); TYPE_NFIELDS (result_type) = 1; - TYPE_FIELDS (result_type) = (struct field *) - TYPE_ALLOC (result_type, sizeof (struct field)); + TYPE_FIELDS (result_type) = + (struct field *) TYPE_ALLOC (result_type, sizeof (struct field)); memset (TYPE_FIELDS (result_type), 0, sizeof (struct field)); TYPE_FIELD_TYPE (result_type, 0) = range_type; TYPE_VPTR_FIELDNO (result_type) = -1; @@ -1072,8 +1097,6 @@ print_cplus_stuff (type, spaces) struct type *type; int spaces; { - int bitno; - printfi_filtered (spaces, "n_baseclasses %d\n", TYPE_N_BASECLASSES (type)); printfi_filtered (spaces, "nfn_fields %d\n", diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 50ea2bd..d15e0c4 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -195,6 +195,7 @@ struct type containing structure. For a function type, this is the position in the argument list of this argument. For a range bound or enum value, this is the value itself. + (FIXME: What about ranges larger than host int size?) For BITS_BIG_ENDIAN=1 targets, it is the bit offset to the MSB. For BITS_BIG_ENDIAN=0 targets, it is the bit offset to the LSB. */ @@ -583,8 +584,10 @@ extern struct type * lookup_function_type PARAMS ((struct type *)); extern struct type * -create_array_type PARAMS ((struct type *, struct type *, struct type *, int, - int)); +create_range_type PARAMS ((struct type *, struct type *, int, int)); + +extern struct type * +create_array_type PARAMS ((struct type *, struct type *, struct type *)); extern struct type * lookup_unsigned_typename PARAMS ((char *)); diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 89859fe..179aa98 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -847,7 +847,7 @@ unset_environment_command (var, from_tty) /* Handle the execution path (PATH variable) */ -const static char path_var_name[] = "PATH"; +static const char path_var_name[] = "PATH"; /* ARGSUSED */ static void diff --git a/gdb/infrun.c b/gdb/infrun.c index faae810..16404f3 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -510,6 +510,7 @@ wait_for_inferior () int remove_breakpoints_on_following_step = 0; int current_line; int handling_longjmp = 0; /* FIXME */ + struct symtab *symtab; sal = find_pc_line(prev_pc, 0); current_line = sal.line; @@ -972,8 +973,9 @@ wait_for_inferior () if (tmp != 0) stop_func_start = tmp; - if (find_pc_function (stop_func_start) != 0) - goto step_into_function; + symtab = find_pc_symtab (stop_pc); + if (symtab && LINETABLE (symtab)) + goto step_into_function; step_over_function: /* A subroutine call has happened. */ @@ -1198,9 +1200,6 @@ save_pc: void normal_stop () { - char *tem; - struct cmd_list_element *c; - /* Make sure that the current_frame's pc is correct. This is a correction for setting up the frame info before doing DECR_PC_AFTER_BREAK */ @@ -1301,6 +1300,7 @@ hook_stop_stub (cmd) char *cmd; { execute_user_command ((struct cmd_list_element *)cmd, 0); + return (0); } @@ -1695,7 +1695,7 @@ Pass means let program see this signal; otherwise program doesn't know.\n\ Ignore is a synonym for nopass and noignore is a synonym for pass.\n\ Pass and Stop may be combined."); - stop_command = add_cmd ("stop", class_pseudo, NO_FUNCTION, + stop_command = add_cmd ("stop", class_obscure, not_just_help_class_command, "There is no `stop' command, but you can set a hook on `stop'.\n\ This allows you to set a list of commands to be run each time execution\n\ of the inferior program stops.", &cmdlist); diff --git a/gdb/language.c b/gdb/language.c index 2c964d1..9d55936 100644 --- a/gdb/language.c +++ b/gdb/language.c @@ -1140,8 +1140,36 @@ unk_lang_create_fundamental_type (objfile, typeid) error ("internal error - unimplemented function unk_lang_create_fundamental_type called."); } +void +unk_lang_print_type (type, varstring, stream, show, level) + struct type *type; + char *varstring; + FILE *stream; + int show; + int level; +{ + error ("internal error - unimplemented function unk_lang_print_type called."); +} + +int +unk_lang_val_print (type, valaddr, address, stream, format, deref_ref, + recurse, pretty) + struct type *type; + char *valaddr; + CORE_ADDR address; + FILE *stream; + int format; + int deref_ref; + int recurse; + enum val_prettyprint pretty; +{ + error ("internal error - unimplemented function unk_lang_val_print called."); +} + static struct type ** const (unknown_builtin_types[]) = { 0 }; -static const struct op_print unk_op_print_tab[] = { 0 }; +static const struct op_print unk_op_print_tab[] = { + {NULL, 0, 0, 0} +}; const struct language_defn unknown_language_defn = { "unknown", @@ -1154,6 +1182,8 @@ const struct language_defn unknown_language_defn = { unk_lang_printchar, /* Print character constant */ unk_lang_printstr, unk_lang_create_fundamental_type, + unk_lang_print_type, /* Print a type using appropriate syntax */ + unk_lang_val_print, /* Print a value using appropriate syntax */ &builtin_type_error, /* longest signed integral type */ &builtin_type_error, /* longest unsigned integral type */ &builtin_type_error, /* longest floating point type */ @@ -1177,6 +1207,8 @@ const struct language_defn auto_language_defn = { unk_lang_printchar, /* Print character constant */ unk_lang_printstr, unk_lang_create_fundamental_type, + unk_lang_print_type, /* Print a type using appropriate syntax */ + unk_lang_val_print, /* Print a value using appropriate syntax */ &builtin_type_error, /* longest signed integral type */ &builtin_type_error, /* longest unsigned integral type */ &builtin_type_error, /* longest floating point type */ @@ -1199,6 +1231,8 @@ const struct language_defn local_language_defn = { unk_lang_printchar, /* Print character constant */ unk_lang_printstr, unk_lang_create_fundamental_type, + unk_lang_print_type, /* Print a type using appropriate syntax */ + unk_lang_val_print, /* Print a value using appropriate syntax */ &builtin_type_error, /* longest signed integral type */ &builtin_type_error, /* longest unsigned integral type */ &builtin_type_error, /* longest floating point type */ diff --git a/gdb/language.h b/gdb/language.h index b5da171..0d54fba 100644 --- a/gdb/language.h +++ b/gdb/language.h @@ -98,33 +98,89 @@ struct language_format_info /* Structure tying together assorted information about a language. */ -struct language_defn { - char * la_name; /* Name of the language */ - enum language la_language; /* its symtab language-enum (defs.h) */ - struct type ** const - *la_builtin_type_vector; /* Its builtin types */ - enum range_check la_range_check; /* Default range checking */ - enum type_check la_type_check; /* Default type checking */ - int (*la_parser) PARAMS((void)); /* Parser function */ - void (*la_error) PARAMS ((char *)); /* Parser error function */ - void (*la_printchar) PARAMS ((int, FILE *)); - void (*la_printstr) PARAMS ((FILE *, char *, unsigned int, int)); - struct type *(*la_fund_type) PARAMS ((struct objfile *, int)); - struct type **la_longest_int; /* Longest signed integral type */ - struct type **la_longest_unsigned_int; /* Longest uns integral type */ - struct type **la_longest_float; /* Longest floating point type */ - struct language_format_info - la_binary_format; /* Base 2 (binary) formats. */ - struct language_format_info - la_octal_format; /* Base 8 (octal) formats. */ - struct language_format_info - la_decimal_format; /* Base 10 (decimal) formats */ - struct language_format_info - la_hex_format; /* Base 16 (hexadecimal) formats */ - const struct op_print - *la_op_print_tab; /* Table for printing expressions */ -/* Add fields above this point, so the magic number is always last. */ - long la_magic; /* Magic number for compat checking */ +struct language_defn +{ + /* Name of the language */ + + char *la_name; + + /* its symtab language-enum (defs.h) */ + + enum language la_language; + + /* Its builtin types */ + + struct type ** const *la_builtin_type_vector; + + /* Default range checking */ + + enum range_check la_range_check; + + /* Default type checking */ + + enum type_check la_type_check; + + /* Parser function. */ + + int (*la_parser) PARAMS((void)); + + /* Parser error function */ + + void (*la_error) PARAMS ((char *)); + + void (*la_printchar) PARAMS ((int, FILE *)); + + void (*la_printstr) PARAMS ((FILE *, char *, unsigned int, int)); + + struct type *(*la_fund_type) PARAMS ((struct objfile *, int)); + + /* Print a type using syntax appropriate for this language. */ + + void (*la_print_type) PARAMS ((struct type *, char *, FILE *, int, int)); + + /* Print a value using syntax appropriate for this language. */ + + int (*la_val_print) PARAMS ((struct type *, char *, CORE_ADDR, FILE *, + int, int, int, enum val_prettyprint)); + + /* Longest signed integral type */ + + struct type **la_longest_int; + + /* Longest unsigned integral type */ + + struct type **la_longest_unsigned_int; + + /* Longest floating point type */ + + struct type **la_longest_float; + + /* Base 2 (binary) formats. */ + + struct language_format_info la_binary_format; + + /* Base 8 (octal) formats. */ + + struct language_format_info la_octal_format; + + /* Base 10 (decimal) formats */ + + struct language_format_info la_decimal_format; + + /* Base 16 (hexadecimal) formats */ + + struct language_format_info la_hex_format; + + + /* Table for printing expressions */ + + const struct op_print *la_op_print_tab; + + /* Add fields above this point, so the magic number is always last. */ + /* Magic number for compat checking */ + + long la_magic; + }; #define LANG_MAGIC 910823L @@ -181,6 +237,13 @@ set_language PARAMS ((enum language)); #define create_fundamental_type(objfile,typeid) \ (current_language->la_fund_type(objfile, typeid)) +#define LA_PRINT_TYPE(type,varstring,stream,show,level) \ + (current_language->la_print_type(type,varstring,stream,show,level)) + +#define LA_VAL_PRINT(type,valaddr,addr,stream,fmt,deref,recurse,pretty) \ + (current_language->la_val_print(type,valaddr,addr,stream,fmt,deref, \ + recurse,pretty)) + /* Return a format string for printf that will print a number in one of the local (language-specific) formats. Result is static and is overwritten by the next call. Takes printf options like "08" or "l" @@ -222,9 +285,9 @@ set_language PARAMS ((enum language)); #define local_hex_format_suffix() \ (current_language->la_hex_format.la_format_suffix) -#define local_printchar(ch, stream) \ +#define LA_PRINT_CHAR(ch, stream) \ (current_language->la_printchar(ch, stream)) -#define local_printstr(stream, string, length, force_ellipses) \ +#define LA_PRINT_STRING(stream, string, length, force_ellipses) \ (current_language->la_printstr(stream, string, length, force_ellipses)) /* Test a character to decide whether it can be printed in literal form diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c index cc1c06c..e059ca2 100644 --- a/gdb/m2-lang.c +++ b/gdb/m2-lang.c @@ -200,7 +200,6 @@ m2_create_fundamental_type (objfile, typeid) int typeid; { register struct type *type = NULL; - register int nbytes; switch (typeid) { @@ -351,7 +350,7 @@ m2_create_fundamental_type (objfile, typeid) /* Table of operators and their precedences for printing expressions. */ -const static struct op_print m2_op_print_tab[] = { +static const struct op_print m2_op_print_tab[] = { {"+", BINOP_ADD, PREC_ADD, 0}, {"+", UNOP_PLUS, PREC_PREFIX, 0}, {"-", BINOP_SUB, PREC_ADD, 0}, @@ -404,6 +403,8 @@ const struct language_defn m2_language_defn = { m2_printchar, /* Print character constant */ m2_printstr, /* function to print string constant */ m2_create_fundamental_type, /* Create fundamental type in this language */ + m2_print_type, /* Print a type using appropriate syntax */ + m2_val_print, /* Print a value using appropriate syntax */ &builtin_type_m2_int, /* longest signed integral type */ &builtin_type_m2_card, /* longest unsigned integral type */ &builtin_type_m2_real, /* longest floating point type */ diff --git a/gdb/m2-lang.h b/gdb/m2-lang.h index 1de31fe..4bc57f5 100644 --- a/gdb/m2-lang.h +++ b/gdb/m2-lang.h @@ -22,3 +22,10 @@ m2_parse PARAMS ((void)); /* Defined in m2-exp.y */ extern void m2_error PARAMS ((char *)); /* Defined in m2-exp.y */ + +extern void /* Defined in m2-typeprint.c */ +m2_print_type PARAMS ((struct type *, char *, FILE *, int, int)); + +extern int +m2_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, + int, enum val_prettyprint)); diff --git a/gdb/m2-typeprint.c b/gdb/m2-typeprint.c new file mode 100644 index 0000000..ef66a80 --- /dev/null +++ b/gdb/m2-typeprint.c @@ -0,0 +1,49 @@ +/* Support for printing Modula 2 types for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "bfd.h" /* Binary File Description */ +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "value.h" +#include "gdbcore.h" +#include "target.h" +#include "command.h" +#include "gdbcmd.h" +#include "language.h" +#include "demangle.h" +#include "m2-lang.h" + +#include <string.h> +#include <errno.h> + +void +m2_print_type (type, varstring, stream, show, level) + struct type *type; + char *varstring; + FILE *stream; + int show; + int level; +{ + extern void c_print_type PARAMS ((struct type *, char *, FILE *, int, int)); + + c_print_type (type, varstring, stream, show, level); /* FIXME */ +} diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c new file mode 100644 index 0000000..fc17ea5 --- /dev/null +++ b/gdb/m2-valprint.c @@ -0,0 +1,45 @@ +/* Support for printing Modula 2 values for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "symtab.h" +#include "gdbtypes.h" +#include "valprint.h" + +/* FIXME: For now, just explicitly declare c_val_print and use it instead */ + +int +m2_val_print (type, valaddr, address, stream, format, deref_ref, recurse, + pretty) + struct type *type; + char *valaddr; + CORE_ADDR address; + FILE *stream; + int format; + int deref_ref; + int recurse; + enum val_prettyprint pretty; +{ + extern int + c_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *, int, int, + int, enum val_prettyprint)); + return (c_val_print (type, valaddr, address, stream, format, deref_ref, + recurse, pretty)); +} @@ -898,7 +898,6 @@ execute_command (p, from_tty) int from_tty; { register struct cmd_list_element *c; - register struct command_line *cmdlines; register enum language flang; static int warned = 0; @@ -2072,7 +2071,7 @@ echo_command (text, from_tty) register int c; if (text) - while (c = *p++) + while ((c = *p++) != '\0') { if (c == '\\') { diff --git a/gdb/mipsread.c b/gdb/mipsread.c index 0760f1e..3225b1d 100644 --- a/gdb/mipsread.c +++ b/gdb/mipsread.c @@ -1555,7 +1555,8 @@ upgrade_type(tpp, tq, ax, bigend) return 0; case tqArray: - /* We should probably try to use create_array_type here. FIXME! */ + /* We should probably try to use create_range_type and + create_array_type here. FIXME! */ off = 0; t = init_type(TYPE_CODE_ARRAY, 0, 0, (char *) NULL, (struct objfile *) NULL); diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 0434df4..33d2300 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -137,18 +137,6 @@ static void display_command PARAMS ((char *, int)); static void -ptype_command PARAMS ((char *, int)); - -static struct type * -ptype_eval PARAMS ((struct expression *)); - -static void -whatis_command PARAMS ((char *, int)); - -static void -whatis_exp PARAMS ((char *, int)); - -static void x_command PARAMS ((char *, int)); static void @@ -445,9 +433,9 @@ print_scalar_formatted (valaddr, type, format, size, stream) case 'd': #ifdef LONG_LONG - fprintf_filtered (stream, "%lld", val_long); + fprintf_filtered (stream, local_decimal_format_custom("ll"), val_long); #else - fprintf_filtered (stream, "%d", val_long); + fprintf_filtered (stream, local_decimal_format(), val_long); #endif break; @@ -531,7 +519,9 @@ print_scalar_formatted (valaddr, type, format, size, stream) if (*cp == '\0') cp--; } + fprintf_filtered (stream, local_binary_format_prefix()); fprintf_filtered (stream, cp); + fprintf_filtered (stream, local_binary_format_suffix()); } break; @@ -1052,94 +1042,7 @@ x_command (exp, from_tty) set_internalvar (lookup_internalvar ("__"), last_examine_value); } } - -/* Commands for printing types of things. */ -/* Print type of EXP, or last thing in value history if EXP == NULL. - show is passed to type_print. */ -static void -whatis_exp (exp, show) - char *exp; - int show; -{ - struct expression *expr; - register value val; - register struct cleanup *old_chain; - - if (exp) - { - expr = parse_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - val = evaluate_type (expr); - } - else - val = access_value_history (0); - - printf_filtered ("type = "); - type_print (VALUE_TYPE (val), "", stdout, show); - printf_filtered ("\n"); - - if (exp) - do_cleanups (old_chain); -} - -/* ARGSUSED */ -static void -whatis_command (exp, from_tty) - char *exp; - int from_tty; -{ - /* Most of the time users do not want to see all the fields - in a structure. If they do they can use the "ptype" command. - Hence the "-1" below. */ - whatis_exp (exp, -1); -} - -/* Simple subroutine for ptype_command. */ -static -struct type * -ptype_eval(exp) - struct expression *exp; -{ - if(exp->elts[0].opcode==OP_TYPE) - return exp->elts[1].type; - else - return 0; -} - -/* TYPENAME is either the name of a type, or an expression. */ -/* ARGSUSED */ -static void -ptype_command (typename, from_tty) - char *typename; - int from_tty; -{ - register struct type *type; - struct expression *expr; - register struct cleanup *old_chain; - - if (typename) - { - expr = parse_expression (typename); - old_chain = make_cleanup (free_current_contents, &expr); - type = ptype_eval (expr); - - if(type) - { - printf_filtered ("type = "); - type_print (type, "", stdout, 1); - printf_filtered ("\n"); - do_cleanups (old_chain); - } - else - { - do_cleanups (old_chain); - whatis_exp (typename, 1); - } - } - else - whatis_exp (typename, 1); -} /* Add an expression to the auto-display chain. Specify the expression. */ @@ -1211,7 +1114,7 @@ clear_displays () { register struct display *d; - while (d = display_chain) + while ((d = display_chain) != NULL) { free ((PTR)d->exp); display_chain = d->next; @@ -1583,18 +1486,17 @@ print_frame_args (func, fi, num, stream) continue; } - /* We have to re-look-up the symbol because arguments often have + /* If the symbol name is non-null, + we have to re-look-up the symbol because arguments often have two entries (one a parameter, one a register or local), and the one we want is the non-parm, which lookup_symbol will find for - us. After this, sym could be any SYMBOL_CLASS... */ -#ifdef IBM6000_TARGET - /* AIX/RS6000 implements a concept of traceback tables, in which case - it creates nameless parameters. Looking for those parameter symbols - will result in an error. */ + us. After this, sym could be any SYMBOL_CLASS... - if ( *SYMBOL_NAME (sym)) -#endif - sym = lookup_symbol (SYMBOL_NAME (sym), + Null parameter names occur on the RS/6000, for traceback tables. + FIXME, should we even print them? */ + + if (*SYMBOL_NAME (sym)) + sym = lookup_symbol (SYMBOL_NAME (sym), b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL); /* Print the current arg. */ @@ -2006,15 +1908,6 @@ Default is the function surrounding the pc of the selected frame.\n\ With a single argument, the function surrounding that address is dumped.\n\ Two arguments are taken as a range of memory to dump."); - add_com ("ptype", class_vars, ptype_command, - "Print definition of type TYPE.\n\ -Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ -or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\ -The selected stack frame's lexical context is used to look up the name."); - - add_com ("whatis", class_vars, whatis_command, - "Print data type of expression EXP."); - #if 0 add_com ("whereis", class_vars, whereis_command, "Print line number and file of definition of variable."); diff --git a/gdb/ser-bsd.c b/gdb/ser-bsd.c index befc961..a7414d7 100644 --- a/gdb/ser-bsd.c +++ b/gdb/ser-bsd.c @@ -69,8 +69,6 @@ int serial_open(name) const char *name; { - struct sgttyb sgttyb; - desc = open (name, O_RDWR); if (desc < 0) error("Open of %s failed: %s", name, safe_strerror(errno)); diff --git a/gdb/source.c b/gdb/source.c index 3869e1a..982e7df 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -427,9 +427,10 @@ source_info (ignore, from_tty) if (s->fullname) printf_filtered ("Located in %s\n", s->fullname); if (s->nlines) - printf_filtered ("Contains %d lines\n", s->nlines); + printf_filtered ("Contains %d line%s.\n", s->nlines, + s->nlines == 1 ? "" : "s"); - printf_filtered("Source language %s.\n", language_str (s->language)); + printf_filtered("Source language is %s.\n", language_str (s->language)); } @@ -610,13 +611,15 @@ find_source_lines (s, desc) int desc; { struct stat st; - char c; register char *data, *p, *end; int nlines = 0; int lines_allocated = 1000; int *line_charpos; long exec_mtime; int size; +#ifdef LSEEK_NOT_LINEAR + char c; +#endif line_charpos = (int *) xmmalloc (s -> objfile -> md, lines_allocated * sizeof (int)); @@ -779,6 +782,8 @@ identify_source_line (s, line, mid_statement) get_filename_and_charpos (s, (char **)NULL); if (s->fullname == 0) return 0; + if (line >= s->nlines) + return 0; printf ("\032\032%s:%d:%d:%s:0x%x\n", s->fullname, line, s->line_charpos[line - 1], mid_statement ? "middle" : "beg", diff --git a/gdb/stabsread.c b/gdb/stabsread.c index ec7900b..65ca574 100644 --- a/gdb/stabsread.c +++ b/gdb/stabsread.c @@ -1073,7 +1073,7 @@ read_type (pp, objfile) /* Copy the prefix. */ from = prefix; - while (*to++ = *from++) + while ((*to++ = *from++) != '\0') ; to--; @@ -2372,7 +2372,9 @@ read_array_type (pp, type, objfile) upper = -1; } - type = create_array_type (type, element_type, index_type, lower, upper); + range_type = + create_range_type ((struct type *) NULL, index_type, lower, upper); + type = create_array_type (type, element_type, range_type); /* If we have an array whose element type is not yet known, but whose bounds *are* known, record it to be adjusted at the end of the file. */ @@ -2745,6 +2747,7 @@ read_range_type (pp, typenums, objfile) int n2bits, n3bits; int self_subrange; struct type *result_type; + struct type *index_type; /* First comes a type we are a subrange of. In C it is usually 0, 1 or the type being defined. */ @@ -2903,26 +2906,15 @@ read_range_type (pp, typenums, objfile) if (self_subrange) return error_type (pp); - result_type = alloc_type (objfile); - - TYPE_CODE (result_type) = TYPE_CODE_RANGE; - - TYPE_TARGET_TYPE (result_type) = *dbx_lookup_type(rangenums); - if (TYPE_TARGET_TYPE (result_type) == 0) { - complain (&range_type_base_complaint, rangenums[1]); - TYPE_TARGET_TYPE (result_type) = lookup_fundamental_type (objfile, FT_INTEGER); - } - - TYPE_NFIELDS (result_type) = 2; - TYPE_FIELDS (result_type) = (struct field *) - TYPE_ALLOC (result_type, 2 * sizeof (struct field)); - memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field)); - TYPE_FIELD_BITPOS (result_type, 0) = n2; - TYPE_FIELD_BITPOS (result_type, 1) = n3; - - TYPE_LENGTH (result_type) = TYPE_LENGTH (TYPE_TARGET_TYPE (result_type)); + index_type = *dbx_lookup_type (rangenums); + if (index_type == NULL) + { + complain (&range_type_base_complaint, rangenums[1]); + index_type = lookup_fundamental_type (objfile, FT_INTEGER); + } - return result_type; + result_type = create_range_type ((struct type *) NULL, index_type, n2, n3); + return (result_type); } /* Read a number from the string pointed to by *PP. diff --git a/gdb/symmisc.c b/gdb/symmisc.c index 73d72e8..be9d6e0 100644 --- a/gdb/symmisc.c +++ b/gdb/symmisc.c @@ -55,9 +55,6 @@ dump_msymbols PARAMS ((struct objfile *, FILE *)); static void dump_objfile PARAMS ((struct objfile *)); -static void -printobjfiles_command PARAMS ((char *, int)); - static int block_depth PARAMS ((struct block *)); @@ -65,19 +62,11 @@ static void print_partial_symbol PARAMS ((struct partial_symbol *, int, char *, FILE *)); static void -printpsyms_command PARAMS ((char *, int)); - -static void print_symbol PARAMS ((struct symbol *, int, FILE *)); static void -printsyms_command PARAMS ((char *, int)); - -static void free_symtab_block PARAMS ((struct objfile *, struct block *)); -static void -printmsyms_command PARAMS ((char *, int)); /* Free a struct block <- B and all the symbols defined in that block. */ @@ -152,6 +141,8 @@ free_symtab (s) mfree (s -> objfile -> md, (PTR) s); } +#if MAINTENANCE_CMDS + static void dump_objfile (objfile) struct objfile *objfile; @@ -267,11 +258,12 @@ dump_psymtab (objfile, psymtab, outfile) /* FIXME, we need to be able to print the relocation stuff. */ /* This prints some garbage for anything but stabs right now. FIXME. */ - fprintf_filtered (outfile, " Relocate symbols by 0x%x, 0x%x, 0x%x, 0x%x.\n", - ANOFFSET (psymtab->section_offsets, 0), - ANOFFSET (psymtab->section_offsets, 1), - ANOFFSET (psymtab->section_offsets, 2), - ANOFFSET (psymtab->section_offsets, 3)); + if (psymtab->section_offsets) + fprintf_filtered (outfile, " Relocate symbols by 0x%x, 0x%x, 0x%x, 0x%x.\n", + ANOFFSET (psymtab->section_offsets, 0), + ANOFFSET (psymtab->section_offsets, 1), + ANOFFSET (psymtab->section_offsets, 2), + ANOFFSET (psymtab->section_offsets, 3)); fprintf_filtered (outfile, " Symbols cover text addresses 0x%x-0x%x\n", psymtab -> textlow, psymtab -> texthigh); @@ -334,6 +326,8 @@ dump_symtab (objfile, symtab, outfile) fprintf (outfile, " (under 0x%x)", (unsigned int) BLOCK_SUPERBLOCK (b)); if (BLOCK_FUNCTION (b)) fprintf (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b))); + if (BLOCK_GCC_COMPILED(b)) + fprintf (outfile, " gcc%d compiled", BLOCK_GCC_COMPILED(b)); fputc ('\n', outfile); blen = BLOCK_NSYMS (b); for (j = 0; j < blen; j++) @@ -344,8 +338,8 @@ dump_symtab (objfile, symtab, outfile) fprintf (outfile, "\n"); } -static void -printsyms_command (args, from_tty) +void +maintenance_print_symbols (args, from_tty) char *args; int from_tty; { @@ -361,7 +355,7 @@ printsyms_command (args, from_tty) if (args == NULL) { - error ("printsyms takes an output file name and optional symbol file name"); + error ("print-symbols takes an output file name and optional symbol file name"); } else if ((argv = buildargv (args)) == NULL) { @@ -412,7 +406,7 @@ print_symbol (symbol, depth, outfile) { if (TYPE_NAME (SYMBOL_TYPE (symbol))) { - type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth); + LA_PRINT_TYPE (SYMBOL_TYPE (symbol), "", outfile, 1, depth); } else { @@ -422,7 +416,7 @@ print_symbol (symbol, depth, outfile) : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT ? "struct" : "union")), SYMBOL_NAME (symbol)); - type_print_1 (SYMBOL_TYPE (symbol), "", outfile, 1, depth); + LA_PRINT_TYPE (SYMBOL_TYPE (symbol), "", outfile, 1, depth); } fprintf (outfile, ";\n"); } @@ -433,9 +427,9 @@ print_symbol (symbol, depth, outfile) if (SYMBOL_TYPE (symbol)) { /* Print details of types, except for enums where it's clutter. */ - type_print_1 (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol), outfile, - TYPE_CODE (SYMBOL_TYPE (symbol)) != TYPE_CODE_ENUM, - depth); + LA_PRINT_TYPE (SYMBOL_TYPE (symbol), SYMBOL_NAME (symbol), outfile, + TYPE_CODE (SYMBOL_TYPE (symbol)) != TYPE_CODE_ENUM, + depth); fprintf (outfile, "; "); } else @@ -533,8 +527,8 @@ print_symbol (symbol, depth, outfile) fprintf (outfile, "\n"); } -static void -printpsyms_command (args, from_tty) +void +maintenance_print_psymbols (args, from_tty) char *args; int from_tty; { @@ -550,7 +544,7 @@ printpsyms_command (args, from_tty) if (args == NULL) { - error ("printpsyms takes an output file name and optional symbol file name"); + error ("print-psymbols takes an output file name and optional symbol file name"); } else if ((argv = buildargv (args)) == NULL) { @@ -665,8 +659,8 @@ print_partial_symbol (p, count, what, outfile) } } -static void -printmsyms_command (args, from_tty) +void +maintenance_print_msymbols (args, from_tty) char *args; int from_tty; { @@ -681,7 +675,7 @@ printmsyms_command (args, from_tty) if (args == NULL) { - error ("printmsyms takes an output file name and optional symbol file name"); + error ("print-msymbols takes an output file name and optional symbol file name"); } else if ((argv = buildargv (args)) == NULL) { @@ -716,8 +710,8 @@ printmsyms_command (args, from_tty) do_cleanups (cleanups); } -static void -printobjfiles_command (ignore, from_tty) +void +maintenance_print_objfiles (ignore, from_tty) char *ignore; int from_tty; { @@ -730,6 +724,7 @@ printobjfiles_command (ignore, from_tty) dump_objfile (objfile); immediate_quit--; } + /* Return the nexting depth of a block within other blocks in its symtab. */ @@ -738,10 +733,15 @@ block_depth (block) struct block *block; { register int i = 0; - while (block = BLOCK_SUPERBLOCK (block)) i++; + while ((block = BLOCK_SUPERBLOCK (block)) != NULL) + { + i++; + } return i; } +#endif /* MAINTENANCE_CMDS */ + /* Increase the space allocated for LISTP, which is probably global_psymbol_list or static_psymbol_list. This space will eventually @@ -829,20 +829,3 @@ add_psymbol_addr_to_list (name, namelength, namespace, class, listp, psymval) } #endif /* DEBUG */ - -void -_initialize_symmisc () -{ - add_com ("printmsyms", class_obscure, printmsyms_command, - "Print dump of current minimal symbol definitions to file OUTFILE.\n\ -If a SOURCE file is specified, dump only that file's symbols."); - add_com ("printpsyms", class_obscure, printpsyms_command, - "Print dump of current partial symbol definitions to file OUTFILE.\n\ -If a SOURCE file is specified, dump only that file's partial symbols."); - add_com ("printsyms", class_obscure, printsyms_command, - "Print dump of current symbol definitions to file OUTFILE.\n\ -If a SOURCE file is specified, dump only that file's symbols."); - add_com ("printobjfiles", class_obscure, printobjfiles_command, - "Print dump of current object file definitions."); -} - diff --git a/gdb/symtab.c b/gdb/symtab.c index d27e8a8..7e6c022 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -1145,7 +1145,7 @@ find_pc_line (pc, notcurrent) val.pc = best->pc; if (best_end && (!alt || best_end < alt->pc)) val.end = best_end; - else if (alt->pc) + else if (alt) val.end = alt->pc; else val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)); @@ -2352,7 +2352,7 @@ list_symbols (regexp, class, bpt) /* Typedef that is not a C++ class */ if (class == 2 && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE) - typedef_print (SYMBOL_TYPE(sym), sym, stdout); + c_typedef_print (SYMBOL_TYPE(sym), sym, stdout); /* variable, func, or typedef-that-is-c++-class */ else if (class < 2 || (class == 2 && @@ -2367,13 +2367,15 @@ list_symbols (regexp, class, bpt) } else { -# if 0 -/* FIXME, why is this zapped out? */ +# if 0 /* FIXME, why is this zapped out? */ char buf[1024]; - type_print_base (TYPE_FN_FIELD_TYPE(t, i), stdout, 0, 0); - type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), stdout, 0); + c_type_print_base (TYPE_FN_FIELD_TYPE(t, i), + stdout, 0, 0); + c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i), + stdout, 0); sprintf (buf, " %s::", type_name_no_tag (t)); - type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), buf, name, stdout); + cp_type_print_method_args (TYPE_FN_FIELD_ARGS (t, i), + buf, name, stdout); # endif } } diff --git a/gdb/typeprint.c b/gdb/typeprint.c new file mode 100644 index 0000000..d82265b --- /dev/null +++ b/gdb/typeprint.c @@ -0,0 +1,305 @@ +/* Language independent support for printing types for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include "obstack.h" +#include "bfd.h" /* Binary File Description */ +#include "symtab.h" +#include "gdbtypes.h" +#include "expression.h" +#include "value.h" +#include "gdbcore.h" +#include "command.h" +#include "gdbcmd.h" +#include "target.h" +#include "language.h" +#include "demangle.h" + +#include <string.h> +#include <errno.h> + +static void +ptype_command PARAMS ((char *, int)); + +static struct type * +ptype_eval PARAMS ((struct expression *)); + +static void +whatis_command PARAMS ((char *, int)); + +static void +whatis_exp PARAMS ((char *, int)); + +/* Print a description of a type TYPE in the form of a declaration of a + variable named VARSTRING. (VARSTRING is demangled if necessary.) + Output goes to STREAM (via stdio). + If SHOW is positive, we show the contents of the outermost level + of structure even if there is a type name that could be used instead. + If SHOW is negative, we never show the details of elements' types. */ + +void +type_print (type, varstring, stream, show) + struct type *type; + char *varstring; + FILE *stream; + int show; +{ + LA_PRINT_TYPE (type, varstring, stream, show, 0); +} + +/* Print type of EXP, or last thing in value history if EXP == NULL. + show is passed to type_print. */ + +static void +whatis_exp (exp, show) + char *exp; + int show; +{ + struct expression *expr; + register value val; + register struct cleanup *old_chain; + + if (exp) + { + expr = parse_expression (exp); + old_chain = make_cleanup (free_current_contents, &expr); + val = evaluate_type (expr); + } + else + val = access_value_history (0); + + printf_filtered ("type = "); + type_print (VALUE_TYPE (val), "", stdout, show); + printf_filtered ("\n"); + + if (exp) + do_cleanups (old_chain); +} + +/* ARGSUSED */ +static void +whatis_command (exp, from_tty) + char *exp; + int from_tty; +{ + /* Most of the time users do not want to see all the fields + in a structure. If they do they can use the "ptype" command. + Hence the "-1" below. */ + whatis_exp (exp, -1); +} + +/* Simple subroutine for ptype_command. */ + +static struct type * +ptype_eval (exp) + struct expression *exp; +{ + if (exp->elts[0].opcode == OP_TYPE) + { + return (exp->elts[1].type); + } + else + { + return (NULL); + } +} + +/* TYPENAME is either the name of a type, or an expression. */ + +/* ARGSUSED */ +static void +ptype_command (typename, from_tty) + char *typename; + int from_tty; +{ + register struct type *type; + struct expression *expr; + register struct cleanup *old_chain; + + if (typename == NULL) + { + /* Print type of last thing in value history. */ + whatis_exp (typename, 1); + } + else + { + expr = parse_expression (typename); + old_chain = make_cleanup (free_current_contents, &expr); + type = ptype_eval (expr); + if (type != NULL) + { + /* User did "ptype <typename>" */ + printf_filtered ("type = "); + type_print (type, "", stdout, 1); + printf_filtered ("\n"); + do_cleanups (old_chain); + } + else + { + /* User did "ptype <symbolname>" */ + do_cleanups (old_chain); + whatis_exp (typename, 1); + } + } +} + +/* Print integral scalar data VAL, of type TYPE, onto stdio stream STREAM. + Used to print data from type structures in a specified type. For example, + array bounds may be characters or booleans in some languages, and this + allows the ranges to be printed in their "natural" form rather than as + decimal integer values. + + FIXME: This is here simply because only the type printing routines + currently use it, and it wasn't clear if it really belonged somewhere + else (like printcmd.c). There are a lot of other gdb routines that do + something similar, but they are generally concerned with printing values + that come from the inferior in target byte order and target size. */ + +void +print_type_scalar (type, val, stream) + struct type *type; + LONGEST val; + FILE *stream; +{ + unsigned int i; + unsigned len; + + switch (TYPE_CODE (type)) + { + + case TYPE_CODE_ENUM: + len = TYPE_NFIELDS (type); + for (i = 0; i < len; i++) + { + if (TYPE_FIELD_BITPOS (type, i) == val) + { + break; + } + } + if (i < len) + { + fputs_filtered (TYPE_FIELD_NAME (type, i), stream); + } + else + { +#ifdef LONG_LONG + fprintf_filtered (stream, "%lld", val); +#else + fprintf_filtered (stream, "%ld", val); +#endif + } + break; + + case TYPE_CODE_INT: +#ifdef LONG_LONG + fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%llu" : "%lld", val); +#else + fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d", val); +#endif + break; + + case TYPE_CODE_CHAR: + LA_PRINT_CHAR ((unsigned char) val, stream); + break; + + case TYPE_CODE_BOOL: + fprintf_filtered (stream, val ? "TRUE" : "FALSE"); + break; + + 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_RANGE: + case TYPE_CODE_PASCAL_ARRAY: + case TYPE_CODE_ERROR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_METHOD: + case TYPE_CODE_REF: + error ("internal error: unhandled type in print_type_scalar"); + break; + + default: + error ("Invalid type code in symbol table."); + } + fflush (stream); +} + +#if MAINTENANCE_CMDS + +/* Dump details of a type specified either directly or indirectly. + Uses the same sort of type lookup mechanism as ptype_command() + and whatis_command(). */ + +void +maintenance_print_type (typename, from_tty) + char *typename; + int from_tty; +{ + register value val; + register struct type *type; + register struct cleanup *old_chain; + struct expression *expr; + + if (typename != NULL) + { + expr = parse_expression (typename); + old_chain = make_cleanup (free_current_contents, &expr); + if (expr -> elts[0].opcode == OP_TYPE) + { + /* The user expression names a type directly, just use that type. */ + type = expr -> elts[1].type; + } + else + { + /* The user expression may name a type indirectly by naming an + object of that type. Find that indirectly named type. */ + val = evaluate_type (expr); + type = VALUE_TYPE (val); + } + if (type != NULL) + { + recursive_dump_type (type, 0); + } + do_cleanups (old_chain); + } +} + +#endif /* MAINTENANCE_CMDS */ + + +void +_initialize_typeprint () +{ + + add_com ("ptype", class_vars, ptype_command, + "Print definition of type TYPE.\n\ +Argument may be a type name defined by typedef, or \"struct STRUCTNAME\"\n\ +or \"union UNIONNAME\" or \"enum ENUMNAME\".\n\ +The selected stack frame's lexical context is used to look up the name."); + + add_com ("whatis", class_vars, whatis_command, + "Print data type of expression EXP."); + +} diff --git a/gdb/typeprint.h b/gdb/typeprint.h new file mode 100644 index 0000000..806f02f --- /dev/null +++ b/gdb/typeprint.h @@ -0,0 +1,23 @@ +/* Language independent support for printing types for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +void +print_type_scalar PARAMS ((struct type *type, LONGEST, FILE *)); + diff --git a/gdb/valprint.c b/gdb/valprint.c index 80dc89b..b2f62fd 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -34,6 +34,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Prototypes for local functions */ static void +print_hex_chars PARAMS ((FILE *, unsigned char *, unsigned int)); + +static void show_print PARAMS ((char *, int)); static void @@ -46,41 +49,7 @@ static void set_output_radix PARAMS ((char *, int, struct cmd_list_element *)); static void -type_print_base PARAMS ((struct type *, FILE *, int, int)); - -static void -type_print_args PARAMS ((struct type *, FILE *)); - -static void -type_print_varspec_suffix PARAMS ((struct type *, FILE *, int, int, int)); - -static void -type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); - -static void -type_print_derivation_info PARAMS ((FILE *, struct type *)); - -static void -type_print_method_args PARAMS ((struct type **, char *, char *, int, FILE *)); - -static void -cplus_val_print PARAMS ((struct type *, char *, FILE *, int, int, - enum val_prettyprint, struct type **)); - -static void -val_print_fields PARAMS ((struct type *, char *, FILE *, int, int, - enum val_prettyprint, struct type **)); - -static int -is_vtbl_member PARAMS ((struct type *)); - -static int -is_vtbl_ptr_type PARAMS ((struct type *)); - -static void -print_hex_chars PARAMS ((FILE *, unsigned char *, unsigned)); - -extern int demangle; /* whether to print C++ syms raw or source-form */ +value_print_array_elements PARAMS ((value, FILE *, int, enum val_prettyprint)); /* Maximum number of chars to print for a string pointer value or vector contents, or UINT_MAX for no limit. */ @@ -99,127 +68,69 @@ int output_format = 0; unsigned int repeat_count_threshold = 10; -/* Define a mess of print controls. */ +int prettyprint_structs; /* Controls pretty printing of structures */ +int prettyprint_arrays; /* Controls pretty printing of arrays. */ -int prettyprint; /* Controls pretty printing of structures */ -int vtblprint; /* Controls printing of vtbl's */ -int unionprint; /* Controls printing of nested unions. */ -int arrayprint; /* Controls pretty printing of arrays. */ -int addressprint; /* Controls pretty printing of addresses. */ -int objectprint; /* Controls looking up an object's derived type - using what we find in its vtables. */ +/* If nonzero, causes unions inside structures or other unions to be + printed. */ -struct obstack dont_print_obstack; - - -/* Print a floating point value of type TYPE, pointed to in GDB by VALADDR, - on STREAM. */ +int unionprint; /* Controls printing of nested unions. */ -void -print_floating (valaddr, type, stream) - char *valaddr; - struct type *type; - FILE *stream; -{ - double doub; - int inv; - unsigned len = TYPE_LENGTH (type); - -#if defined (IEEE_FLOAT) +/* If nonzero, causes machine addresses to be printed in certain contexts. */ - /* Check for NaN's. Note that this code does not depend on us being - on an IEEE conforming system. It only depends on the target - machine using IEEE representation. This means (a) - cross-debugging works right, and (2) IEEE_FLOAT can (and should) - be defined for systems like the 68881, which uses IEEE - representation, but is not IEEE conforming. */ +int addressprint; /* Controls printing of machine addresses */ - { - long low, high; - /* Is the sign bit 0? */ - int nonnegative; - /* Is it is a NaN (i.e. the exponent is all ones and - the fraction is nonzero)? */ - int is_nan; - - if (len == sizeof (float)) - { - /* It's single precision. */ - memcpy ((char *) &low, valaddr, sizeof (low)); - /* target -> host. */ - SWAP_TARGET_AND_HOST (&low, sizeof (float)); - nonnegative = low >= 0; - is_nan = ((((low >> 23) & 0xFF) == 0xFF) - && 0 != (low & 0x7FFFFF)); - low &= 0x7fffff; - high = 0; - } - else - { - /* It's double precision. Get the high and low words. */ + +/* Print data of type TYPE located at VALADDR (within GDB), + which came from the inferior at address ADDRESS, + onto stdio stream STREAM according to FORMAT + (a letter or 0 for natural format). The data at VALADDR + is in target byte order. -#if TARGET_BYTE_ORDER == BIG_ENDIAN - memcpy (&low, valaddr+4, sizeof (low)); - memcpy (&high, valaddr+0, sizeof (high)); -#else - memcpy (&low, valaddr+0, sizeof (low)); - memcpy (&high, valaddr+4, sizeof (high)); -#endif - SWAP_TARGET_AND_HOST (&low, sizeof (low)); - SWAP_TARGET_AND_HOST (&high, sizeof (high)); - nonnegative = high >= 0; - is_nan = (((high >> 20) & 0x7ff) == 0x7ff - && ! ((((high & 0xfffff) == 0)) && (low == 0))); - high &= 0xfffff; - } + If the data are a string pointer, returns the number of + sting characters printed. - if (is_nan) - { - /* The meaning of the sign and fraction is not defined by IEEE. - But the user might know what they mean. For example, they - (in an implementation-defined manner) distinguish between - signaling and quiet NaN's. */ - if (high) - fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonnegative, - high, low); - else - fprintf_filtered (stream, "-NaN(0x%lx)" + nonnegative, low); - return; - } - } -#endif /* IEEE_FLOAT. */ + if DEREF_REF is nonzero, then dereference references, + otherwise just print them like pointers. - doub = unpack_double (type, valaddr, &inv); - if (inv) - fprintf_filtered (stream, "<invalid float value>"); - else - fprintf_filtered (stream, len <= sizeof(float) ? "%.9g" : "%.17g", doub); -} + The PRETTY parameter controls prettyprinting. */ -/* VALADDR points to an integer of LEN bytes. Print it in hex on stream. */ -static void -print_hex_chars (stream, valaddr, len) +int +val_print (type, valaddr, address, stream, format, deref_ref, recurse, + pretty) + struct type *type; + char *valaddr; + CORE_ADDR address; FILE *stream; - unsigned char *valaddr; - unsigned len; + int format; + int deref_ref; + int recurse; + enum val_prettyprint pretty; { - unsigned char *p; + if (pretty == Val_pretty_default) + { + pretty = prettyprint_structs ? Val_prettyprint : Val_no_prettyprint; + } - fprintf_filtered (stream, "0x"); -#if TARGET_BYTE_ORDER == BIG_ENDIAN - for (p = valaddr; - p < valaddr + len; - p++) -#else /* Little endian. */ - for (p = valaddr + len - 1; - p >= valaddr; - p--) -#endif + QUIT; + + /* Ensure that the type is complete and not just a stub. If the type is + only a stub and we can't find and substitute its complete type, then + print appropriate string and return. Typical types that my be stubs + are structs, unions, and C++ methods. */ + + check_stub_type (type); + if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) { - fprintf_filtered (stream, "%02x", *p); + fprintf_filtered (stream, "<incomplete type>"); + fflush (stream); + return (0); } + + return (LA_VAL_PRINT (type, valaddr, address, stream, format, deref_ref, + recurse, pretty)); } - + /* Print the value VAL in C-ish syntax on stream STREAM. FORMAT is a format-letter, or 0 for print in natural format of data type. If the object printed is a string pointer, returns @@ -232,7 +143,7 @@ value_print (val, stream, format, pretty) int format; enum val_prettyprint pretty; { - register unsigned int i, n, typelen; + register unsigned int n, typelen; if (val == 0) { @@ -249,7 +160,7 @@ value_print (val, stream, format, pretty) They are made by the @ operator. Print such values as if they were arrays. */ - else if (VALUE_REPEATED (val)) + if (VALUE_REPEATED (val)) { n = VALUE_REPETITIONS (val); typelen = TYPE_LENGTH (VALUE_TYPE (val)); @@ -257,57 +168,13 @@ value_print (val, stream, format, pretty) /* Print arrays of characters using string syntax. */ if (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT && format == 0) - local_printstr (stream, VALUE_CONTENTS (val), n, 0); + LA_PRINT_STRING (stream, VALUE_CONTENTS (val), n, 0); else { - unsigned int things_printed = 0; - - for (i = 0; i < n && things_printed < print_max; i++) - { - /* 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; - - if (i != 0) - fprintf_filtered (stream, ", "); - wrap_here (""); - - rep1 = i + 1; - reps = 1; - while (rep1 < n - && !memcmp (VALUE_CONTENTS (val) + typelen * i, - VALUE_CONTENTS (val) + typelen * rep1, typelen)) - { - ++reps; - ++rep1; - } - - if (reps > repeat_count_threshold) - { - val_print (VALUE_TYPE (val), - VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, - stream, format, 1, 0, pretty); - fprintf (stream, " <repeats %u times>", reps); - i = rep1 - 1; - things_printed += repeat_count_threshold; - } - else - { - val_print (VALUE_TYPE (val), - VALUE_CONTENTS (val) + typelen * i, - VALUE_ADDRESS (val) + typelen * i, - stream, format, 1, 0, pretty); - things_printed++; - } - } - if (i < n) - fprintf_filtered (stream, "..."); + value_print_array_elements (val, stream, format, pretty); } fprintf_filtered (stream, "}"); - return n * typelen; + return (n * typelen); } else { @@ -319,15 +186,15 @@ value_print (val, stream, format, pretty) C++: if it is a member pointer, we will take care of that when we print it. */ - if (TYPE_CODE (type) == TYPE_CODE_PTR - || TYPE_CODE (type) == TYPE_CODE_REF) + if (TYPE_CODE (type) == TYPE_CODE_PTR || + TYPE_CODE (type) == TYPE_CODE_REF) { /* Hack: remove (char *) for char strings. Their type is indicated by the quoted string anyway. */ - if (TYPE_CODE (type) == TYPE_CODE_PTR - && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) - && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT - && !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type))) + if (TYPE_CODE (type) == TYPE_CODE_PTR && + TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) && + TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT && + !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type))) { /* Print nothing */ } @@ -338,310 +205,219 @@ value_print (val, stream, format, pretty) fprintf_filtered (stream, ") "); } } - return val_print (type, VALUE_CONTENTS (val), - VALUE_ADDRESS (val), stream, format, 1, 0, pretty); + return (val_print (type, VALUE_CONTENTS (val), + VALUE_ADDRESS (val), stream, format, 1, 0, pretty)); } } -/* Return truth value for assertion that TYPE is of the type - "pointer to virtual function". */ -static int -is_vtbl_ptr_type(type) - struct type *type; -{ - char *typename = type_name_no_tag (type); - static const char vtbl_ptr_name[] = - { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 }; - - return (typename != NULL && !strcmp(typename, vtbl_ptr_name)); -} - -/* Return truth value for the assertion that TYPE is of the type - "pointer to virtual function table". */ -static int -is_vtbl_member(type) - struct type *type; -{ - if (TYPE_CODE (type) == TYPE_CODE_PTR) - type = TYPE_TARGET_TYPE (type); - else - return 0; - - if (TYPE_CODE (type) == TYPE_CODE_ARRAY - && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT) - /* Virtual functions tables are full of pointers to virtual functions. */ - return is_vtbl_ptr_type (TYPE_TARGET_TYPE (type)); - return 0; -} - -/* Mutually recursive subroutines of cplus_val_print and val_print to print out - a structure's fields: val_print_fields and cplus_val_print. - - TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the - same meanings as in cplus_val_print and val_print. - - DONT_PRINT is an array of baseclass types that we - should not print, or zero if called from top level. */ +/* Called by various <lang>_val_print routines to print TYPE_CODE_INT's */ -static void -val_print_fields (type, valaddr, stream, format, recurse, pretty, dont_print) +void +val_print_type_code_int (type, valaddr, stream) struct type *type; char *valaddr; FILE *stream; - int format; - int recurse; - enum val_prettyprint pretty; - struct type **dont_print; { - int i, len, n_baseclasses; - - check_stub_type (type); - - fprintf_filtered (stream, "{"); - len = TYPE_NFIELDS (type); - n_baseclasses = TYPE_N_BASECLASSES (type); + char *p; + /* Pointer to first (i.e. lowest address) nonzero character. */ + char *first_addr; + unsigned int len; - /* Print out baseclasses such that we don't print - duplicates of virtual baseclasses. */ - if (n_baseclasses > 0) - cplus_val_print (type, valaddr, stream, format, recurse+1, pretty, dont_print); - - if (!len && n_baseclasses == 1) - fprintf_filtered (stream, "<No data fields>"); - else + if (TYPE_LENGTH (type) > sizeof (LONGEST)) { - extern int inspect_it; - int fields_seen = 0; - - for (i = n_baseclasses; i < len; i++) + if (TYPE_UNSIGNED (type)) { - /* Check if static field */ - if (TYPE_FIELD_STATIC (type, i)) - continue; - if (fields_seen) - fprintf_filtered (stream, ", "); - else if (n_baseclasses > 0) + /* First figure out whether the number in fact has zeros + in all its bytes more significant than least significant + sizeof (LONGEST) ones. */ + len = TYPE_LENGTH (type); + +#if TARGET_BYTE_ORDER == BIG_ENDIAN + for (p = valaddr; + len > sizeof (LONGEST) && p < valaddr + TYPE_LENGTH (type); + p++) +#else /* Little endian. */ + first_addr = valaddr; + for (p = valaddr + TYPE_LENGTH (type); + len > sizeof (LONGEST) && p >= valaddr; + p--) +#endif /* Little endian. */ { - if (pretty) + if (*p == 0) { - fprintf_filtered (stream, "\n"); - print_spaces_filtered (2 + 2 * recurse, stream); - fputs_filtered ("members of ", stream); - fputs_filtered (type_name_no_tag (type), stream); - fputs_filtered (": ", stream); + len--; } - } - fields_seen = 1; - - if (pretty) - { - fprintf_filtered (stream, "\n"); - print_spaces_filtered (2 + 2 * recurse, stream); - } - else - { - wrap_here (n_spaces (2 + 2 * recurse)); - } - if (inspect_it) - { - if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR) - fputs_filtered ("\"( ptr \"", stream); else - fputs_filtered ("\"( nodef \"", stream); - fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); - fputs_filtered ("\" \"", stream); - fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); - fputs_filtered ("\") \"", stream); - } - else - { - fprint_symbol (stream, TYPE_FIELD_NAME (type, i)); - fputs_filtered (" = ", stream); + { + break; + } } - if (TYPE_FIELD_PACKED (type, i)) +#if TARGET_BYTE_ORDER == BIG_ENDIAN + first_addr = p; +#endif + if (len <= sizeof (LONGEST)) { - value v; - - /* Bitfields require special handling, especially due to byte - order problems. */ - v = value_from_longest (TYPE_FIELD_TYPE (type, i), - unpack_field_as_long (type, valaddr, i)); - - val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0, - stream, format, 0, recurse + 1, pretty); + /* We can print it in decimal. */ + fprintf_filtered + (stream, +#if defined (LONG_LONG) + "%llu", +#else + "%lu", +#endif + unpack_long (BUILTIN_TYPE_LONGEST, first_addr)); } else { - val_print (TYPE_FIELD_TYPE (type, i), - valaddr + TYPE_FIELD_BITPOS (type, i) / 8, - 0, stream, format, 0, recurse + 1, pretty); + /* It is big, so print it in hex. */ + print_hex_chars (stream, (unsigned char *) first_addr, len); } } - if (pretty) + else { - fprintf_filtered (stream, "\n"); - print_spaces_filtered (2 * recurse, stream); + /* Signed. One could assume two's complement (a reasonable + assumption, I think) and do better than this. */ + print_hex_chars (stream, (unsigned char *) valaddr, + TYPE_LENGTH (type)); } } - fprintf_filtered (stream, "}"); -} + else + { +#ifdef PRINT_TYPELESS_INTEGER + PRINT_TYPELESS_INTEGER (stream, type, unpack_long (type, valaddr)); +#else + fprintf_filtered (stream, TYPE_UNSIGNED (type) ? +#if defined (LONG_LONG) + "%llu" : "%lld", +#else + "%u" : "%d", +#endif + unpack_long (type, valaddr)); +#endif + } +} -/* Special val_print routine to avoid printing multiple copies of virtual - baseclasses. */ +/* Print a floating point value of type TYPE, pointed to in GDB by VALADDR, + on STREAM. */ -static void -cplus_val_print (type, valaddr, stream, format, recurse, pretty, dont_print) - struct type *type; +void +print_floating (valaddr, type, stream) char *valaddr; + struct type *type; FILE *stream; - int format; - int recurse; - enum val_prettyprint pretty; - struct type **dont_print; { - struct obstack tmp_obstack; - struct type **last_dont_print - = (struct type **)obstack_next_free (&dont_print_obstack); - int i, n_baseclasses = TYPE_N_BASECLASSES (type); - - if (dont_print == 0) - { - /* If we're at top level, carve out a completely fresh - chunk of the obstack and use that until this particular - invocation returns. */ - tmp_obstack = dont_print_obstack; - /* Bump up the high-water mark. Now alpha is omega. */ - obstack_finish (&dont_print_obstack); - } - - for (i = 0; i < n_baseclasses; i++) - { - char *baddr; - int err; - - if (BASETYPE_VIA_VIRTUAL (type, i)) - { - struct type **first_dont_print - = (struct type **)obstack_base (&dont_print_obstack); - - int j = (struct type **)obstack_next_free (&dont_print_obstack) - - first_dont_print; + double doub; + int inv; + unsigned len = TYPE_LENGTH (type); + +#if defined (IEEE_FLOAT) - while (--j >= 0) - if (TYPE_BASECLASS (type, i) == first_dont_print[j]) - goto flush_it; + /* Check for NaN's. Note that this code does not depend on us being + on an IEEE conforming system. It only depends on the target + machine using IEEE representation. This means (a) + cross-debugging works right, and (2) IEEE_FLOAT can (and should) + be defined for systems like the 68881, which uses IEEE + representation, but is not IEEE conforming. */ - obstack_ptr_grow (&dont_print_obstack, TYPE_BASECLASS (type, i)); - } + { + long low, high; + /* Is the sign bit 0? */ + int nonnegative; + /* Is it is a NaN (i.e. the exponent is all ones and + the fraction is nonzero)? */ + int is_nan; - /* Fix to use baseclass_offset instead. FIXME */ - baddr = baseclass_addr (type, i, valaddr, 0, &err); - if (err == 0 && baddr == 0) - error ("could not find virtual baseclass `%s'\n", - type_name_no_tag (TYPE_BASECLASS (type, i))); + if (len == sizeof (float)) + { + /* It's single precision. */ + memcpy ((char *) &low, valaddr, sizeof (low)); + /* target -> host. */ + SWAP_TARGET_AND_HOST (&low, sizeof (float)); + nonnegative = low >= 0; + is_nan = ((((low >> 23) & 0xFF) == 0xFF) + && 0 != (low & 0x7FFFFF)); + low &= 0x7fffff; + high = 0; + } + else + { + /* It's double precision. Get the high and low words. */ - if (pretty) - { - fprintf_filtered (stream, "\n"); - print_spaces_filtered (2 * recurse, stream); - } - fputs_filtered ("<", stream); - fputs_filtered (type_name_no_tag (TYPE_BASECLASS (type, i)), stream); - fputs_filtered ("> = ", stream); - if (err != 0) - fprintf_filtered (stream, "<invalid address 0x%x>", baddr); - else - val_print_fields (TYPE_BASECLASS (type, i), baddr, stream, format, - recurse, pretty, - (struct type **)obstack_base (&dont_print_obstack)); - fputs_filtered (", ", stream); +#if TARGET_BYTE_ORDER == BIG_ENDIAN + memcpy (&low, valaddr+4, sizeof (low)); + memcpy (&high, valaddr+0, sizeof (high)); +#else + memcpy (&low, valaddr+0, sizeof (low)); + memcpy (&high, valaddr+4, sizeof (high)); +#endif + SWAP_TARGET_AND_HOST (&low, sizeof (low)); + SWAP_TARGET_AND_HOST (&high, sizeof (high)); + nonnegative = high >= 0; + is_nan = (((high >> 20) & 0x7ff) == 0x7ff + && ! ((((high & 0xfffff) == 0)) && (low == 0))); + high &= 0xfffff; + } - flush_it: - ; - } + if (is_nan) + { + /* The meaning of the sign and fraction is not defined by IEEE. + But the user might know what they mean. For example, they + (in an implementation-defined manner) distinguish between + signaling and quiet NaN's. */ + if (high) + fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonnegative, + high, low); + else + fprintf_filtered (stream, "-NaN(0x%lx)" + nonnegative, low); + return; + } + } +#endif /* IEEE_FLOAT. */ - if (dont_print == 0) - { - /* Free the space used to deal with the printing - of this type from top level. */ - obstack_free (&dont_print_obstack, last_dont_print); - /* Reset watermark so that we can continue protecting - ourselves from whatever we were protecting ourselves. */ - dont_print_obstack = tmp_obstack; - } + doub = unpack_double (type, valaddr, &inv); + if (inv) + fprintf_filtered (stream, "<invalid float value>"); + else + fprintf_filtered (stream, len <= sizeof(float) ? "%.9g" : "%.17g", doub); } +/* VALADDR points to an integer of LEN bytes. Print it in hex on stream. */ + static void -print_class_member (valaddr, domain, stream, prefix) - char *valaddr; - struct type *domain; +print_hex_chars (stream, valaddr, len) FILE *stream; - char *prefix; + unsigned char *valaddr; + unsigned len; { + unsigned char *p; - /* VAL is a byte offset into the structure type DOMAIN. - Find the name of the field for that offset and - print it. */ - int extra = 0; - int bits = 0; - register unsigned int i; - unsigned len = TYPE_NFIELDS (domain); - /* @@ Make VAL into bit offset */ - LONGEST val = unpack_long (builtin_type_int, valaddr) << 3; - for (i = TYPE_N_BASECLASSES (domain); i < len; i++) - { - int bitpos = TYPE_FIELD_BITPOS (domain, i); - QUIT; - if (val == bitpos) - break; - if (val < bitpos && i != 0) - { - /* Somehow pointing into a field. */ - i -= 1; - extra = (val - TYPE_FIELD_BITPOS (domain, i)); - if (extra & 0x7) - bits = 1; - else - extra >>= 3; - break; - } - } - if (i < len) + fprintf_filtered (stream, "0x"); +#if TARGET_BYTE_ORDER == BIG_ENDIAN + for (p = valaddr; + p < valaddr + len; + p++) +#else /* Little endian. */ + for (p = valaddr + len - 1; + p >= valaddr; + p--) +#endif { - char *name; - fprintf_filtered (stream, prefix); - name = type_name_no_tag (domain); - if (name) - fputs_filtered (name, stream); - else - type_print_base (domain, stream, 0, 0); - fprintf_filtered (stream, "::"); - fputs_filtered (TYPE_FIELD_NAME (domain, i), stream); - if (extra) - fprintf_filtered (stream, " + %d bytes", extra); - if (bits) - fprintf_filtered (stream, " (offset in bits)"); + fprintf_filtered (stream, "%02x", *p); } - else - fprintf_filtered (stream, "%d", val >> 3); } -/* Print data of type TYPE located at VALADDR (within GDB), - which came from the inferior at address ADDRESS, - onto stdio stream STREAM according to FORMAT - (a letter or 0 for natural format). The data at VALADDR - is in target byte order. +/* Called by various <lang>_val_print routines to print elements of an + array in the form "<elem1>, <elem2>, <elem3>, ...". - If the data are a string pointer, returns the number of - sting characters printed. + (FIXME?) Assumes array element separator is a comma, which is correct + for all languages currently handled. + (FIXME?) Some languages have a notation for repeated array elements, + perhaps we should try to use that notation when appropriate. + */ - if DEREF_REF is nonzero, then dereference references, - otherwise just print them like pointers. - - The PRETTY parameter controls prettyprinting. */ - -int -val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) +void +val_print_array_elements (type, valaddr, address, stream, format, deref_ref, + recurse, pretty, i) struct type *type; char *valaddr; CORE_ADDR address; @@ -650,1309 +426,125 @@ val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) int deref_ref; int recurse; enum val_prettyprint pretty; + unsigned int i; { - register unsigned int i; + unsigned int things_printed = 0; unsigned len; struct type *elttype; unsigned eltlen; - LONGEST val; - unsigned char c; - - if (pretty == Val_pretty_default) - { - pretty = prettyprint ? Val_prettyprint : Val_no_prettyprint; - } - - QUIT; - - check_stub_type (type); - - if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) - { - fprintf_filtered (stream, "<unknown struct>"); - fflush (stream); - return 0; - } - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - if (TYPE_LENGTH (type) > 0 - && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) - { - elttype = TYPE_TARGET_TYPE (type); - eltlen = TYPE_LENGTH (elttype); - len = TYPE_LENGTH (type) / eltlen; - if (arrayprint) - print_spaces_filtered (2 + 2 * recurse, stream); - fprintf_filtered (stream, "{"); - /* For an array of chars, print with string syntax. */ - if (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT - && (format == 0 || format == 's') ) - local_printstr (stream, valaddr, len, 0); - else - { - unsigned int things_printed = 0; + /* 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; + + elttype = TYPE_TARGET_TYPE (type); + eltlen = TYPE_LENGTH (elttype); + len = TYPE_LENGTH (type) / eltlen; - /* If this is a virtual function table, print the 0th - entry specially, and the rest of the members normally. */ - if (is_vtbl_ptr_type (elttype)) - { - fprintf_filtered (stream, "%d vtable entries", len-1); - i = 1; - } - else - i = 0; - - for (; i < len && things_printed < print_max; i++) - { - /* 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; - - if (i != 0) - if (arrayprint) - { - fprintf_filtered (stream, ",\n"); - print_spaces_filtered (2 + 2 * recurse, stream); - } - else - fprintf_filtered (stream, ", "); - wrap_here (n_spaces (2 + 2 * recurse)); - - rep1 = i + 1; - reps = 1; - while (rep1 < len - && !memcmp (valaddr + i * eltlen, - valaddr + rep1 * eltlen, eltlen)) - { - ++reps; - ++rep1; - } - - if (reps > repeat_count_threshold) - { - val_print (elttype, valaddr + i * eltlen, - 0, stream, format, deref_ref, - recurse + 1, pretty); - fprintf_filtered (stream, " <repeats %u times>", reps); - i = rep1 - 1; - things_printed += repeat_count_threshold; - } - else - { - val_print (elttype, valaddr + i * eltlen, - 0, stream, format, deref_ref, - recurse + 1, pretty); - things_printed++; - } - } - if (i < len) - fprintf_filtered (stream, "..."); - } - fprintf_filtered (stream, "}"); - break; - } - /* Array of unspecified length: treat like pointer to first elt. */ - valaddr = (char *) &address; - - case TYPE_CODE_PTR: - if (format && format != 's') - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_METHOD) + for (; i < len && things_printed < print_max; i++) + { + if (i != 0) { - struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)); - struct fn_field *f; - int j, len2; - char *kind = ""; - CORE_ADDR addr; - - addr = unpack_pointer (lookup_pointer_type (builtin_type_void), - valaddr); - if (METHOD_PTR_IS_VIRTUAL(addr)) + if (prettyprint_arrays) { - int offset = METHOD_PTR_TO_VOFFSET(addr); - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) - { - QUIT; - if (TYPE_FN_FIELD_VOFFSET (f, j) == offset) - { - kind = "virtual "; - goto common; - } - } - } + fprintf_filtered (stream, ",\n"); + print_spaces_filtered (2 + 2 * recurse, stream); } else { - struct symbol *sym = find_pc_function (addr); - if (sym == 0) - error ("invalid pointer to member function"); - len = TYPE_NFN_FIELDS (domain); - for (i = 0; i < len; i++) - { - f = TYPE_FN_FIELDLIST1 (domain, i); - len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i); - - for (j = 0; j < len2; j++) - { - QUIT; - if (!strcmp (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j))) - goto common; - } - } - } - common: - if (i < len) - { - fprintf_filtered (stream, "&"); - type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0); - fprintf (stream, kind); - if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER) - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - TYPE_FN_FIELDLIST_NAME (domain, i), 0, stream); - break; - } - fprintf_filtered (stream, "("); - type_print (type, "", stream, -1); - fprintf_filtered (stream, ") %d", (int) addr >> 3); - } - else if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) - { - print_class_member (valaddr, - TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), - stream, "&"); - } - else - { - CORE_ADDR addr = unpack_pointer (type, valaddr); - elttype = TYPE_TARGET_TYPE (type); - - if (TYPE_CODE (elttype) == TYPE_CODE_FUNC) - { - /* Try to print what function it points to. */ - print_address_demangle (addr, stream, demangle); - /* Return value is irrelevant except for string pointers. */ - return 0; - } - - if (addressprint && format != 's') - fprintf_filtered (stream, "0x%x", addr); - - /* For a pointer to char or unsigned char, - also print the string pointed to, unless pointer is null. */ - i = 0; /* Number of characters printed. */ - if (TYPE_LENGTH (elttype) == 1 - && TYPE_CODE (elttype) == TYPE_CODE_INT - && (format == 0 || format == 's') - && addr != 0 - /* If print_max is UINT_MAX, the alloca below will fail. - In that case don't try to print the string. */ - && print_max < UINT_MAX) - { - int first_addr_err = 0; - int errcode = 0; - - /* Get first character. */ - errcode = target_read_memory (addr, (char *)&c, 1); - if (errcode != 0) - { - /* First address out of bounds. */ - first_addr_err = 1; - } - else - { - /* A real string. */ - char *string = (char *) alloca (print_max); - - /* If the loop ends by us hitting print_max characters, - we need to have elipses at the end. */ - int force_ellipses = 1; - - /* This loop always fetches print_max characters, even - though local_printstr might want to print more or fewer - (with repeated characters). This is so that - we don't spend forever fetching if we print - a long string consisting of the same character - repeated. Also so we can do it all in one memory - operation, which is faster. However, this will be - slower if print_max is set high, e.g. if you set - print_max to 1000, not only will it take a long - time to fetch short strings, but if you are near - the end of the address space, it might not work. */ - QUIT; - errcode = target_read_memory (addr, string, print_max); - if (errcode != 0) - { - /* Try reading just one character. If that succeeds, - assume we hit the end of the address space, but - the initial part of the string is probably safe. */ - char x[1]; - errcode = target_read_memory (addr, x, 1); - } - if (errcode != 0) - force_ellipses = 0; - else - for (i = 0; i < print_max; i++) - if (string[i] == '\0') - { - force_ellipses = 0; - break; - } - QUIT; - - if (addressprint) - fputs_filtered (" ", stream); - local_printstr (stream, string, i, force_ellipses); - } - - if (errcode != 0) - { - if (errcode == EIO) - { - fprintf_filtered (stream, - (" <Address 0x%x out of bounds>" - + first_addr_err), - addr + i); - } - else - { - error ("Error reading memory address 0x%x: %s.", - addr + i, safe_strerror (errcode)); - } - } - - fflush (stream); - } - else /* print vtbl's nicely */ - if (is_vtbl_member(type)) - { - CORE_ADDR vt_address = unpack_pointer (type, valaddr); - - struct minimal_symbol *msymbol = - lookup_minimal_symbol_by_pc (vt_address); - if ((msymbol != NULL) && (vt_address == msymbol -> address)) - { - fputs_filtered (" <", stream); - fputs_demangled (msymbol -> name, stream, - DMGL_ANSI | DMGL_PARAMS); - fputs_filtered (">", stream); - } - if (vtblprint) - { - value vt_val; - - vt_val = value_at (TYPE_TARGET_TYPE (type), vt_address); - val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val), - VALUE_ADDRESS (vt_val), stream, format, - deref_ref, recurse + 1, pretty); - if (pretty) - { - fprintf_filtered (stream, "\n"); - print_spaces_filtered (2 + 2 * recurse, stream); - } - } - } - - /* Return number of characters printed, plus one for the - terminating null if we have "reached the end". */ - return i + (print_max && i != print_max); - } - break; - - case TYPE_CODE_MEMBER: - error ("not implemented: member type in val_print"); - break; - - case TYPE_CODE_REF: - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER) - { - print_class_member (valaddr, - TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)), - stream, ""); - break; - } - if (addressprint) - { - fprintf_filtered (stream, "@0x%lx", - unpack_long (builtin_type_int, valaddr)); - if (deref_ref) - fputs_filtered (": ", stream); - } - /* De-reference the reference. */ - if (deref_ref) - { - if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF) - { - value deref_val = - value_at - (TYPE_TARGET_TYPE (type), - unpack_pointer (lookup_pointer_type (builtin_type_void), - valaddr)); - val_print (VALUE_TYPE (deref_val), VALUE_CONTENTS (deref_val), - VALUE_ADDRESS (deref_val), stream, format, - deref_ref, recurse + 1, pretty); + fprintf_filtered (stream, ", "); } - else - fputs_filtered ("???", stream); - } - break; - - case TYPE_CODE_UNION: - if (recurse && !unionprint) - { - fprintf_filtered (stream, "{...}"); - break; - } - /* Fall through. */ - case TYPE_CODE_STRUCT: - if (vtblprint && is_vtbl_ptr_type(type)) - { - /* Print the unmangled name if desired. */ - print_address_demangle(*((int *) (valaddr + /* FIXME bytesex */ - TYPE_FIELD_BITPOS (type, VTBL_FNADDR_OFFSET) / 8)), - stream, demangle); - break; } - val_print_fields (type, valaddr, stream, format, recurse, pretty, 0); - break; - - case TYPE_CODE_ENUM: - if (format) + wrap_here (n_spaces (2 + 2 * recurse)); + + rep1 = i + 1; + reps = 1; + while ((rep1 < len) && + !memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen)) { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; + ++reps; + ++rep1; } - len = TYPE_NFIELDS (type); - val = unpack_long (builtin_type_int, valaddr); - for (i = 0; i < len; i++) + + if (reps > repeat_count_threshold) { - QUIT; - if (val == TYPE_FIELD_BITPOS (type, i)) - break; + val_print (elttype, valaddr + i * eltlen, 0, stream, format, + deref_ref, recurse + 1, pretty); + fprintf_filtered (stream, " <repeats %u times>", reps); + i = rep1 - 1; + things_printed += repeat_count_threshold; } - if (i < len) - fputs_filtered (TYPE_FIELD_NAME (type, i), stream); else -#ifdef LONG_LONG - fprintf_filtered (stream, "%lld", val); -#else - fprintf_filtered (stream, "%ld", val); -#endif - break; - - case TYPE_CODE_FUNC: - if (format) - { - print_scalar_formatted (valaddr, type, format, 0, stream); - break; - } - /* FIXME, we should consider, at least for ANSI C language, eliminating - the distinction made between FUNCs and POINTERs to FUNCs. */ - fprintf_filtered (stream, "{"); - type_print (type, "", stream, -1); - fprintf_filtered (stream, "} "); - /* Try to print what function it points to, and its address. */ - print_address_demangle (address, stream, demangle); - break; - - case TYPE_CODE_INT: - if (format || output_format) { - print_scalar_formatted (valaddr, type, - format? format: output_format, - 0, stream); - break; + val_print (elttype, valaddr + i * eltlen, 0, stream, format, + deref_ref, recurse + 1, pretty); + things_printed++; } - if (TYPE_LENGTH (type) > sizeof (LONGEST)) - { - if (TYPE_UNSIGNED (type)) - { - /* First figure out whether the number in fact has zeros - in all its bytes more significant than least significant - sizeof (LONGEST) ones. */ - char *p; - /* Pointer to first (i.e. lowest address) nonzero character. */ - char *first_addr; - len = TYPE_LENGTH (type); - -#if TARGET_BYTE_ORDER == BIG_ENDIAN - for (p = valaddr; - len > sizeof (LONGEST) - && p < valaddr + TYPE_LENGTH (type); - p++) -#else /* Little endian. */ - first_addr = valaddr; - for (p = valaddr + TYPE_LENGTH (type); - len > sizeof (LONGEST) && p >= valaddr; - p--) -#endif /* Little endian. */ - { - if (*p == 0) - len--; - else - break; - } -#if TARGET_BYTE_ORDER == BIG_ENDIAN - first_addr = p; -#endif - - if (len <= sizeof (LONGEST)) - { - /* We can print it in decimal. */ - fprintf_filtered - (stream, -#if defined (LONG_LONG) - "%llu", -#else - "%lu", -#endif - unpack_long (BUILTIN_TYPE_LONGEST, first_addr)); - } - else - { - /* It is big, so print it in hex. */ - print_hex_chars (stream, (unsigned char *)first_addr, len); - } - } - else - { - /* Signed. One could assume two's complement (a reasonable - assumption, I think) and do better than this. */ - print_hex_chars (stream, (unsigned char *)valaddr, - TYPE_LENGTH (type)); - } - break; - } -#ifdef PRINT_TYPELESS_INTEGER - PRINT_TYPELESS_INTEGER (stream, type, unpack_long (type, valaddr)); -#else -#ifndef LONG_LONG - fprintf_filtered (stream, - TYPE_UNSIGNED (type) ? "%u" : "%d", - unpack_long (type, valaddr)); -#else - fprintf_filtered (stream, - TYPE_UNSIGNED (type) ? "%llu" : "%lld", - unpack_long (type, valaddr)); -#endif -#endif - - if (TYPE_LENGTH (type) == 1) - { - fputs_filtered (" ", stream); - local_printchar ((unsigned char) unpack_long (type, valaddr), - stream); - } - break; - - case TYPE_CODE_CHAR: - if (format || output_format) - { - print_scalar_formatted (valaddr, type, - format? format: output_format, - 0, stream); - break; - } - fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d", - unpack_long (type, valaddr)); - fputs_filtered (" ", stream); - local_printchar ((unsigned char) unpack_long (type, valaddr), stream); - break; - - case TYPE_CODE_FLT: - if (format) - print_scalar_formatted (valaddr, type, format, 0, stream); - else - print_floating (valaddr, type, stream); - break; - - case TYPE_CODE_VOID: - fprintf_filtered (stream, "void"); - break; - - case TYPE_CODE_UNDEF: - /* This happens (without TYPE_FLAG_STUB set) on systems which don't use - dbx xrefs (NO_DBX_XREFS in gcc) if a file has a "struct foo *bar" - and no complete type for struct foo in that file. */ - fprintf_filtered (stream, "<unknown struct>"); - break; - - case TYPE_CODE_ERROR: - fprintf_filtered (stream, "?"); - break; - - case TYPE_CODE_RANGE: - /* FIXME, we should not ever have to print one of these yet. */ - fprintf_filtered (stream, "<range type>"); - break; - - /* start-sanitize-chill (FIXME!) */ - case TYPE_CODE_BOOL: - val = unpack_long (builtin_type_chill_bool, valaddr); - fprintf_filtered (stream, val ? "TRUE" : "FALSE"); - break; - /* end-sanitize-chill */ - - default: - error ("Invalid type code in symbol table."); } - fflush (stream); - return 0; -} - -/* Print a description of a type in the format of a - typedef for the current language. - NEW is the new name for a type TYPE. */ -void -typedef_print (type, new, stream) - struct type *type; - struct symbol *new; - FILE *stream; -{ - switch (current_language->la_language) - { -#ifdef _LANG_c - case language_c: - case language_cplus: - fprintf_filtered(stream, "typedef "); - type_print(type,"",stream,0); - if(TYPE_NAME ((SYMBOL_TYPE (new))) == 0 - || 0 != strcmp (TYPE_NAME ((SYMBOL_TYPE (new))), - SYMBOL_NAME (new))) - fprintf_filtered(stream, " %s", SYMBOL_NAME(new)); - break; -#endif -#ifdef _LANG_m2 - case language_m2: - fprintf_filtered(stream, "TYPE "); - if(!TYPE_NAME(SYMBOL_TYPE(new)) || - strcmp (TYPE_NAME(SYMBOL_TYPE(new)), - SYMBOL_NAME(new))) - fprintf_filtered(stream, "%s = ", SYMBOL_NAME(new)); - else - fprintf_filtered(stream, "<builtin> = "); - type_print(type,"",stream,0); - break; -#endif -/* start-sanitize-chill */ -#ifdef _LANG_chill - case language_chill: - error("Missing Chill support in function typedef_print."); /*FIXME*/ -#endif -/* end-sanitize-chill */ - default: - error("Language not supported."); - } - fprintf_filtered(stream, ";\n"); -} - - -/* Print a description of a type TYPE - in the form of a declaration of a variable named VARSTRING. - (VARSTRING is demangled if necessary.) - Output goes to STREAM (via stdio). - If SHOW is positive, we show the contents of the outermost level - of structure even if there is a type name that could be used instead. - If SHOW is negative, we never show the details of elements' types. */ - -void -type_print (type, varstring, stream, show) - struct type *type; - char *varstring; - FILE *stream; - int show; -{ - type_print_1 (type, varstring, stream, show, 0); -} - -/* LEVEL is the depth to indent lines by. */ - -void -type_print_1 (type, varstring, stream, show, level) - struct type *type; - char *varstring; - FILE *stream; - int show; - int level; -{ - register enum type_code code; - char *demangled = NULL; - int demangled_args; - - type_print_base (type, stream, show, level); - code = TYPE_CODE (type); - if ((varstring && *varstring) - || - /* Need a space if going to print stars or brackets; - but not if we will print just a type name. */ - ((show > 0 || TYPE_NAME (type) == 0) - && - (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC - || code == TYPE_CODE_METHOD - || code == TYPE_CODE_ARRAY - || code == TYPE_CODE_MEMBER - || code == TYPE_CODE_REF))) - fprintf_filtered (stream, " "); - type_print_varspec_prefix (type, stream, show, 0); - - /* See if the name has a C++ demangled equivalent, and if so, print that - instead. */ - - if (demangle) - { - demangled = cplus_demangle (varstring, DMGL_ANSI | DMGL_PARAMS); - } - fputs_filtered ((demangled != NULL) ? demangled : varstring, stream); - - /* For demangled function names, we have the arglist as part of the name, - so don't print an additional pair of ()'s */ - - demangled_args = (demangled != NULL) && (code == TYPE_CODE_FUNC); - type_print_varspec_suffix (type, stream, show, 0, demangled_args); - - if (demangled) + if (i < len) { - free (demangled); + fprintf_filtered (stream, "..."); } } -/* Print the method arguments ARGS to the file STREAM. */ static void -type_print_method_args (args, prefix, varstring, staticp, stream) - struct type **args; - char *prefix, *varstring; - int staticp; +value_print_array_elements (val, stream, format, pretty) + value val; FILE *stream; + int format; + enum val_prettyprint pretty; { - int i; - - fputs_demangled (prefix, stream, DMGL_ANSI | DMGL_PARAMS); - fputs_demangled (varstring, stream, DMGL_ANSI | DMGL_PARAMS); - fputs_filtered (" (", stream); - if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID) + unsigned int things_printed = 0; + register unsigned int i, n, typelen; + /* Position of the array elem we are examining to see if it is repeated. */ + unsigned int rep1; + /* Number of repetitions we have detected so far. */ + unsigned int reps; + + n = VALUE_REPETITIONS (val); + typelen = TYPE_LENGTH (VALUE_TYPE (val)); + for (i = 0; i < n && things_printed < print_max; i++) { - i = !staticp; /* skip the class variable */ - while (1) + if (i != 0) { - type_print (args[i++], "", stream, 0); - if (!args[i]) - { - fprintf_filtered (stream, " ..."); - break; - } - else if (args[i]->code != TYPE_CODE_VOID) - { - fprintf_filtered (stream, ", "); - } - else break; + fprintf_filtered (stream, ", "); } - } - fprintf_filtered (stream, ")"); -} - -/* If TYPE is a derived type, then print out derivation information. - Print only the actual base classes of this type, not the base classes - of the base classes. I.E. for the derivation hierarchy: - - class A { int a; }; - class B : public A {int b; }; - class C : public B {int c; }; - - Print the type of class C as: - - class C : public B { - int c; - } - - Not as the following (like gdb used to), which is not legal C++ syntax for - derived types and may be confused with the multiple inheritance form: - - class C : public B : public A { - int c; - } - - In general, gdb should try to print the types as closely as possible to - the form that they appear in the source code. */ - -static void -type_print_derivation_info (stream, type) - FILE *stream; - struct type *type; -{ - char *name; - int i; - - for (i = 0; i < TYPE_N_BASECLASSES (type); i++) - { - fputs_filtered (i == 0 ? ": " : ", ", stream); - fprintf_filtered (stream, "%s%s ", - BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private", - BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : ""); - name = type_name_no_tag (TYPE_BASECLASS (type, i)); - fprintf_filtered (stream, "%s", name ? name : "(null)"); - } - if (i > 0) - { - fputs_filtered (" ", stream); - } -} - -/* Print any asterisks or open-parentheses needed before the - variable name (to describe its type). - - On outermost call, pass 0 for PASSED_A_PTR. - On outermost call, SHOW > 0 means should ignore - any typename for TYPE and show its details. - SHOW is always zero on recursive calls. */ - -static void -type_print_varspec_prefix (type, stream, show, passed_a_ptr) - struct type *type; - FILE *stream; - int show; - int passed_a_ptr; -{ - char *name; - if (type == 0) - return; - - if (TYPE_NAME (type) && show <= 0) - return; - - QUIT; - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_PTR: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fprintf_filtered (stream, "*"); - break; - - case TYPE_CODE_MEMBER: - if (passed_a_ptr) - fprintf_filtered (stream, "("); - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); - fprintf_filtered (stream, " "); - name = type_name_no_tag (TYPE_DOMAIN_TYPE (type)); - if (name) - fputs_filtered (name, stream); - else - type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); - fprintf_filtered (stream, "::"); - break; - - case TYPE_CODE_METHOD: - if (passed_a_ptr) - fprintf (stream, "("); - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); - if (passed_a_ptr) + wrap_here (""); + + rep1 = i + 1; + reps = 1; + while (rep1 < n && !memcmp (VALUE_CONTENTS (val) + typelen * i, + VALUE_CONTENTS (val) + typelen * rep1, + typelen)) { - fprintf_filtered (stream, " "); - type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr); - fprintf_filtered (stream, "::"); + ++reps; + ++rep1; } - break; - - case TYPE_CODE_REF: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); - fprintf_filtered (stream, "&"); - break; - - case TYPE_CODE_FUNC: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); - if (passed_a_ptr) - fprintf_filtered (stream, "("); - break; - - case TYPE_CODE_ARRAY: - type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); - if (passed_a_ptr) - fprintf_filtered (stream, "("); - break; - - case TYPE_CODE_UNDEF: - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - case TYPE_CODE_ENUM: - case TYPE_CODE_INT: - case TYPE_CODE_FLT: - case TYPE_CODE_VOID: - case TYPE_CODE_ERROR: - case TYPE_CODE_CHAR: - case TYPE_CODE_BOOL: - case TYPE_CODE_SET: - case TYPE_CODE_RANGE: - case TYPE_CODE_PASCAL_ARRAY: - /* These types need no prefix. They are listed here so that - gcc -Wall will reveal any types that haven't been handled. */ - break; - } -} - -static void -type_print_args (type, stream) - struct type *type; - FILE *stream; -{ - int i; - struct type **args; - - fprintf_filtered (stream, "("); - args = TYPE_ARG_TYPES (type); - if (args != NULL) - { - if (args[1] == NULL) + + if (reps > repeat_count_threshold) { - fprintf_filtered (stream, "..."); + val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, + VALUE_ADDRESS (val) + typelen * i, stream, format, 1, + 0, pretty); + fprintf (stream, " <repeats %u times>", reps); + i = rep1 - 1; + things_printed += repeat_count_threshold; } else { - for (i = 1; - args[i] != NULL && args[i]->code != TYPE_CODE_VOID; - i++) - { - type_print_1 (args[i], "", stream, -1, 0); - if (args[i+1] == NULL) - { - fprintf_filtered (stream, "..."); - } - else if (args[i+1]->code != TYPE_CODE_VOID) - { - fprintf_filtered (stream, ","); - wrap_here (" "); - } - } + val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i, + VALUE_ADDRESS (val) + typelen * i, stream, format, 1, + 0, pretty); + things_printed++; } } - fprintf_filtered (stream, ")"); -} - -/* Print any array sizes, function arguments or close parentheses - needed after the variable name (to describe its type). - Args work like type_print_varspec_prefix. */ - -static void -type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args) - struct type *type; - FILE *stream; - int show; - int passed_a_ptr; - int demangled_args; -{ - if (type == 0) - return; - - if (TYPE_NAME (type) && show <= 0) - return; - - QUIT; - - switch (TYPE_CODE (type)) + if (i < n) { - case TYPE_CODE_ARRAY: - if (passed_a_ptr) - fprintf_filtered (stream, ")"); - - fprintf_filtered (stream, "["); - if (TYPE_LENGTH (type) > 0 - && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) - fprintf_filtered (stream, "%d", - (TYPE_LENGTH (type) - / TYPE_LENGTH (TYPE_TARGET_TYPE (type)))); - fprintf_filtered (stream, "]"); - - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - 0, 0); - break; - - case TYPE_CODE_MEMBER: - if (passed_a_ptr) - fprintf_filtered (stream, ")"); - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); - break; - - case TYPE_CODE_METHOD: - if (passed_a_ptr) - fprintf_filtered (stream, ")"); - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); - if (passed_a_ptr) - { - type_print_args (type, stream); - } - break; - - case TYPE_CODE_PTR: - case TYPE_CODE_REF: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0); - break; - - case TYPE_CODE_FUNC: - type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, - passed_a_ptr, 0); - if (passed_a_ptr) - fprintf_filtered (stream, ")"); - if (!demangled_args) - fprintf_filtered (stream, "()"); - break; - - case TYPE_CODE_UNDEF: - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - case TYPE_CODE_ENUM: - case TYPE_CODE_INT: - case TYPE_CODE_FLT: - case TYPE_CODE_VOID: - case TYPE_CODE_ERROR: - case TYPE_CODE_CHAR: - case TYPE_CODE_BOOL: - case TYPE_CODE_SET: - case TYPE_CODE_RANGE: - case TYPE_CODE_PASCAL_ARRAY: - /* These types do not need a suffix. They are listed so that - gcc -Wall will report types that may not have been considered. */ - break; + fprintf_filtered (stream, "..."); } } -/* Print the name of the type (or the ultimate pointer target, - function value or array element), or the description of a - structure or union. - - SHOW nonzero means don't print this type as just its name; - show its real definition even if it has a name. - SHOW zero means print just typename or struct tag if there is one - SHOW negative means abbreviate structure elements. - SHOW is decremented for printing of structure elements. - - LEVEL is the depth to indent by. - We increase it for some recursive calls. */ - -static void -type_print_base (type, stream, show, level) - struct type *type; - FILE *stream; - int show; - int level; -{ - char *name; - register int i; - register int len; - register int lastval; - char *mangled_name; - char *demangled_name; - enum {s_none, s_public, s_private, s_protected} section_type; - QUIT; - - wrap_here (" "); - if (type == NULL) - { - fputs_filtered ("<type unknown>", stream); - return; - } - - /* When SHOW is zero or less, and there is a valid type name, then always - just print the type name directly from the type. */ - - if ((show <= 0) && (TYPE_NAME (type) != NULL)) - { - fputs_filtered (TYPE_NAME (type), stream); - return; - } - - switch (TYPE_CODE (type)) - { - case TYPE_CODE_ARRAY: - case TYPE_CODE_PTR: - case TYPE_CODE_MEMBER: - case TYPE_CODE_REF: - case TYPE_CODE_FUNC: - case TYPE_CODE_METHOD: - type_print_base (TYPE_TARGET_TYPE (type), stream, show, level); - break; - - case TYPE_CODE_STRUCT: - fprintf_filtered (stream, - HAVE_CPLUS_STRUCT (type) ? "class " : "struct "); - goto struct_union; - - case TYPE_CODE_UNION: - fprintf_filtered (stream, "union "); - struct_union: - if (name = type_name_no_tag (type)) - { - fputs_filtered (name, stream); - fputs_filtered (" ", stream); - wrap_here (" "); - } - if (show < 0) - fprintf_filtered (stream, "{...}"); - else - { - check_stub_type (type); - - type_print_derivation_info (stream, type); - - fprintf_filtered (stream, "{\n"); - if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) - { - if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) - fprintfi_filtered (level + 4, stream, "<incomplete type>\n"); - else - fprintfi_filtered (level + 4, stream, "<no data fields>\n"); - } - - /* Start off with no specific section type, so we can print - one for the first field we find, and use that section type - thereafter until we find another type. */ - - section_type = s_none; - - /* If there is a base class for this type, - do not print the field that it occupies. */ - - len = TYPE_NFIELDS (type); - for (i = TYPE_N_BASECLASSES (type); i < len; i++) - { - QUIT; - /* Don't print out virtual function table. */ - if ((TYPE_FIELD_NAME (type, i))[5] == CPLUS_MARKER && - !strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5)) - continue; - - /* If this is a C++ class we can print the various C++ section - labels. */ - - if (HAVE_CPLUS_STRUCT (type)) - { - if (TYPE_FIELD_PROTECTED (type, i)) - { - if (section_type != s_protected) - { - section_type = s_protected; - fprintfi_filtered (level + 2, stream, - "protected:\n"); - } - } - else if (TYPE_FIELD_PRIVATE (type, i)) - { - if (section_type != s_private) - { - section_type = s_private; - fprintfi_filtered (level + 2, stream, "private:\n"); - } - } - else - { - if (section_type != s_public) - { - section_type = s_public; - fprintfi_filtered (level + 2, stream, "public:\n"); - } - } - } - - print_spaces_filtered (level + 4, stream); - if (TYPE_FIELD_STATIC (type, i)) - { - fprintf_filtered (stream, "static "); - } - type_print_1 (TYPE_FIELD_TYPE (type, i), - TYPE_FIELD_NAME (type, i), - stream, show - 1, level + 4); - if (!TYPE_FIELD_STATIC (type, i) - && TYPE_FIELD_PACKED (type, i)) - { - /* It is a bitfield. This code does not attempt - to look at the bitpos and reconstruct filler, - unnamed fields. This would lead to misleading - results if the compiler does not put out fields - for such things (I don't know what it does). */ - fprintf_filtered (stream, " : %d", - TYPE_FIELD_BITSIZE (type, i)); - } - fprintf_filtered (stream, ";\n"); - } - - /* If there are both fields and methods, put a space between. */ - len = TYPE_NFN_FIELDS (type); - if (len && section_type != s_none) - fprintf_filtered (stream, "\n"); - - /* C++: print out the methods */ - - for (i = 0; i < len; i++) - { - struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); - int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); - char *method_name = TYPE_FN_FIELDLIST_NAME (type, i); - int is_constructor = name && strcmp(method_name, name) == 0; - for (j = 0; j < len2; j++) - { - QUIT; - if (TYPE_FN_FIELD_PROTECTED (f, j)) - { - if (section_type != s_protected) - { - section_type = s_protected; - fprintfi_filtered (level + 2, stream, - "protected:\n"); - } - } - else if (TYPE_FN_FIELD_PRIVATE (f, j)) - { - if (section_type != s_private) - { - section_type = s_private; - fprintfi_filtered (level + 2, stream, "private:\n"); - } - } - else - { - if (section_type != s_public) - { - section_type = s_public; - fprintfi_filtered (level + 2, stream, "public:\n"); - } - } - - print_spaces_filtered (level + 4, stream); - if (TYPE_FN_FIELD_VIRTUAL_P (f, j)) - fprintf_filtered (stream, "virtual "); - else if (TYPE_FN_FIELD_STATIC_P (f, j)) - fprintf_filtered (stream, "static "); - if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0) - { - /* Keep GDB from crashing here. */ - fprintf (stream, "<undefined type> %s;\n", - TYPE_FN_FIELD_PHYSNAME (f, j)); - break; - } - else if (!is_constructor) - { - type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)), - "", stream, 0); - fputs_filtered (" ", stream); - } - if (TYPE_FN_FIELD_STUB (f, j)) - { - /* Build something we can demangle. */ - mangled_name = gdb_mangle_name (type, i, j); - demangled_name = - cplus_demangle (mangled_name, - DMGL_ANSI | DMGL_PARAMS); - if (demangled_name == NULL) - fprintf_filtered (stream, "<badly mangled name %s>", - mangled_name); - else - { - fprintf_filtered (stream, "%s", - strchr (demangled_name, ':') + 2); - free (demangled_name); - } - free (mangled_name); - } - else if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_' - && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == CPLUS_MARKER) - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j) + 1, "~", - method_name, 0, stream); - else - type_print_method_args - (TYPE_FN_FIELD_ARGS (f, j), "", - method_name, - TYPE_FN_FIELD_STATIC_P (f, j), stream); - - fprintf_filtered (stream, ";\n"); - } - } - - fprintfi_filtered (level, stream, "}"); - } - break; - - case TYPE_CODE_ENUM: - fprintf_filtered (stream, "enum "); - if (name = type_name_no_tag (type)) - { - fputs_filtered (name, stream); - fputs_filtered (" ", stream); - } - wrap_here (" "); - if (show < 0) - fprintf_filtered (stream, "{...}"); - else - { - fprintf_filtered (stream, "{"); - len = TYPE_NFIELDS (type); - lastval = 0; - for (i = 0; i < len; i++) - { - QUIT; - if (i) fprintf_filtered (stream, ", "); - wrap_here (" "); - fputs_filtered (TYPE_FIELD_NAME (type, i), stream); - if (lastval != TYPE_FIELD_BITPOS (type, i)) - { - fprintf_filtered (stream, " = %d", TYPE_FIELD_BITPOS (type, i)); - lastval = TYPE_FIELD_BITPOS (type, i); - } - lastval++; - } - fprintf_filtered (stream, "}"); - } - break; - - case TYPE_CODE_VOID: - fprintf_filtered (stream, "void"); - break; - - case TYPE_CODE_UNDEF: - fprintf_filtered (stream, "struct <unknown>"); - break; - - case TYPE_CODE_ERROR: - fprintf_filtered (stream, "<unknown type>"); - break; - - case TYPE_CODE_RANGE: - /* This should not occur */ - fprintf_filtered (stream, "<range type>"); - break; - - default: - /* Handle types not explicitly handled by the other cases, - such as fundamental types. For these, just print whatever - the type name is, as recorded in the type itself. If there - is no type name, then complain. */ - if (TYPE_NAME (type) != NULL) - { - fputs_filtered (TYPE_NAME (type), stream); - } - else - { - error ("Invalid type code (%d) in symbol table.", TYPE_CODE (type)); - } - break; - } -} #if 0 /* Validate an input or output radix setting, and make sure the user @@ -2079,7 +671,8 @@ _initialize_valprint () &showprintlist); add_show_from_set - (add_set_cmd ("pretty", class_support, var_boolean, (char *)&prettyprint, + (add_set_cmd ("pretty", class_support, var_boolean, + (char *)&prettyprint_structs, "Set prettyprinting of structures.", &setprintlist), &showprintlist); @@ -2091,24 +684,13 @@ _initialize_valprint () &showprintlist); add_show_from_set - (add_set_cmd ("vtbl", class_support, var_boolean, (char *)&vtblprint, - "Set printing of C++ virtual function tables.", - &setprintlist), - &showprintlist); - - add_show_from_set - (add_set_cmd ("array", class_support, var_boolean, (char *)&arrayprint, + (add_set_cmd ("array", class_support, var_boolean, + (char *)&prettyprint_arrays, "Set prettyprinting of arrays.", &setprintlist), &showprintlist); add_show_from_set - (add_set_cmd ("object", class_support, var_boolean, (char *)&objectprint, - "Set printing of object's derived type based on vtable info.", - &setprintlist), - &showprintlist); - - add_show_from_set (add_set_cmd ("address", class_support, var_boolean, (char *)&addressprint, "Set printing of addresses.", &setprintlist), @@ -2141,14 +723,9 @@ _initialize_valprint () c->function.sfunc = set_radix; /* Give people the defaults which they are used to. */ - prettyprint = 0; + prettyprint_structs = 0; + prettyprint_arrays = 0; unionprint = 1; - vtblprint = 0; - arrayprint = 0; addressprint = 1; - objectprint = 0; - print_max = 200; - - obstack_begin (&dont_print_obstack, 32 * sizeof (struct type *)); } diff --git a/gdb/valprint.h b/gdb/valprint.h new file mode 100644 index 0000000..5918def --- /dev/null +++ b/gdb/valprint.h @@ -0,0 +1,40 @@ +/* Declarations for value printing routines for GDB, the GNU debugger. + Copyright 1986, 1988, 1989, 1991 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 +(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, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + +extern int prettyprint_arrays; /* Controls pretty printing of arrays. */ +extern int prettyprint_structs; /* Controls pretty printing of structures */ +extern int prettyprint_arrays; /* Controls pretty printing of arrays. */ + +extern int vtblprint; /* Controls printing of vtbl's */ +extern int unionprint; /* Controls printing of nested unions. */ +extern int addressprint; /* Controls pretty printing of addresses. */ +extern int objectprint; /* Controls looking up an object's derived type + using what we find in its vtables. */ + +extern unsigned int print_max; /* Max # of chars for strings/vectors */ +extern int output_format; + +extern void +val_print_array_elements PARAMS ((struct type *, char *, CORE_ADDR, FILE *, + int, int, int, enum val_prettyprint, int)); + +extern void +val_print_type_code_int PARAMS ((struct type *, char *, FILE *)); + diff --git a/gdb/values.c b/gdb/values.c index 14ecccb..76a66f2 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -314,7 +314,7 @@ clear_value_history () while (value_history_chain) { for (i = 0; i < VALUE_HISTORY_CHUNK; i++) - if (val = value_history_chain->values[i]) + if ((val = value_history_chain->values[i]) != NULL) free ((PTR)val); next = value_history_chain->next; free ((PTR)value_history_chain); |