/* Print values for GNU debugger GDB.
- Copyright 1986, 1987, 1988, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1994
+ Free Software Foundation, Inc.
This file is part of GDB.
#include "target.h"
#include "breakpoint.h"
#include "demangle.h"
+#include "valprint.h"
extern int asm_demangle; /* Whether to demangle syms in asm printouts */
extern int addressprint; /* Whether to print hex addresses in HLL " */
printing a symbolic value as `<symbol at filename:linenum>' if set. */
static int print_symbol_filename = 0;
+/* Switch for quick display of symbolic addresses -- only uses minsyms,
+ not full search of symtabs. */
+
+int fast_symbolic_addr = 1;
+
/* Number of auto-display expression currently being displayed.
So that we can disable it if we get an error or a signal within it.
-1 when not doing one. */
static void
print_frame_nameless_args PARAMS ((struct frame_info *, long, int, int,
- FILE *));
+ GDB_FILE *));
static void
display_info PARAMS ((char *, int));
{
if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
val.size = *p++;
-#ifdef CC_HAS_LONG_LONG
- else if (*p == 'l')
- {
- val.size = 'g';
- p++;
- }
-#endif
else if (*p >= 'a' && *p <= 'z')
val.format = *p++;
else
return val;
}
\f
-/* Print value VAL on stdout according to FORMAT, a letter or 0.
+/* Print value VAL on gdb_stdout according to FORMAT, a letter or 0.
Do not end with a newline.
0 means print VAL according to its own type.
SIZE is the letter for the size of datum being printed.
{
case 's':
next_address = VALUE_ADDRESS (val)
- + value_print (value_addr (val), stdout, format, Val_pretty_default);
+ + value_print (value_addr (val), gdb_stdout, format, Val_pretty_default);
break;
case 'i':
/* We often wrap here if there are long symbolic names. */
wrap_here (" ");
next_address = VALUE_ADDRESS (val)
- + print_insn (VALUE_ADDRESS (val), stdout);
+ + print_insn (VALUE_ADDRESS (val), gdb_stdout);
break;
default:
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_STRUCT
|| TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_UNION
|| VALUE_REPEATED (val))
- value_print (val, stdout, format, Val_pretty_default);
+ value_print (val, gdb_stdout, format, Val_pretty_default);
else
print_scalar_formatted (VALUE_CONTENTS (val), VALUE_TYPE (val),
- format, size, stdout);
+ format, size, gdb_stdout);
}
}
struct type *type;
int format;
int size;
- FILE *stream;
+ GDB_FILE *stream;
{
LONGEST val_long;
int len = TYPE_LENGTH (type);
val_long = unpack_long (type, valaddr);
- /* If value is unsigned, truncate it in case negative. */
+ /* If we are printing it as unsigned, truncate it in case it is actually
+ a negative signed value (e.g. "print/u (short)-1" should print 65535
+ (if shorts are 16 bits) instead of 4294967295). */
if (format != 'd')
{
- if (len == sizeof (char))
- val_long &= (1 << 8 * sizeof(char)) - 1;
- else if (len == sizeof (short))
- val_long &= (1 << 8 * sizeof(short)) - 1;
- else if (len == sizeof (long))
- val_long &= (unsigned long) - 1;
+ if (len < sizeof (LONGEST))
+ val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
}
switch (format)
/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> on STREAM,
after LEADIN. Print nothing if no symbolic name is found nearby.
+ Optionally also print source file and line number, if available.
DO_DEMANGLE controls whether to print a symbol in its native "raw" form,
or to interpret it as a possible C++ name and convert it back to source
form. However note that DO_DEMANGLE can be overridden by the specific
- settings of the demangle and asm_demangle variables. */
+ settings of the demangle and asm_demangle variables. */
void
print_address_symbolic (addr, stream, do_demangle, leadin)
CORE_ADDR addr;
- FILE *stream;
+ GDB_FILE *stream;
int do_demangle;
char *leadin;
{
- CORE_ADDR name_location;
- register struct symbol *symbol;
+ struct minimal_symbol *msymbol;
+ struct symbol *symbol;
+ struct symtab *symtab = 0;
+ CORE_ADDR name_location = 0;
char *name;
- /* First try to find the address in the symbol tables to find
- static functions. If that doesn't succeed we try the minimal symbol
- vector for symbols in non-text space.
- FIXME: Should find a way to get at the static non-text symbols too. */
-
- symbol = find_pc_function (addr);
- if (symbol)
+ /* First try to find the address in the symbol table, then
+ in the minsyms. Take the closest one. */
+
+ if (fast_symbolic_addr)
{
- name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
- if (do_demangle)
- name = SYMBOL_SOURCE_NAME (symbol);
- else
- name = SYMBOL_LINKAGE_NAME (symbol);
+ /* This is defective in the sense that it only finds text symbols. */
+ symbol = find_pc_function (addr);
+ if (symbol)
+ name_location = BLOCK_START (SYMBOL_BLOCK_VALUE (symbol));
}
else
+ find_addr_symbol (addr, &symtab, &name_location);
+
+ if (symbol)
{
- register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (addr);
+ if (do_demangle)
+ name = SYMBOL_SOURCE_NAME (symbol);
+ else
+ name = SYMBOL_LINKAGE_NAME (symbol);
+ }
- /* If nothing comes out, don't print anything symbolic. */
- if (msymbol == NULL)
- return;
- name_location = SYMBOL_VALUE_ADDRESS (msymbol);
- if (do_demangle)
- name = SYMBOL_SOURCE_NAME (msymbol);
- else
- name = SYMBOL_LINKAGE_NAME (msymbol);
+ msymbol = lookup_minimal_symbol_by_pc (addr);
+ if (msymbol != NULL)
+ {
+ if (SYMBOL_VALUE_ADDRESS (msymbol) > name_location || symbol == NULL)
+ {
+ /* The msymbol is closer to the address than the symbol;
+ use the msymbol instead. */
+ symbol = 0;
+ symtab = 0;
+ name_location = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (do_demangle)
+ name = SYMBOL_SOURCE_NAME (msymbol);
+ else
+ name = SYMBOL_LINKAGE_NAME (msymbol);
+ }
}
+ if (symbol == NULL && msymbol == NULL)
+ return;
/* If the nearest symbol is too far away, don't print anything symbolic. */
if (addr != name_location)
fprintf_filtered (stream, "+%u", (unsigned int)(addr - name_location));
- /* Append source filename and line number if desired. */
- if (symbol && print_symbol_filename)
+ /* Append source filename and line number if desired. Give specific
+ line # of this addr, if we have it; else line # of the nearest symbol. */
+ if (print_symbol_filename)
{
struct symtab_and_line sal;
sal = find_pc_line (addr, 0);
if (sal.symtab)
fprintf_filtered (stream, " at %s:%d", sal.symtab->filename, sal.line);
+ else if (symtab && symbol && symbol->line)
+ fprintf_filtered (stream, " at %s:%d", symtab->filename, symbol->line);
+ else if (symtab)
+ fprintf_filtered (stream, " in %s", symtab->filename);
}
fputs_filtered (">", stream);
}
+/* Print address ADDR on STREAM. */
+void
+print_address_numeric (addr, stream)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+{
+ /* This assumes a CORE_ADDR can fit in a LONGEST. Probably a safe
+ assumption. We pass use_local but I'm not completely sure whether
+ that is correct. When (if ever) should we *not* use_local? */
+ print_longest (stream, 'x', 1, (unsigned LONGEST) addr);
+}
+
/* Print address ADDR symbolically on STREAM.
First print it as a number. Then perhaps print
<SYMBOL + OFFSET> after the number. */
void
print_address (addr, stream)
CORE_ADDR addr;
- FILE *stream;
+ GDB_FILE *stream;
{
-#if 0 && defined (ADDR_BITS_REMOVE)
- /* This is wrong for pointer to char, in which we do want to print
- the low bits. */
- fprintf_filtered (stream, local_hex_format(), ADDR_BITS_REMOVE(addr));
-#else
- fprintf_filtered (stream, local_hex_format(), addr);
-#endif
+ print_address_numeric (addr, stream);
print_address_symbolic (addr, stream, asm_demangle, " ");
}
void
print_address_demangle (addr, stream, do_demangle)
CORE_ADDR addr;
- FILE *stream;
+ GDB_FILE *stream;
int do_demangle;
{
- if (addr == 0) {
- fprintf_filtered (stream, "0");
- } else if (addressprint) {
- fprintf_filtered (stream, local_hex_format(), addr);
- print_address_symbolic (addr, stream, do_demangle, " ");
- } else {
- print_address_symbolic (addr, stream, do_demangle, "");
- }
+ if (addr == 0)
+ {
+ fprintf_filtered (stream, "0");
+ }
+ else if (addressprint)
+ {
+ print_address_numeric (addr, stream);
+ print_address_symbolic (addr, stream, do_demangle, " ");
+ }
+ else
+ {
+ print_address_symbolic (addr, stream, do_demangle, "");
+ }
}
\f
+/* These are the types that $__ will get after an examine command of one
+ of these sizes. */
+
+static struct type *examine_b_type;
+static struct type *examine_h_type;
+static struct type *examine_w_type;
+static struct type *examine_g_type;
+
/* Examine data at address ADDR in format FMT.
- Fetch it from memory and print on stdout. */
+ Fetch it from memory and print on gdb_stdout. */
static void
do_examine (fmt, addr)
register char format = 0;
register char size;
register int count = 1;
- struct type *val_type;
+ struct type *val_type = NULL;
register int i;
register int maxelts;
size = 'b';
if (size == 'b')
- val_type = builtin_type_char;
+ val_type = examine_b_type;
else if (size == 'h')
- val_type = builtin_type_short;
+ val_type = examine_h_type;
else if (size == 'w')
- val_type = builtin_type_long;
+ val_type = examine_w_type;
else if (size == 'g')
-#ifndef CC_HAS_LONG_LONG
- val_type = builtin_type_double;
-#else
- val_type = builtin_type_long_long;
-#endif
+ val_type = examine_g_type;
maxelts = 8;
if (size == 'w')
while (count > 0)
{
- print_address (next_address, stdout);
+ print_address (next_address, gdb_stdout);
printf_filtered (":");
for (i = maxelts;
i > 0 && count > 0;
print_formatted (last_examine_value, format, size);
}
printf_filtered ("\n");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
}
\f
int histindex = record_latest_value (val);
if (inspect)
- printf ("\031(gdb-makebuffer \"%s\" %d '(\"", exp, histindex);
+ printf_unfiltered ("\031(gdb-makebuffer \"%s\" %d '(\"", exp, histindex);
else
if (histindex >= 0) printf_filtered ("$%d = ", histindex);
print_formatted (val, format, fmt.size);
printf_filtered ("\n");
if (inspect)
- printf("\") )\030");
+ printf_unfiltered("\") )\030");
}
if (cleanup)
{
if (is_a_field_of_this)
{
- printf ("Symbol \"%s\" is a field of the local class variable `this'\n", exp);
+ printf_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, exp,
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is a field of the local class variable `this'\n");
return;
}
msymbol = lookup_minimal_symbol (exp, (struct objfile *) NULL);
if (msymbol != NULL)
- printf ("Symbol \"%s\" is at %s in a file compiled without debugging.\n",
- exp, local_hex_string(SYMBOL_VALUE_ADDRESS (msymbol)));
+ {
+ printf_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, exp,
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is at ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (msymbol), gdb_stdout);
+ printf_filtered (" in a file compiled without debugging.\n");
+ }
else
error ("No symbol \"%s\" in current context.", exp);
return;
}
- printf ("Symbol \"%s\" is ", SYMBOL_NAME (sym));
+ printf_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, SYMBOL_NAME (sym),
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is ", SYMBOL_NAME (sym));
val = SYMBOL_VALUE (sym);
basereg = SYMBOL_BASEREG (sym);
{
case LOC_CONST:
case LOC_CONST_BYTES:
- printf ("constant");
+ printf_filtered ("constant");
break;
case LOC_LABEL:
- printf ("a label at address %s", local_hex_string(SYMBOL_VALUE_ADDRESS (sym)));
+ printf_filtered ("a label at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), gdb_stdout);
break;
case LOC_REGISTER:
- printf ("a variable in register %s", reg_names[val]);
+ printf_filtered ("a variable in register %s", reg_names[val]);
break;
case LOC_STATIC:
- printf ("static storage at address %s", local_hex_string(SYMBOL_VALUE_ADDRESS (sym)));
+ printf_filtered ("static storage at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), gdb_stdout);
break;
case LOC_REGPARM:
- printf ("an argument in register %s", reg_names[val]);
+ printf_filtered ("an argument in register %s", reg_names[val]);
+ break;
+
+ case LOC_REGPARM_ADDR:
+ printf_filtered ("address of an argument in register %s", reg_names[val]);
break;
- case LOC_REGPARM_ADDR:
- printf ("address of an argument in register %s", reg_names[val]);
- break;
-
case LOC_ARG:
- if (SYMBOL_BASEREG_VALID (sym))
- {
- printf ("an argument at offset %ld from register %s",
- val, reg_names[basereg]);
- }
- else
- {
- printf ("an argument at offset %ld", val);
- }
+ printf_filtered ("an argument at offset %ld", val);
break;
case LOC_LOCAL_ARG:
- if (SYMBOL_BASEREG_VALID (sym))
- {
- printf ("an argument at offset %ld from register %s",
- val, reg_names[basereg]);
- }
- else
- {
- printf ("an argument at frame offset %ld", val);
- }
+ printf_filtered ("an argument at frame offset %ld", val);
break;
case LOC_LOCAL:
- if (SYMBOL_BASEREG_VALID (sym))
- {
- printf ("a local variable at offset %ld from register %s",
- val, reg_names[basereg]);
- }
- else
- {
- printf ("a local variable at frame offset %ld", val);
- }
+ printf_filtered ("a local variable at frame offset %ld", val);
break;
case LOC_REF_ARG:
- printf ("a reference argument at offset %ld", val);
+ printf_filtered ("a reference argument at offset %ld", val);
+ break;
+
+ case LOC_BASEREG:
+ printf_filtered ("a variable at offset %ld from register %s",
+ val, reg_names[basereg]);
+ break;
+
+ case LOC_BASEREG_ARG:
+ printf_filtered ("an argument at offset %ld from register %s",
+ val, reg_names[basereg]);
break;
case LOC_TYPEDEF:
- printf ("a typedef");
+ printf_filtered ("a typedef");
break;
case LOC_BLOCK:
- printf ("a function at address %s",
- local_hex_string(BLOCK_START (SYMBOL_BLOCK_VALUE (sym))));
+ printf_filtered ("a function at address ");
+ print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)),
+ gdb_stdout);
break;
case LOC_OPTIMIZED_OUT:
break;
default:
- printf ("of unknown (botched) type");
+ printf_filtered ("of unknown (botched) type");
break;
}
- printf (".\n");
+ printf_filtered (".\n");
}
\f
static void
if (d->format.format != 'i' && d->format.format != 's')
printf_filtered ("%c", d->format.size);
printf_filtered (" ");
- print_expression (d->exp, stdout);
+ print_expression (d->exp, gdb_stdout);
if (d->format.count != 1)
printf_filtered ("\n");
else
{
if (d->format.format)
printf_filtered ("/%c ", d->format.format);
- print_expression (d->exp, stdout);
+ print_expression (d->exp, gdb_stdout);
printf_filtered (" = ");
print_formatted (evaluate_expression (d->exp),
d->format.format, d->format.size);
printf_filtered ("\n");
}
- fflush (stdout);
+ gdb_flush (gdb_stdout);
current_display_number = -1;
}
d->status = disabled;
return;
}
- printf ("No display number %d.\n", num);
+ printf_unfiltered ("No display number %d.\n", num);
}
void
if (current_display_number >= 0)
{
disable_display (current_display_number);
- fprintf (stderr, "Disabling display %d to avoid infinite recursion.\n",
+ fprintf_unfiltered (gdb_stderr, "Disabling display %d to avoid infinite recursion.\n",
current_display_number);
}
current_display_number = -1;
register struct display *d;
if (!display_chain)
- printf ("There are no auto-display expressions now.\n");
+ printf_unfiltered ("There are no auto-display expressions now.\n");
else
printf_filtered ("Auto-display expressions now in effect:\n\
Num Enb Expression\n");
d->format.format);
else if (d->format.format)
printf_filtered ("/%c ", d->format.format);
- print_expression (d->exp, stdout);
+ print_expression (d->exp, gdb_stdout);
if (d->block && !contained_in (get_selected_block (), d->block))
printf_filtered (" (cannot be evaluated in the current context)");
printf_filtered ("\n");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
}
d->status = enabled;
goto win;
}
- printf ("No display number %d.\n", num);
+ printf_unfiltered ("No display number %d.\n", num);
win:
p = p1;
while (*p == ' ' || *p == '\t')
print_variable_value (var, frame, stream)
struct symbol *var;
FRAME frame;
- FILE *stream;
+ GDB_FILE *stream;
{
value val = read_var_value (var, frame);
value_print (val, stream, 0, Val_pretty_default);
struct symbol *func;
struct frame_info *fi;
int num;
- FILE *stream;
+ GDB_FILE *stream;
{
- struct block *b;
+ struct block *b = NULL;
int nsyms = 0;
int first = 1;
register int i;
case LOC_REGPARM:
case LOC_REGPARM_ADDR:
case LOC_LOCAL_ARG:
+ case LOC_BASEREG_ARG:
break;
/* Other types of symbols we just skip over. */
and it is passed as a double and converted to float by
the prologue (in the latter case the type of the LOC_ARG
symbol is double and the type of the LOC_LOCAL symbol is
- float). There are also LOC_ARG/LOC_REGISTER pairs which
- are not combined in symbol-reading. */
+ float). */
/* But if the parameter name is null, don't try it.
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);
+ {
+ struct symbol *nsym;
+ nsym = lookup_symbol
+ (SYMBOL_NAME (sym),
+ b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+ if (SYMBOL_CLASS (nsym) == LOC_REGISTER)
+ {
+ /* There is a LOC_ARG/LOC_REGISTER pair. This means that
+ it was passed on the stack and loaded into a register,
+ or passed in a register and stored in a stack slot.
+ GDB 3.x used the LOC_ARG; GDB 4.0-4.11 used the LOC_REGISTER.
+
+ Reasons for using the LOC_ARG:
+ (1) because find_saved_registers may be slow for remote
+ debugging,
+ (2) because registers are often re-used and stack slots
+ rarely (never?) are. Therefore using the stack slot is
+ much less likely to print garbage.
+
+ Reasons why we might want to use the LOC_REGISTER:
+ (1) So that the backtrace prints the same value as
+ "print foo". I see no compelling reason why this needs
+ to be the case; having the backtrace print the value which
+ was passed in, and "print foo" print the value as modified
+ within the called function, makes perfect sense to me.
+
+ Additional note: It might be nice if "info args" displayed
+ both values.
+ One more note: There is a case with sparc sturcture passing
+ where we need to use the LOC_REGISTER, but this is dealt with
+ by creating a single LOC_REGPARM in symbol reading. */
+
+ /* Leave sym (the LOC_ARG) alone. */
+ ;
+ }
+ else
+ sym = nsym;
+ }
/* Print the current arg. */
if (! first)
long start;
int num;
int first;
- FILE *stream;
+ GDB_FILE *stream;
{
int i;
CORE_ADDR argsaddr;
}
}
\f
-/* Make makeva* work on an __INT_VARARGS_H machine. */
-
-#if defined (__INT_VARARGS_H)
-/* This is used on an 88k. Not sure whether it is used by anything else. */
-#define MAKEVA_END(list) \
- va_list retval; \
- retval.__va_arg = 0; \
- retval.__va_stk = (int *) (list)->arg_bytes; \
- retval.__va_reg = (int *) (list)->arg_bytes; \
- return retval;
-#endif
-\f
-/* This is an interface which allows to us make a va_list. */
-typedef struct {
- unsigned int nargs;
- unsigned int max_arg_size;
-
- /* Current position in bytes. */
- unsigned int argindex;
-
-#ifdef MAKEVA_EXTRA_INFO
- /* For host dependent information. */
- MAKEVA_EXTRA_INFO
-#endif
-
- /* Some systems (mips, pa) would like this to be aligned, and it never
- will hurt. */
- union
- {
- char arg_bytes[1];
- double force_double_align;
- LONGEST force_long_align;
- } aligner;
-} makeva_list;
-
-/* Tell the caller how many bytes to allocate for a makeva_list with NARGS
- arguments and whose largest argument is MAX_ARG_SIZE bytes. This
- way the caller can use alloca, malloc, or some other allocator. */
-unsigned int
-makeva_size (nargs, max_arg_size)
- unsigned int nargs;
- unsigned int max_arg_size;
-{
- return sizeof (makeva_list) + nargs * max_arg_size;
-}
-
-/* Start working on LIST with NARGS arguments and whose largest
- argument is MAX_ARG_SIZE bytes. */
-void
-makeva_start (list, nargs, max_arg_size)
- makeva_list *list;
- unsigned int nargs;
- unsigned int max_arg_size;
-{
- list->nargs = nargs;
- list->max_arg_size = max_arg_size;
-#if defined (MAKEVA_START)
- MAKEVA_START (list);
-#else
- list->argindex = 0;
-#endif
-}
-
-/* Add ARG to LIST. */
-void
-makeva_arg (list, argaddr, argsize)
- makeva_list *list;
- PTR argaddr;
- unsigned int argsize;
-{
-#if defined (MAKEVA_ARG)
- MAKEVA_ARG (list, argaddr, argsize);
-#else
- memcpy (&list->aligner.arg_bytes[list->argindex], argaddr, argsize);
- list->argindex += argsize;
-#endif
-}
-
-/* From LIST, for which makeva_arg has been called for each arg,
- return a va_list containing the args. */
-va_list
-makeva_end (list)
- makeva_list *list;
-{
-#if defined (MAKEVA_END)
- MAKEVA_END (list);
-#else
- /* This works if a va_list is just a pointer to the arguments. */
- return (va_list) list->aligner.arg_bytes;
-#endif
-}
-\f
/* ARGSUSED */
static void
printf_command (arg, from_tty)
register char *s = arg;
char *string;
value *val_args;
+ char *substrings;
+ char *current_substring;
int nargs = 0;
int allocated_args = 20;
- va_list args_to_vprintf;
+ struct cleanup *old_cleanups;
val_args = (value *) xmalloc (allocated_args * sizeof (value));
+ old_cleanups = make_cleanup (free_current_contents, &val_args);
if (s == 0)
error_no_arg ("format-control string and values to print");
processing some kinds of escape sequence. */
f = string = (char *) alloca (strlen (s) + 1);
+
while (*s != '"')
{
int c = *s++;
{
case '\0':
error ("Bad format string, non-terminated '\"'.");
- /* doesn't return */
case '\\':
switch (c = *s++)
if (*s == ',') s++;
while (*s == ' ' || *s == '\t') s++;
+ /* Need extra space for the '\0's. Doubling the size is sufficient. */
+ substrings = alloca (strlen (string) * 2);
+ current_substring = substrings;
+
{
/* Now scan the string for %-specs and see what kinds of args they want.
- argclass[I] classifies the %-specs so we can give vprintf something
+ argclass[I] classifies the %-specs so we can give vprintf_unfiltered something
of the right size. */
-
- enum argclass {int_arg, string_arg, double_arg, long_long_arg};
+
+ enum argclass {no_arg, int_arg, string_arg, double_arg, long_long_arg};
enum argclass *argclass;
+ enum argclass this_argclass;
+ char *last_arg;
int nargs_wanted;
int lcount;
int i;
- makeva_list *args_makeva;
argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
nargs_wanted = 0;
f = string;
+ last_arg = string;
while (*f)
if (*f++ == '%')
{
lcount++;
f++;
}
- if (*f == 's')
- argclass[nargs_wanted++] = string_arg;
- else if (*f == 'e' || *f == 'f' || *f == 'g')
- argclass[nargs_wanted++] = double_arg;
- else if (lcount > 1)
- argclass[nargs_wanted++] = long_long_arg;
- else if (*f != '%')
- argclass[nargs_wanted++] = int_arg;
+ switch (*f)
+ {
+ case 's':
+ this_argclass = string_arg;
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ this_argclass = double_arg;
+ break;
+
+ case '*':
+ error ("`*' not supported for precision or width in printf");
+
+ case 'n':
+ error ("Format specifier `n' not supported in printf");
+
+ case '%':
+ this_argclass = no_arg;
+ break;
+
+ default:
+ if (lcount > 1)
+ this_argclass = long_long_arg;
+ else
+ this_argclass = int_arg;
+ break;
+ }
f++;
+ if (this_argclass != no_arg)
+ {
+ strncpy (current_substring, last_arg, f - last_arg);
+ current_substring += f - last_arg;
+ *current_substring++ = '\0';
+ last_arg = f;
+ argclass[nargs_wanted++] = this_argclass;
+ }
}
-
+
/* Now, parse all arguments and evaluate them.
Store the VALUEs in VAL_ARGS. */
-
+
while (*s != '\0')
{
char *s1;
if (nargs != nargs_wanted)
error ("Wrong number of arguments for specified format-string");
- /* Now lay out an argument-list containing the arguments
- as doubles, integers and C pointers. */
+ /* FIXME: We should be using vprintf_filtered, but as long as it
+ has an arbitrary limit that is unacceptable. Correct fix is
+ for vprintf_filtered to scan down the format string so it knows
+ how big a buffer it needs (perhaps by putting a vasprintf (see
+ GNU C library) in libiberty).
- args_makeva = (makeva_list *)
- alloca (makeva_size (nargs, sizeof (double)));
- makeva_start (args_makeva, nargs, sizeof (double));
+ But for now, just force out any pending output, so at least the output
+ appears in the correct order. */
+ wrap_here ((char *)NULL);
+
+ /* Now actually print them. */
+ current_substring = substrings;
for (i = 0; i < nargs; i++)
{
- if (argclass[i] == string_arg)
+ switch (argclass[i])
{
- char *str;
- CORE_ADDR tem;
- int j;
- tem = value_as_pointer (val_args[i]);
-
- /* This is a %s argument. Find the length of the string. */
- for (j = 0; ; j++)
- {
- char c;
- QUIT;
- read_memory (tem + j, &c, 1);
- if (c == 0)
- break;
- }
-
- /* Copy the string contents into a string inside GDB. */
- str = (char *) alloca (j + 1);
- read_memory (tem, str, j);
- str[j] = 0;
-
- /* Pass address of internal copy as the arg to vprintf. */
- makeva_arg (args_makeva, &str, sizeof (str));
- }
- else if (VALUE_TYPE (val_args[i])->code == TYPE_CODE_FLT)
- {
- double val = value_as_double (val_args[i]);
- makeva_arg (args_makeva, &val, sizeof (val));
- }
- else
-#ifdef CC_HAS_LONG_LONG
- if (argclass[i] == long_long_arg)
+ case string_arg:
+ {
+ char *str;
+ CORE_ADDR tem;
+ int j;
+ tem = value_as_pointer (val_args[i]);
+
+ /* This is a %s argument. Find the length of the string. */
+ for (j = 0; ; j++)
+ {
+ char c;
+ QUIT;
+ read_memory (tem + j, &c, 1);
+ if (c == 0)
+ break;
+ }
+
+ /* Copy the string contents into a string inside GDB. */
+ str = (char *) alloca (j + 1);
+ read_memory (tem, str, j);
+ str[j] = 0;
+
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf_unfiltered (current_substring, str);
+ }
+ break;
+ case double_arg:
+ {
+ double val = value_as_double (val_args[i]);
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf_unfiltered (current_substring, val);
+ break;
+ }
+ case long_long_arg:
+#if defined (CC_HAS_LONG_LONG) && defined (PRINTF_HAS_LONG_LONG)
{
long long val = value_as_long (val_args[i]);
- makeva_arg (args_makeva, &val, sizeof (val));
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf_unfiltered (current_substring, val);
+ break;
}
- else
+#else
+ error ("long long not supported in printf");
#endif
+ case int_arg:
{
+ /* FIXME: there should be separate int_arg and long_arg. */
long val = value_as_long (val_args[i]);
- makeva_arg (args_makeva, &val, sizeof (val));
+ /* Don't use printf_filtered because of arbitrary limit. */
+ printf_unfiltered (current_substring, val);
+ break;
}
+ default:
+ error ("internal error in printf_command");
+ }
+ /* Skip to the next substring. */
+ current_substring += strlen (current_substring) + 1;
}
- args_to_vprintf = makeva_end (args_makeva);
+ /* Print the portion of the format string after the last argument. */
+ /* It would be OK to use printf_filtered here. */
+ printf (last_arg);
}
-
- /* FIXME: We should be using vprintf_filtered, but as long as it has an
- arbitrary limit that is unacceptable. Correct fix is for vprintf_filtered
- to scan down the format string so it knows how big a buffer it needs.
-
- But for now, just force out any pending output, so at least the output
- appears in the correct order. */
- wrap_here ((char *)NULL);
- vprintf (string, args_to_vprintf);
+ do_cleanups (old_cleanups);
}
\f
/* Dump a specified section of assembly code. With no command line
}
else
{
- printf_filtered ("from %s ", local_hex_string(low));
- printf_filtered ("to %s:\n", local_hex_string(high));
+ printf_filtered ("from ");
+ print_address_numeric (low, gdb_stdout);
+ printf_filtered (" to ");
+ print_address_numeric (high, gdb_stdout);
+ printf_filtered (":\n");
}
/* Dump the specified range. */
for (pc = low; pc < high; )
{
QUIT;
- print_address (pc, stdout);
+ print_address (pc, gdb_stdout);
printf_filtered (":\t");
- pc += print_insn (pc, stdout);
+ /* We often wrap here if there are long symbolic names. */
+ wrap_here (" ");
+ pc += print_insn (pc, gdb_stdout);
printf_filtered ("\n");
}
printf_filtered ("End of assembler dump.\n");
- fflush (stdout);
+ gdb_flush (gdb_stdout);
}
\f
"Set printing of source filename and line number with <symbol>.",
&setprintlist),
&showprintlist);
+
+ add_show_from_set (
+ add_set_cmd ("fast-symbolic-addr", no_class, var_boolean,
+ (char *)&fast_symbolic_addr,
+ "Set fast printing of symbolic addresses (using minimal symbols).",
+ &setprintlist),
+ &showprintlist);
+
+ examine_b_type = init_type (TYPE_CODE_INT, 1, 0, NULL, NULL);
+ examine_h_type = init_type (TYPE_CODE_INT, 2, 0, NULL, NULL);
+ examine_w_type = init_type (TYPE_CODE_INT, 4, 0, NULL, NULL);
+ examine_g_type = init_type (TYPE_CODE_INT, 8, 0, NULL, NULL);
}