123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564 |
- /* 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:
- 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);
- }
- /* 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:
- type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
- passed_a_ptr);
- if (passed_a_ptr)
- fputc ('(', stream);
- break;
- case TYPE_CODE_ARRAY:
- type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
- passed_a_ptr);
- }
- }
- /* 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,
- passed_a_ptr);
- 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,
- passed_a_ptr);
- 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);
- type_print_1 (TYPE_FIELD_TYPE (type, i),
- TYPE_FIELD_NAME (type, i),
- stream, show - 1, level + 4);
- if (TYPE_FIELD_PACKED (type, i))
- {
- /* ??? don't know what to put here ??? */;
- }
- 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
|