mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 09:38:57 +00:00
gdb-2.4+.aux.coff
This commit is contained in:
622
gdb/valprint.c
Normal file
622
gdb/valprint.c
Normal file
@@ -0,0 +1,622 @@
|
||||
/* Print values for GNU debugger gdb.
|
||||
Copyright (C) 1986 Free Software Foundation, Inc.
|
||||
|
||||
GDB is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY. No author or distributor accepts responsibility to anyone
|
||||
for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing.
|
||||
Refer to the GDB General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute GDB,
|
||||
but only under the conditions described in the GDB General Public
|
||||
License. A copy of this license is supposed to have been given to you
|
||||
along with GDB so you can know your rights and responsibilities. It
|
||||
should be in a file named COPYING. Among other things, the copyright
|
||||
notice and this notice must be preserved on all copies.
|
||||
|
||||
In other words, go ahead and share GDB, but don't try to stop
|
||||
anyone else from sharing it farther. Help stamp out software hoarding!
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "initialize.h"
|
||||
#include "symtab.h"
|
||||
#include "value.h"
|
||||
|
||||
/* Maximum number of chars to print for a string pointer value
|
||||
or vector contents. */
|
||||
|
||||
static int print_max;
|
||||
|
||||
static void type_print_varspec_suffix ();
|
||||
static void type_print_varspec_prefix ();
|
||||
static void type_print_base ();
|
||||
|
||||
START_FILE
|
||||
|
||||
char **unsigned_type_table;
|
||||
char **signed_type_table;
|
||||
char **float_type_table;
|
||||
|
||||
/* Print the value VAL in C-ish syntax on stream STREAM.
|
||||
If the object printed is a string pointer, returns
|
||||
the number of string bytes printed. */
|
||||
|
||||
value_print (val, stream)
|
||||
value val;
|
||||
FILE *stream;
|
||||
{
|
||||
register int i, n, typelen;
|
||||
|
||||
/* A "repeated" value really contains several values in a row.
|
||||
They are made by the @ operator.
|
||||
Print such values as if they were arrays. */
|
||||
|
||||
if (VALUE_REPEATED (val))
|
||||
{
|
||||
n = VALUE_REPETITIONS (val);
|
||||
typelen = TYPE_LENGTH (VALUE_TYPE (val));
|
||||
fputc ('{', stream);
|
||||
/* Print arrays of characters using string syntax. */
|
||||
if (VALUE_TYPE (val) == builtin_type_char
|
||||
|| VALUE_TYPE (val) == builtin_type_unsigned_char)
|
||||
{
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < n && i < print_max; i++)
|
||||
{
|
||||
QUIT;
|
||||
printchar (VALUE_CONTENTS (val)[i], stream);
|
||||
}
|
||||
if (i < n)
|
||||
fprintf (stream, "...");
|
||||
fputc ('"', stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < n && i < print_max; i++)
|
||||
{
|
||||
if (i)
|
||||
fprintf (stream, ", ");
|
||||
val_print (VALUE_TYPE (val), VALUE_CONTENTS (val) + typelen * i,
|
||||
VALUE_ADDRESS (val) + typelen * i, stream);
|
||||
}
|
||||
if (i < n)
|
||||
fprintf (stream, "...");
|
||||
}
|
||||
fputc ('}', stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A simple (nonrepeated) value */
|
||||
/* If it is a pointer, indicate what it points to. */
|
||||
if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR)
|
||||
{
|
||||
fprintf (stream, "(");
|
||||
type_print (VALUE_TYPE (val), "", stream, -1);
|
||||
fprintf (stream, ") ");
|
||||
}
|
||||
return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
|
||||
VALUE_ADDRESS (val), stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print on STREAM data stored in debugger at address VALADDR
|
||||
according to the format of type TYPE.
|
||||
ADDRESS is the location in the inferior that the data
|
||||
is supposed to have come from.
|
||||
|
||||
If the data are a string pointer, returns the number of
|
||||
sting characters printed. */
|
||||
|
||||
int
|
||||
val_print (type, valaddr, address, stream)
|
||||
struct type *type;
|
||||
char *valaddr;
|
||||
CORE_ADDR address;
|
||||
FILE *stream;
|
||||
{
|
||||
register int i;
|
||||
int len;
|
||||
struct type *elttype;
|
||||
int eltlen;
|
||||
int val;
|
||||
unsigned char c;
|
||||
|
||||
QUIT;
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (TYPE_LENGTH (type) >= 0)
|
||||
{
|
||||
elttype = TYPE_TARGET_TYPE (type);
|
||||
eltlen = TYPE_LENGTH (elttype);
|
||||
len = TYPE_LENGTH (type) / eltlen;
|
||||
fprintf (stream, "{");
|
||||
/* For an array of chars, print with string syntax. */
|
||||
if (elttype == builtin_type_char
|
||||
|| elttype == builtin_type_unsigned_char)
|
||||
{
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < len && i < print_max; i++)
|
||||
{
|
||||
QUIT;
|
||||
printchar (valaddr[i], stream);
|
||||
}
|
||||
if (i < len)
|
||||
fprintf (stream, "...");
|
||||
fputc ('"', stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < len && i < print_max; i++)
|
||||
{
|
||||
if (i) fprintf (stream, ", ");
|
||||
val_print (elttype, valaddr + i * eltlen,
|
||||
0, stream);
|
||||
}
|
||||
if (i < len)
|
||||
fprintf (stream, "...");
|
||||
}
|
||||
fprintf (stream, "}");
|
||||
break;
|
||||
}
|
||||
/* Array of unspecified length: treat like pointer. */
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
fprintf (stream, "0x%x", * (int *) valaddr);
|
||||
/* For a pointer to char or unsigned char,
|
||||
also print the string pointed to, unless pointer is null. */
|
||||
if ((TYPE_TARGET_TYPE (type) == builtin_type_char
|
||||
|| TYPE_TARGET_TYPE (type) == builtin_type_unsigned_char)
|
||||
&& unpack_long (type, valaddr) != 0)
|
||||
{
|
||||
fputc (' ', stream);
|
||||
fputc ('"', stream);
|
||||
for (i = 0; i < print_max; i++)
|
||||
{
|
||||
QUIT;
|
||||
read_memory (unpack_long (type, valaddr) + i, &c, 1);
|
||||
if (c == 0)
|
||||
break;
|
||||
printchar (c, stream);
|
||||
}
|
||||
fputc ('"', stream);
|
||||
if (i == print_max)
|
||||
fprintf (stream, "...");
|
||||
fflush (stream);
|
||||
/* Return number of characters printed, plus one for the
|
||||
terminating null if we have "reached the end". */
|
||||
return i + (i != print_max);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (i) fprintf (stream, ", ");
|
||||
fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i));
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
val = unpack_field_as_long (type, valaddr, i);
|
||||
val_print (TYPE_FIELD_TYPE (type, i), &val, 0, stream);
|
||||
}
|
||||
else
|
||||
val_print (TYPE_FIELD_TYPE (type, i),
|
||||
valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
|
||||
0, stream);
|
||||
}
|
||||
fprintf (stream, "}");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
len = TYPE_NFIELDS (type);
|
||||
val = unpack_long (builtin_type_int, valaddr);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (val == TYPE_FIELD_VALUE (type, i))
|
||||
break;
|
||||
}
|
||||
if (i < len)
|
||||
fprintf (stream, "%s", TYPE_FIELD_NAME (type, i));
|
||||
else
|
||||
fprintf (stream, "%d", val);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
fprintf (stream, "{");
|
||||
type_print (type, "", stream, -1);
|
||||
fprintf (stream, "} ");
|
||||
fprintf (stream, "0x%x", address);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
fprintf (stream,
|
||||
TYPE_UNSIGNED (type) ? "%u" : "%d",
|
||||
unpack_long (type, valaddr));
|
||||
if (type == builtin_type_char
|
||||
|| type == builtin_type_unsigned_char)
|
||||
{
|
||||
fprintf (stream, " '");
|
||||
printchar (unpack_long (type, valaddr), stream);
|
||||
fputc ('\'', stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
#ifdef IEEE_FLOAT
|
||||
if (is_nan (unpack_double (type, valaddr)))
|
||||
{
|
||||
fprintf (stream, "Nan");
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
fprintf (stream, "%g", unpack_double (type, valaddr));
|
||||
break;
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
fprintf (stream, "void");
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid type code in symbol table.");
|
||||
}
|
||||
fflush (stream);
|
||||
}
|
||||
|
||||
#ifdef IEEE_FLOAT
|
||||
|
||||
union ieee {
|
||||
int i[2];
|
||||
double d;
|
||||
};
|
||||
|
||||
/* Nonzero if ARG (a double) is a NAN. */
|
||||
|
||||
int
|
||||
is_nan (arg)
|
||||
union ieee arg;
|
||||
{
|
||||
int lowhalf, highhalf;
|
||||
union { int i; char c; } test;
|
||||
|
||||
/* Separate the high and low words of the double.
|
||||
Distinguish big and little-endian machines. */
|
||||
test.i = 1;
|
||||
if (test.c != 1)
|
||||
/* Big-endian machine */
|
||||
lowhalf = arg.i[1], highhalf = arg.i[0];
|
||||
else
|
||||
lowhalf = arg.i[0], highhalf = arg.i[1];
|
||||
|
||||
/* Nan: exponent is the maximum possible, and fraction is nonzero. */
|
||||
return (((highhalf>>20) & 0x7ff) == 0x7ff
|
||||
&&
|
||||
! ((highhalf & 0xfffff == 0) && (lowhalf == 0)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print a description of a type TYPE
|
||||
in the form of a declaration of a variable named VARSTRING.
|
||||
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. */
|
||||
|
||||
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. */
|
||||
|
||||
type_print_1 (type, varstring, stream, show, level)
|
||||
struct type *type;
|
||||
char *varstring;
|
||||
FILE *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
register enum type_code code;
|
||||
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_ARRAY)))
|
||||
fprintf (stream, " ");
|
||||
type_print_varspec_prefix (type, stream, show, 0);
|
||||
fprintf (stream, "%s", varstring);
|
||||
type_print_varspec_suffix (type, stream, show, 0);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
{
|
||||
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);
|
||||
fputc ('*', stream);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_ARRAY:
|
||||
type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fputc ('(', stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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)
|
||||
struct type *type;
|
||||
FILE *stream;
|
||||
int show;
|
||||
int passed_a_ptr;
|
||||
{
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
return;
|
||||
|
||||
QUIT;
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf (stream, ")");
|
||||
fprintf (stream, "[");
|
||||
if (TYPE_LENGTH (type) >= 0)
|
||||
fprintf (stream, "%d",
|
||||
TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type)));
|
||||
fprintf (stream, "]");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
if (passed_a_ptr)
|
||||
fprintf (stream, ")");
|
||||
fprintf (stream, "()");
|
||||
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. */
|
||||
|
||||
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;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (TYPE_NAME (type) && show <= 0)
|
||||
{
|
||||
fprintf (stream, TYPE_NAME (type));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_ARRAY:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_FUNC:
|
||||
type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_STRUCT:
|
||||
fprintf (stream, "struct ");
|
||||
goto struct_union;
|
||||
|
||||
case TYPE_CODE_UNION:
|
||||
fprintf (stream, "union ");
|
||||
struct_union:
|
||||
if (TYPE_NAME (type) && (name = TYPE_NAME (type)))
|
||||
{
|
||||
while (*name != ' ') name++;
|
||||
fprintf (stream, "%s ", name + 1);
|
||||
}
|
||||
if (show < 0)
|
||||
fprintf (stream, "{...}");
|
||||
else
|
||||
{
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
fprintf (stream, "\n");
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
print_spaces (level + 4, stream);
|
||||
|
||||
/* If this is a bit-field and there is a gap before it,
|
||||
print a nameless field to account for the gap. */
|
||||
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
{
|
||||
int gap = (TYPE_FIELD_BITPOS (type, i)
|
||||
- (i > 0
|
||||
? (TYPE_FIELD_BITPOS (type, i - 1)
|
||||
+ (TYPE_FIELD_PACKED (type, i - 1)
|
||||
? TYPE_FIELD_BITSIZE (type, i - 1)
|
||||
: TYPE_LENGTH (TYPE_FIELD_TYPE (type, i - 1)) * 8))
|
||||
: 0));
|
||||
if (gap != 0)
|
||||
{
|
||||
fprintf (stream, "int : %d;\n", gap);
|
||||
print_spaces (level + 4, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the declaration of this field. */
|
||||
|
||||
type_print_1 (TYPE_FIELD_TYPE (type, i),
|
||||
TYPE_FIELD_NAME (type, i),
|
||||
stream, show - 1, level + 4);
|
||||
|
||||
/* Print the field width. */
|
||||
|
||||
if (TYPE_FIELD_PACKED (type, i))
|
||||
fprintf (stream, " : %d", TYPE_FIELD_BITSIZE (type, i));
|
||||
|
||||
fprintf (stream, ";\n");
|
||||
}
|
||||
print_spaces (level, stream);
|
||||
fputc ('}', stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
fprintf (stream, "enum ");
|
||||
if (TYPE_NAME (type))
|
||||
{
|
||||
name = TYPE_NAME (type);
|
||||
while (*name != ' ') name++;
|
||||
fprintf (stream, "%s ", name + 1);
|
||||
}
|
||||
if (show < 0)
|
||||
fprintf (stream, "{...}");
|
||||
else
|
||||
{
|
||||
fprintf (stream, "{");
|
||||
len = TYPE_NFIELDS (type);
|
||||
lastval = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
QUIT;
|
||||
if (i) fprintf (stream, ", ");
|
||||
fprintf (stream, "%s", TYPE_FIELD_NAME (type, i));
|
||||
if (lastval != TYPE_FIELD_VALUE (type, i))
|
||||
{
|
||||
fprintf (stream, " : %d", TYPE_FIELD_VALUE (type, i));
|
||||
lastval = TYPE_FIELD_VALUE (type, i);
|
||||
}
|
||||
lastval++;
|
||||
}
|
||||
fprintf (stream, "}");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_INT:
|
||||
if (TYPE_UNSIGNED (type))
|
||||
name = unsigned_type_table[TYPE_LENGTH (type)];
|
||||
else
|
||||
name = signed_type_table[TYPE_LENGTH (type)];
|
||||
fprintf (stream, "%s", name);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FLT:
|
||||
name = float_type_table[TYPE_LENGTH (type)];
|
||||
fprintf (stream, "%s", name);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_VOID:
|
||||
fprintf (stream, "void");
|
||||
break;
|
||||
|
||||
case 0:
|
||||
fprintf (stream, "struct unknown");
|
||||
break;
|
||||
|
||||
default:
|
||||
error ("Invalid type code in symbol table.");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_maximum_command (arg)
|
||||
char *arg;
|
||||
{
|
||||
if (!arg) error_no_arg ("value for maximum elements to print");
|
||||
print_max = atoi (arg);
|
||||
}
|
||||
|
||||
static
|
||||
initialize ()
|
||||
{
|
||||
add_com ("set-maximum", class_vars, set_maximum_command,
|
||||
"Set NUMBER as limit on string chars or array elements to print.");
|
||||
|
||||
print_max = 200;
|
||||
|
||||
unsigned_type_table
|
||||
= (char **) xmalloc ((1 + sizeof (unsigned long)) * sizeof (char *));
|
||||
bzero (unsigned_type_table, (1 + sizeof (unsigned long)));
|
||||
unsigned_type_table[sizeof (unsigned char)] = "unsigned char";
|
||||
unsigned_type_table[sizeof (unsigned short)] = "unsigned short";
|
||||
unsigned_type_table[sizeof (unsigned long)] = "unsigned long";
|
||||
unsigned_type_table[sizeof (unsigned int)] = "unsigned int";
|
||||
|
||||
signed_type_table
|
||||
= (char **) xmalloc ((1 + sizeof (long)) * sizeof (char *));
|
||||
bzero (signed_type_table, (1 + sizeof (long)));
|
||||
signed_type_table[sizeof (char)] = "char";
|
||||
signed_type_table[sizeof (short)] = "short";
|
||||
signed_type_table[sizeof (long)] = "long";
|
||||
signed_type_table[sizeof (int)] = "int";
|
||||
|
||||
float_type_table
|
||||
= (char **) xmalloc ((1 + sizeof (double)) * sizeof (char *));
|
||||
bzero (float_type_table, (1 + sizeof (double)));
|
||||
float_type_table[sizeof (float)] = "float";
|
||||
float_type_table[sizeof (double)] = "double";
|
||||
}
|
||||
|
||||
END_FILE
|
||||
Reference in New Issue
Block a user