aboutsummaryrefslogtreecommitdiff
path: root/gdb/RCS/valprint.c,v
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/RCS/valprint.c,v')
-rw-r--r--gdb/RCS/valprint.c,v1117
1 files changed, 1117 insertions, 0 deletions
diff --git a/gdb/RCS/valprint.c,v b/gdb/RCS/valprint.c,v
new file mode 100644
index 0000000..52d89b0
--- /dev/null
+++ b/gdb/RCS/valprint.c,v
@@ -0,0 +1,1117 @@
+head 1.3;
+access ;
+symbols ;
+locks ; strict;
+comment @ * @;
+
+
+1.3
+date 89.04.26.01.49.11; author gnu; state Exp;
+branches ;
+next 1.2;
+
+1.2
+date 89.04.26.00.57.15; author gnu; state Exp;
+branches ;
+next 1.1;
+
+1.1
+date 89.04.25.15.16.40; author gnu; state Exp;
+branches ;
+next ;
+
+
+desc
+@@
+
+
+1.3
+log
+@Fix spelling Nan => NaN
+@
+text
+@/* Print values for GNU debugger gdb.
+ Copyright (C) 1986, 1988 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 "param.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 ();
+static void type_print_method_args ();
+
+
+char **unsigned_type_table;
+char **signed_type_table;
+char **float_type_table;
+
+/* 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
+ the number of string bytes printed. */
+
+int
+value_print (val, stream, format)
+ value val;
+ FILE *stream;
+ char format;
+{
+ 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 (typelen == 1 && TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT
+ && format == 0)
+ {
+ 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, format, 1);
+ }
+ if (i < n)
+ fprintf (stream, "...");
+ }
+ fputc ('}', stream);
+ return n * typelen;
+ }
+ else
+ {
+ /* If it is a pointer, indicate what it points to.
+
+ Print type also if it is a reference.
+
+ C++: if it is a member pointer, we will take care
+ of that when we print it. */
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_PTR
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF)
+ {
+ fprintf (stream, "(");
+ type_print (VALUE_TYPE (val), "", stream, -1);
+ fprintf (stream, ") ");
+ }
+ return val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val), stream, format, 1);
+ }
+}
+
+/* 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).
+
+ If the data are a string pointer, returns the number of
+ sting characters printed.
+
+ if DEREF_REF is nonzero, then dereference references,
+ otherwise just print them like pointers. */
+
+int
+val_print (type, valaddr, address, stream, format, deref_ref)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ char format;
+ int deref_ref;
+{
+ register int i;
+ int len, n_baseclasses;
+ struct type *elttype;
+ int eltlen;
+ LONGEST 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 (eltlen == 1 && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && format == 0)
+ {
+ 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, format, deref_ref);
+ }
+ if (i < len)
+ fprintf (stream, "...");
+ }
+ fprintf (stream, "}");
+ break;
+ }
+ /* Array of unspecified length: treat like pointer. */
+
+ case TYPE_CODE_PTR:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_MEMBER)
+ {
+ struct type *domain = TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type));
+ struct type *target = TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (type));
+ struct fn_field *f;
+ int j, len2;
+ char *kind = "";
+
+ val = unpack_long (builtin_type_int, valaddr);
+ if (TYPE_CODE (target) == TYPE_CODE_FUNC)
+ {
+ if (val < 128)
+ {
+ 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) == val)
+ {
+ kind = "virtual";
+ goto common;
+ }
+ }
+ }
+ }
+ else
+ {
+ struct symbol *sym = find_pc_function ((CORE_ADDR) val);
+ 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)
+ {
+ fputc ('&', 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] == '$')
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+ TYPE_FN_FIELDLIST_NAME (domain, i), stream);
+ else
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j), "",
+ TYPE_FN_FIELDLIST_NAME (domain, i), stream);
+ break;
+ }
+ }
+ else
+ {
+ /* 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;
+ len = TYPE_NFIELDS (domain);
+ val <<= 3; /* @@@@ Make VAL into bit offset */
+ for (i = 0; i < len; i++)
+ {
+ int bitpos = TYPE_FIELD_BITPOS (domain, i);
+ QUIT;
+ if (val == bitpos)
+ break;
+ if (val < bitpos && i > 0)
+ {
+ int ptrsize = (TYPE_LENGTH (builtin_type_char) * TYPE_LENGTH (target));
+ /* Somehow pointing into a field. */
+ i -= 1;
+ extra = (val - TYPE_FIELD_BITPOS (domain, i));
+ if (extra & 0x3)
+ bits = 1;
+ else
+ extra >>= 3;
+ break;
+ }
+ }
+ if (i < len)
+ {
+ fputc ('&', stream);
+ type_print_base (domain, stream, 0, 0);
+ fprintf (stream, "::");
+ fprintf (stream, "%s", TYPE_FIELD_NAME (domain, i));
+ if (extra)
+ fprintf (stream, " + %d bytes", extra);
+ if (bits)
+ fprintf (stream, " (offset in bits)");
+ break;
+ }
+ }
+ fputc ('(', stream);
+ type_print (type, "", stream, -1);
+ fprintf (stream, ") %d", val >> 3);
+ }
+ else
+ {
+ fprintf (stream, "0x%x", * (int *) valaddr);
+ /* For a pointer to char or unsigned char,
+ also print the string pointed to, unless pointer is null. */
+
+ /* For an array of chars, print with string syntax. */
+ elttype = TYPE_TARGET_TYPE (type);
+ i = 0; /* Number of characters printed. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && format == 0
+ /* Convex needs this typecast to a long */
+ && (long) unpack_long (type, valaddr) != 0
+ && print_max)
+ {
+ fputc (' ', stream);
+
+ /* Get first character. */
+ if (read_memory ( (CORE_ADDR) unpack_long (type, valaddr),
+ &c, 1))
+ {
+ /* First address out of bounds. */
+ fprintf (stream, "<Address 0x%x out of bounds>",
+ (* (int *) valaddr));
+ break;
+ }
+ else
+ {
+ /* A real string. */
+ int out_of_bounds = 0;
+
+ fputc ('"', stream);
+ while (c)
+ {
+ QUIT;
+ printchar (c, stream, '"');
+ if (++i >= print_max)
+ break;
+ if (read_memory ((CORE_ADDR) unpack_long (type, valaddr)
+ + i, &c, 1))
+ {
+ /* This address was out of bounds. */
+ fprintf (stream,
+ "\"*** <Address 0x%x out of bounds>",
+ (* (int *) valaddr) + i);
+ out_of_bounds = 1;
+ break;
+ }
+ }
+ if (!out_of_bounds)
+ {
+ 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 + (print_max && i != print_max);
+ }
+ break;
+
+ case TYPE_CODE_MEMBER:
+ error ("not implemented: member type in val_print");
+ break;
+
+ case TYPE_CODE_REF:
+ fprintf (stream, "(0x%x &) = ", * (int *) valaddr);
+ /* De-reference the reference. */
+ if (deref_ref)
+ {
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
+ {
+ value val = value_at (TYPE_TARGET_TYPE (type), * (int *) valaddr);
+ val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val), stream, format, deref_ref);
+ }
+ else
+ fprintf (stream, "???");
+ }
+ break;
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ fprintf (stream, "{");
+ len = TYPE_NFIELDS (type);
+ n_baseclasses = TYPE_N_BASECLASSES (type);
+ for (i = 1; i <= n_baseclasses; i++)
+ {
+ fprintf (stream, "\n<%s> = ", TYPE_NAME (TYPE_BASECLASS (type, i)));
+ val_print (TYPE_FIELD_TYPE (type, 0),
+ valaddr + TYPE_FIELD_BITPOS (type, i-1) / 8,
+ 0, stream, 0, 0);
+ }
+ if (i > 1) fprintf (stream, "\nmembers of %s: ", TYPE_NAME (type));
+ for (i -= 1; i < len; i++)
+ {
+ if (i > n_baseclasses) fprintf (stream, ", ");
+ fprintf (stream, "%s = ", TYPE_FIELD_NAME (type, i));
+ /* check if static field */
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ value v;
+
+ v = value_static_field (type, TYPE_FIELD_NAME (type, i), i);
+ val_print (TYPE_FIELD_TYPE (type, i),
+ VALUE_CONTENTS (v), 0, stream, format, deref_ref);
+ }
+ else if (TYPE_FIELD_PACKED (type, i))
+ {
+ val = unpack_field_as_long (type, valaddr, i);
+ val_print (TYPE_FIELD_TYPE (type, i), &val, 0,
+ stream, format, deref_ref);
+ }
+ else
+ {
+ val_print (TYPE_FIELD_TYPE (type, i),
+ valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
+ 0, stream, format, deref_ref);
+ }
+ }
+ fprintf (stream, "}");
+ break;
+
+ case TYPE_CODE_ENUM:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ len = TYPE_NFIELDS (type);
+ val = (long) unpack_long (builtin_type_int, valaddr);
+ for (i = 0; i < len; i++)
+ {
+ QUIT;
+ if (val == TYPE_FIELD_BITPOS (type, i))
+ break;
+ }
+ if (i < len)
+ fprintf (stream, "%s", TYPE_FIELD_NAME (type, i));
+ else
+ fprintf (stream, "%d", val);
+ break;
+
+ case TYPE_CODE_FUNC:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ fprintf (stream, "{");
+ type_print (type, "", stream, -1);
+ fprintf (stream, "} ");
+ fprintf (stream, "0x%x", address);
+ break;
+
+ case TYPE_CODE_INT:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ fprintf (stream,
+ TYPE_UNSIGNED (type) ? "%u" : "%d",
+ unpack_long (type, valaddr));
+ if (TYPE_LENGTH (type) == 1)
+ {
+ fprintf (stream, " '");
+ printchar ((unsigned char) unpack_long (type, valaddr),
+ stream, '\'');
+ fputc ('\'', stream);
+ }
+ break;
+
+ case TYPE_CODE_FLT:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ /* FIXME: When printing NaNs or invalid floats, print them
+ in raw hex in addition to the message. */
+#ifdef IEEE_FLOAT
+ if (is_nan ((void *)valaddr, TYPE_LENGTH(type)))
+ {
+ fprintf (stream, "NaN");
+ break;
+ }
+#endif
+ {
+ double doub;
+ int inv;
+
+ doub = unpack_double (type, valaddr, &inv);
+ if (inv)
+ fprintf (stream, "Invalid float value");
+ else
+ fprintf (stream, TYPE_LENGTH (type) <= 4? "%.6g": "%.16g", doub);
+ }
+ break;
+
+ case TYPE_CODE_VOID:
+ fprintf (stream, "void");
+ break;
+
+ default:
+ error ("Invalid type code in symbol table.");
+ }
+ fflush (stream);
+}
+
+#ifdef IEEE_FLOAT
+
+/* Nonzero if ARG (a double) is a NAN. */
+
+int
+is_nan (fp, len)
+ void *fp;
+ int len;
+{
+ int lowhalf, highhalf;
+ union ieee {
+ long i[2]; /* ASSUMED 32 BITS */
+ float f; /* ASSUMED 32 BITS */
+ double d; /* ASSUMED 64 BITS */
+ } *arg;
+
+ arg = (union ieee *)fp;
+
+ /*
+ * Single precision float.
+ */
+ if (len == sizeof(long)) {
+ highhalf = arg->i[0];
+ return ((((highhalf >> 23) & 0xFF) == 0xFF)
+ && 0 != (highhalf & 0x7FFFFF));
+ }
+
+ /* Separate the high and low words of the double.
+ Distinguish big and little-endian machines. */
+#ifdef WORDS_BIG_ENDIAN
+ lowhalf = arg->i[1], highhalf = arg->i[0];
+#else
+ lowhalf = arg->i[0], highhalf = arg->i[1];
+#endif
+
+ /* 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. */
+
+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;
+ 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
+ || code == TYPE_CODE_MEMBER
+ || code == TYPE_CODE_REF)))
+ fprintf (stream, " ");
+ type_print_varspec_prefix (type, stream, show, 0);
+ fprintf (stream, "%s", varstring);
+ type_print_varspec_suffix (type, stream, show, 0);
+}
+
+/* Print the method arguments ARGS to the file STREAM. */
+static void
+type_print_method_args (args, prefix, varstring, stream)
+ struct type **args;
+ char *prefix, *varstring;
+ FILE *stream;
+{
+ int i;
+
+ fprintf (stream, " %s%s (", prefix, varstring);
+ if (args[1] && args[1]->code != TYPE_CODE_VOID)
+ {
+ i = 1; /* skip the class variable */
+ while (1)
+ {
+ type_print (args[i++], "", stream, 0);
+ if (!args[i])
+ {
+ fprintf (stream, " ...");
+ break;
+ }
+ else if (args[i]->code != TYPE_CODE_VOID)
+ {
+ fprintf (stream, ", ");
+ }
+ else break;
+ }
+ }
+ fprintf (stream, ")");
+}
+
+/* If TYPE is a derived type, then print out derivation
+ information. Print out all layers of the type heirarchy
+ until we encounter one with multiple inheritance.
+ At that point, print out that ply, and return. */
+static void
+type_print_derivation_info (stream, type)
+ FILE *stream;
+ struct type *type;
+{
+ char *name;
+ int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+ struct type *basetype = 0;
+
+ while (type && n_baseclasses == 1)
+ {
+ basetype = TYPE_BASECLASS (type, 1);
+ if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
+ {
+ while (*name != ' ') name++;
+ fprintf (stream, ": %s%s %s ",
+ TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
+ TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "",
+ name + 1);
+ }
+ n_baseclasses = TYPE_N_BASECLASSES (basetype);
+ type = basetype;
+ }
+
+ if (type)
+ {
+ if (n_baseclasses != 0)
+ fprintf (stream, ": ");
+ for (i = 1; i <= n_baseclasses; i++)
+ {
+ basetype = TYPE_BASECLASS (type, i);
+ if (TYPE_NAME (basetype) && (name = TYPE_NAME (basetype)))
+ {
+ while (*name != ' ') name++;
+ fprintf (stream, "%s%s %s",
+ TYPE_VIA_PUBLIC (basetype) ? "public" : "private",
+ TYPE_VIA_VIRTUAL (basetype) ? " virtual" : "",
+ name + 1);
+ }
+ if (i < n_baseclasses)
+ fprintf (stream, ", ");
+ }
+ putc (' ', 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;
+{
+ 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);
+ fputc ('*', stream);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr);
+ fputc (' ', stream);
+ type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0,
+ passed_a_ptr);
+ fprintf (stream, "::");
+ break;
+
+ case TYPE_CODE_REF:
+ 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 == 0)
+ return;
+
+ 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
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ fprintf (stream, "%d",
+ TYPE_LENGTH (type) / TYPE_LENGTH (TYPE_TARGET_TYPE (type)));
+ fprintf (stream, "]");
+ break;
+
+ case TYPE_CODE_MEMBER:
+ if (passed_a_ptr)
+ fputc (')', stream);
+ type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ break;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ 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 == 0)
+ {
+ fprintf (stream, "type unknown");
+ return;
+ }
+
+ 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_MEMBER:
+ case TYPE_CODE_REF:
+ 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
+ {
+ int i;
+
+ type_print_derivation_info (stream, type);
+
+ fprintf (stream, "{");
+ len = TYPE_NFIELDS (type);
+ if (len) fprintf (stream, "\n");
+ else fprintf (stream, "<no data fields>\n");
+
+ /* If there is a base class for this type,
+ do not print the field that it occupies. */
+ for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+ {
+ QUIT;
+ /* Don't print out virtual function table. */
+ if (! strncmp (TYPE_FIELD_NAME (type, i),
+ "_vptr$", 6))
+ continue;
+
+ print_spaces (level + 4, stream);
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ fprintf (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))
+ {
+ /* ??? don't know what to put here ??? */;
+ }
+ fprintf (stream, ";\n");
+ }
+
+ /* C++: print out the methods */
+ len = TYPE_NFN_FIELDS (type);
+ if (len) fprintf (stream, "\n");
+ for (i = 0; i < len; i++)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ print_spaces (level + 4, stream);
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ fprintf (stream, "virtual ");
+ type_print (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))), "", stream, 0);
+ if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+ && TYPE_FN_FIELD_PHYSNAME (f, j)[1] == '$')
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+ TYPE_FN_FIELDLIST_NAME (type, i), stream);
+ else
+ type_print_method_args
+ (TYPE_FN_FIELD_ARGS (f, j), "",
+ TYPE_FN_FIELDLIST_NAME (type, i), stream);
+
+ fprintf (stream, ";\n");
+ }
+ if (len2) 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_BITPOS (type, i))
+ {
+ fprintf (stream, " : %d", TYPE_FIELD_BITPOS (type, i));
+ lastval = TYPE_FIELD_BITPOS (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);
+}
+
+extern struct cmd_list_element *setlist;
+
+void
+_initialize_valprint ()
+{
+ add_cmd ("array-max", class_vars, set_maximum_command,
+ "Set NUMBER as limit on string chars or array elements to print.",
+ &setlist);
+
+ print_max = 200;
+
+ unsigned_type_table
+ = (char **) xmalloc ((1 + sizeof (unsigned LONGEST)) * sizeof (char *));
+ bzero (unsigned_type_table, (1 + sizeof (unsigned LONGEST)));
+ 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";
+#ifdef LONG_LONG
+ unsigned_type_table[sizeof (unsigned long long)] = "unsigned long long";
+#endif
+
+ signed_type_table
+ = (char **) xmalloc ((1 + sizeof (LONGEST)) * sizeof (char *));
+ bzero (signed_type_table, (1 + sizeof (LONGEST)));
+ signed_type_table[sizeof (char)] = "char";
+ signed_type_table[sizeof (short)] = "short";
+ signed_type_table[sizeof (long)] = "long";
+ signed_type_table[sizeof (int)] = "int";
+#ifdef LONG_LONG
+ signed_type_table[sizeof (long long)] = "long long";
+#endif
+
+ 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";
+}
+
+@
+
+
+1.2
+log
+@(1) Use XXX_BIG_ENDIAN macros rather than testing at runtime.
+(2) Change args to is_nan, support floats, change one call to it.
+(3) Change args to unpack_double.
+@
+text
+@d488 1
+a488 1
+ fprintf (stream, "Nan");
+@
+
+
+1.1
+log
+@Initial revision
+@
+text
+@d483 2
+d486 1
+a486 1
+ if (is_nan (unpack_double (type, valaddr)))
+d492 10
+a501 4
+ if (TYPE_LENGTH (type) <= 4)
+ fprintf (stream, "%.6g", unpack_double (type, valaddr));
+ else
+ fprintf (stream, "%.16g", unpack_double (type, valaddr));
+a515 5
+union ieee {
+ int i[2];
+ double d;
+};
+
+d519 3
+a521 2
+is_nan (arg)
+ union ieee arg;
+d524 16
+a539 1
+ union { int i; char c; } test;
+d543 5
+a547 6
+ 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];
+@