mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
2000-06-14 Pierre Muller <muller@ics.u-strasbg.fr>
Add support for Pascal language. Part 1: new files. * p-exp.y, p-lang.c, p-lang.h, p-typeprint.c, p-valprint.c: New files.
This commit is contained in:
parent
c06ae4f232
commit
373a824730
@ -1,3 +1,8 @@
|
||||
2000-06-14 Pierre Muller <muller@ics.u-strasbg.fr>
|
||||
|
||||
Add support for Pascal language. Part 1: new files.
|
||||
* p-exp.y, p-lang.c, p-lang.h, p-typeprint.c, p-valprint.c: New files.
|
||||
|
||||
2000-06-13 Kevin Buettner <kevinb@redhat.com>
|
||||
|
||||
* ser-ocd.c, symtab.c: Eliminate use of PARAMS from these files.
|
||||
|
1446
gdb/p-exp.y
Normal file
1446
gdb/p-exp.y
Normal file
File diff suppressed because it is too large
Load Diff
430
gdb/p-lang.c
Normal file
430
gdb/p-lang.c
Normal file
@ -0,0 +1,430 @@
|
||||
/* Pascal language support routines for GDB, the GNU debugger.
|
||||
Copyright 2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This file is derived from p-lang.c */
|
||||
|
||||
#include "defs.h"
|
||||
#include "symtab.h"
|
||||
#include "gdbtypes.h"
|
||||
#include "expression.h"
|
||||
#include "parser-defs.h"
|
||||
#include "language.h"
|
||||
#include "p-lang.h"
|
||||
#include "valprint.h"
|
||||
|
||||
extern void _initialize_pascal_language (void);
|
||||
static void pascal_one_char (int, struct ui_file *, int *);
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string.
|
||||
In_quotes is reset to 0 if a char is written with #4 notation */
|
||||
|
||||
static void
|
||||
pascal_one_char (c, stream, in_quotes)
|
||||
register int c;
|
||||
struct ui_file *stream;
|
||||
int *in_quotes;
|
||||
{
|
||||
|
||||
c &= 0xFF; /* Avoid sign bit follies */
|
||||
|
||||
if ((c == '\'') || (PRINT_LITERAL_FORM (c)))
|
||||
{
|
||||
if (!(*in_quotes))
|
||||
fputs_filtered ("'", stream);
|
||||
*in_quotes = 1;
|
||||
if (c == '\'')
|
||||
{
|
||||
fputs_filtered ("''", stream);
|
||||
}
|
||||
else
|
||||
fprintf_filtered (stream, "%c", c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*in_quotes)
|
||||
fputs_filtered ("'", stream);
|
||||
*in_quotes = 0;
|
||||
fprintf_filtered (stream, "#%d", (unsigned int) c);
|
||||
}
|
||||
}
|
||||
|
||||
static void pascal_emit_char (int c, struct ui_file *stream, int quoter);
|
||||
|
||||
/* Print the character C on STREAM as part of the contents of a literal
|
||||
string whose delimiter is QUOTER. Note that that format for printing
|
||||
characters and strings is language specific. */
|
||||
|
||||
static void
|
||||
pascal_emit_char (c, stream, quoter)
|
||||
register int c;
|
||||
struct ui_file *stream;
|
||||
int quoter;
|
||||
{
|
||||
int in_quotes = 0;
|
||||
pascal_one_char (c, stream, &in_quotes);
|
||||
if (in_quotes)
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
void
|
||||
pascal_printchar (c, stream)
|
||||
int c;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
int in_quotes = 0;
|
||||
pascal_one_char (c, stream, &in_quotes);
|
||||
if (in_quotes)
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
/* Print the character string STRING, printing at most LENGTH characters.
|
||||
Printing stops early if the number hits print_max; repeat counts
|
||||
are printed as appropriate. Print ellipses at the end if we
|
||||
had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. */
|
||||
|
||||
void
|
||||
pascal_printstr (stream, string, length, width, force_ellipses)
|
||||
struct ui_file *stream;
|
||||
char *string;
|
||||
unsigned int length;
|
||||
int width;
|
||||
int force_ellipses;
|
||||
{
|
||||
register unsigned int i;
|
||||
unsigned int things_printed = 0;
|
||||
int in_quotes = 0;
|
||||
int need_comma = 0;
|
||||
extern int inspect_it;
|
||||
|
||||
/* If the string was not truncated due to `set print elements', and
|
||||
the last byte of it is a null, we don't print that, in traditional C
|
||||
style. */
|
||||
if ((!force_ellipses) && length > 0 && string[length - 1] == '\0')
|
||||
length--;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
fputs_filtered ("''", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < length && things_printed < print_max; ++i)
|
||||
{
|
||||
/* Position of the character we are examining
|
||||
to see whether it is repeated. */
|
||||
unsigned int rep1;
|
||||
/* Number of repetitions we have detected so far. */
|
||||
unsigned int reps;
|
||||
|
||||
QUIT;
|
||||
|
||||
if (need_comma)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
need_comma = 0;
|
||||
}
|
||||
|
||||
rep1 = i + 1;
|
||||
reps = 1;
|
||||
while (rep1 < length && string[rep1] == string[i])
|
||||
{
|
||||
++rep1;
|
||||
++reps;
|
||||
}
|
||||
|
||||
if (reps > repeat_count_threshold)
|
||||
{
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\', ", stream);
|
||||
else
|
||||
fputs_filtered ("', ", stream);
|
||||
in_quotes = 0;
|
||||
}
|
||||
pascal_printchar (string[i], stream);
|
||||
fprintf_filtered (stream, " <repeats %u times>", reps);
|
||||
i = rep1 - 1;
|
||||
things_printed += repeat_count_threshold;
|
||||
need_comma = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int c = string[i];
|
||||
if ((!in_quotes) && (PRINT_LITERAL_FORM (c)))
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\'", stream);
|
||||
else
|
||||
fputs_filtered ("'", stream);
|
||||
in_quotes = 1;
|
||||
}
|
||||
pascal_one_char (c, stream, &in_quotes);
|
||||
++things_printed;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the quotes if necessary. */
|
||||
if (in_quotes)
|
||||
{
|
||||
if (inspect_it)
|
||||
fputs_filtered ("\\'", stream);
|
||||
else
|
||||
fputs_filtered ("'", stream);
|
||||
}
|
||||
|
||||
if (force_ellipses || i < length)
|
||||
fputs_filtered ("...", stream);
|
||||
}
|
||||
|
||||
/* Create a fundamental Pascal type using default reasonable for the current
|
||||
target machine.
|
||||
|
||||
Some object/debugging file formats (DWARF version 1, COFF, etc) do not
|
||||
define fundamental types such as "int" or "double". Others (stabs or
|
||||
DWARF version 2, etc) do define fundamental types. For the formats which
|
||||
don't provide fundamental types, gdb can create such types using this
|
||||
function.
|
||||
|
||||
FIXME: Some compilers distinguish explicitly signed integral types
|
||||
(signed short, signed int, signed long) from "regular" integral types
|
||||
(short, int, long) in the debugging information. There is some dis-
|
||||
agreement as to how useful this feature is. In particular, gcc does
|
||||
not support this. Also, only some debugging formats allow the
|
||||
distinction to be passed on to a debugger. For now, we always just
|
||||
use "short", "int", or "long" as the type name, for both the implicit
|
||||
and explicitly signed types. This also makes life easier for the
|
||||
gdb test suite since we don't have to account for the differences
|
||||
in output depending upon what the compiler and debugging format
|
||||
support. We will probably have to re-examine the issue when gdb
|
||||
starts taking it's fundamental type information directly from the
|
||||
debugging information supplied by the compiler. fnf@cygnus.com */
|
||||
|
||||
/* Note there might be some discussion about the choosen correspondance
|
||||
because it mainly reflects Free Pascal Compiler setup for now PM */
|
||||
|
||||
|
||||
struct type *
|
||||
pascal_create_fundamental_type (objfile, typeid)
|
||||
struct objfile *objfile;
|
||||
int typeid;
|
||||
{
|
||||
register struct type *type = NULL;
|
||||
|
||||
switch (typeid)
|
||||
{
|
||||
default:
|
||||
/* FIXME: For now, if we are asked to produce a type not in this
|
||||
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);
|
||||
warning ("internal error: no Pascal fundamental type %d", typeid);
|
||||
break;
|
||||
case FT_VOID:
|
||||
type = init_type (TYPE_CODE_VOID,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "void", objfile);
|
||||
break;
|
||||
case FT_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "char", objfile);
|
||||
break;
|
||||
case FT_SIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
0, "shortint", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_CHAR:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_CHAR_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "byte", objfile);
|
||||
break;
|
||||
case FT_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0, "integer", objfile);
|
||||
break;
|
||||
case FT_SIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
0, "integer", objfile); /* FIXME-fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_SHORT:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_SHORT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "word", objfile);
|
||||
break;
|
||||
case FT_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "longint", objfile);
|
||||
break;
|
||||
case FT_SIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
0, "longint", objfile); /* FIXME -fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_INTEGER:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_INT_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "cardinal", objfile);
|
||||
break;
|
||||
case FT_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long", objfile);
|
||||
break;
|
||||
case FT_SIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long", objfile); /* FIXME -fnf */
|
||||
break;
|
||||
case FT_UNSIGNED_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
|
||||
break;
|
||||
case FT_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "long long", objfile);
|
||||
break;
|
||||
case FT_SIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
0, "signed long long", objfile);
|
||||
break;
|
||||
case FT_UNSIGNED_LONG_LONG:
|
||||
type = init_type (TYPE_CODE_INT,
|
||||
TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
|
||||
TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
|
||||
0, "float", objfile);
|
||||
break;
|
||||
case FT_DBL_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "double", objfile);
|
||||
break;
|
||||
case FT_EXT_PREC_FLOAT:
|
||||
type = init_type (TYPE_CODE_FLT,
|
||||
TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
|
||||
0, "extended", objfile);
|
||||
break;
|
||||
}
|
||||
return (type);
|
||||
}
|
||||
|
||||
|
||||
/* Table mapping opcodes into strings for printing operators
|
||||
and precedences of the operators. */
|
||||
|
||||
const struct op_print pascal_op_print_tab[] =
|
||||
{
|
||||
{",", BINOP_COMMA, PREC_COMMA, 0},
|
||||
{":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
|
||||
{"or", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
|
||||
{"xor", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
|
||||
{"and", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
|
||||
{"=", BINOP_EQUAL, PREC_EQUAL, 0},
|
||||
{"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
|
||||
{"<=", BINOP_LEQ, PREC_ORDER, 0},
|
||||
{">=", BINOP_GEQ, PREC_ORDER, 0},
|
||||
{">", BINOP_GTR, PREC_ORDER, 0},
|
||||
{"<", BINOP_LESS, PREC_ORDER, 0},
|
||||
{"shr", BINOP_RSH, PREC_SHIFT, 0},
|
||||
{"shl", BINOP_LSH, PREC_SHIFT, 0},
|
||||
{"+", BINOP_ADD, PREC_ADD, 0},
|
||||
{"-", BINOP_SUB, PREC_ADD, 0},
|
||||
{"*", BINOP_MUL, PREC_MUL, 0},
|
||||
{"/", BINOP_DIV, PREC_MUL, 0},
|
||||
{"div", BINOP_INTDIV, PREC_MUL, 0},
|
||||
{"mod", BINOP_REM, PREC_MUL, 0},
|
||||
{"@", BINOP_REPEAT, PREC_REPEAT, 0},
|
||||
{"-", UNOP_NEG, PREC_PREFIX, 0},
|
||||
{"not", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
|
||||
{"^", UNOP_IND, PREC_SUFFIX, 1},
|
||||
{"@", UNOP_ADDR, PREC_PREFIX, 0},
|
||||
{"sizeof", UNOP_SIZEOF, PREC_PREFIX, 0},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
struct type **const /* CONST_PTR v 4.17 */ (pascal_builtin_types[]) =
|
||||
{
|
||||
&builtin_type_int,
|
||||
&builtin_type_long,
|
||||
&builtin_type_short,
|
||||
&builtin_type_char,
|
||||
&builtin_type_float,
|
||||
&builtin_type_double,
|
||||
&builtin_type_void,
|
||||
&builtin_type_long_long,
|
||||
&builtin_type_signed_char,
|
||||
&builtin_type_unsigned_char,
|
||||
&builtin_type_unsigned_short,
|
||||
&builtin_type_unsigned_int,
|
||||
&builtin_type_unsigned_long,
|
||||
&builtin_type_unsigned_long_long,
|
||||
&builtin_type_long_double,
|
||||
&builtin_type_complex,
|
||||
&builtin_type_double_complex,
|
||||
0
|
||||
};
|
||||
|
||||
const struct language_defn pascal_language_defn =
|
||||
{
|
||||
"pascal", /* Language name */
|
||||
language_pascal,
|
||||
pascal_builtin_types,
|
||||
range_check_on,
|
||||
type_check_on,
|
||||
pascal_parse,
|
||||
pascal_error,
|
||||
evaluate_subexp_standard,
|
||||
pascal_printchar, /* Print a character constant */
|
||||
pascal_printstr, /* Function to print string constant */
|
||||
pascal_emit_char, /* Print a single char */
|
||||
pascal_create_fundamental_type, /* Create fundamental type in this language */
|
||||
pascal_print_type, /* Print a type using appropriate syntax */
|
||||
pascal_val_print, /* Print a value using appropriate syntax */
|
||||
pascal_value_print, /* Print a top-level value */
|
||||
{"", "%", "b", ""}, /* Binary format info */
|
||||
{"0%lo", "0", "o", ""}, /* Octal format info */
|
||||
{"%ld", "", "d", ""}, /* Decimal format info */
|
||||
{"$%lx", "$", "x", ""}, /* Hex format info */
|
||||
pascal_op_print_tab, /* expression operators for printing */
|
||||
1, /* c-style arrays */
|
||||
0, /* String lower bound */
|
||||
&builtin_type_char, /* Type of string elements */
|
||||
LANG_MAGIC
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_pascal_language ()
|
||||
{
|
||||
add_language (&pascal_language_defn);
|
||||
}
|
75
gdb/p-lang.h
Normal file
75
gdb/p-lang.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* Pascal language support definitions for GDB, the GNU debugger.
|
||||
Copyright 2000 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This file is derived from c-lang.h */
|
||||
|
||||
#ifdef __STDC__ /* Forward decls for prototypes */
|
||||
struct value;
|
||||
#endif
|
||||
|
||||
extern int pascal_parse (void); /* Defined in p-exp.y */
|
||||
|
||||
extern void pascal_error (char *); /* Defined in p-exp.y */
|
||||
|
||||
/* Defined in p-typeprint.c */
|
||||
extern void pascal_print_type (struct type *, char *, struct ui_file *, int, int);
|
||||
|
||||
extern int pascal_val_print (struct type *, char *, int, CORE_ADDR, struct ui_file *, int, int,
|
||||
int, enum val_prettyprint);
|
||||
|
||||
extern int pascal_value_print (struct value *, struct ui_file *, int, enum val_prettyprint);
|
||||
|
||||
extern void pascal_type_print_method_args (char *, char *,
|
||||
struct ui_file *);
|
||||
|
||||
/* These are in p-lang.c: */
|
||||
|
||||
extern void pascal_printchar (int, struct ui_file *);
|
||||
|
||||
extern void pascal_printstr (struct ui_file *, char *, unsigned int, int, int);
|
||||
|
||||
extern struct type *pascal_create_fundamental_type (struct objfile *, int);
|
||||
|
||||
extern struct type **const (pascal_builtin_types[]);
|
||||
|
||||
/* These are in p-typeprint.c: */
|
||||
|
||||
extern void
|
||||
pascal_type_print_base (struct type *, struct ui_file *, int, int);
|
||||
|
||||
extern void
|
||||
pascal_type_print_varspec_prefix (struct type *, struct ui_file *, int, int);
|
||||
|
||||
/* These are in cp-valprint.c */
|
||||
|
||||
extern int vtblprint; /* Controls printing of vtbl's */
|
||||
|
||||
extern int static_field_print;
|
||||
|
||||
extern void pascal_object_print_class_member (char *, struct type *, struct ui_file *, char *);
|
||||
|
||||
extern void pascal_object_print_class_method (char *, struct type *, struct ui_file *);
|
||||
|
||||
extern void pascal_object_print_value_fields (struct type *, char *, CORE_ADDR,
|
||||
struct ui_file *, int, int, enum val_prettyprint,
|
||||
struct type **, int);
|
||||
|
||||
extern int pascal_object_is_vtbl_ptr_type (struct type *);
|
||||
|
||||
extern int pascal_object_is_vtbl_member (struct type *);
|
882
gdb/p-typeprint.c
Normal file
882
gdb/p-typeprint.c
Normal file
@ -0,0 +1,882 @@
|
||||
/* Support for printing Pascal types for GDB, the GNU debugger.
|
||||
Copyright 2000
|
||||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* This file is derived from p-typeprint.c */
|
||||
|
||||
#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 "p-lang.h"
|
||||
#include "typeprint.h"
|
||||
|
||||
#include "gdb_string.h"
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static void pascal_type_print_args (struct type *, struct ui_file *);
|
||||
|
||||
static void pascal_type_print_varspec_suffix (struct type *, struct ui_file *, int, int, int);
|
||||
|
||||
static void pascal_type_print_derivation_info (struct ui_file *, struct type *);
|
||||
|
||||
void pascal_type_print_varspec_prefix (struct type *, struct ui_file *, int, int);
|
||||
|
||||
|
||||
/* LEVEL is the depth to indent lines by. */
|
||||
|
||||
void
|
||||
pascal_print_type (type, varstring, stream, show, level)
|
||||
struct type *type;
|
||||
char *varstring;
|
||||
struct ui_file *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
register enum type_code code;
|
||||
int demangled_args;
|
||||
|
||||
code = TYPE_CODE (type);
|
||||
|
||||
if (show > 0)
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
if ((code == TYPE_CODE_FUNC ||
|
||||
code == TYPE_CODE_METHOD))
|
||||
{
|
||||
pascal_type_print_varspec_prefix (type, stream, show, 0);
|
||||
}
|
||||
/* first the name */
|
||||
fputs_filtered (varstring, stream);
|
||||
|
||||
if ((varstring != NULL && *varstring != '\0') &&
|
||||
!(code == TYPE_CODE_FUNC ||
|
||||
code == TYPE_CODE_METHOD))
|
||||
{
|
||||
fputs_filtered (" : ", stream);
|
||||
}
|
||||
|
||||
if (!(code == TYPE_CODE_FUNC ||
|
||||
code == TYPE_CODE_METHOD))
|
||||
{
|
||||
pascal_type_print_varspec_prefix (type, stream, show, 0);
|
||||
}
|
||||
|
||||
pascal_type_print_base (type, stream, show, level);
|
||||
/* For demangled function names, we have the arglist as part of the name,
|
||||
so don't print an additional pair of ()'s */
|
||||
|
||||
demangled_args = varstring ? strchr (varstring, '(') != NULL : 0;
|
||||
pascal_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
|
||||
|
||||
}
|
||||
|
||||
/* 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
|
||||
pascal_type_print_derivation_info (stream, type)
|
||||
struct ui_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 the Pascal method arguments ARGS to the file STREAM. */
|
||||
|
||||
void
|
||||
pascal_type_print_method_args (physname, methodname, stream)
|
||||
char *physname;
|
||||
char *methodname;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
int is_constructor = STREQN (physname, "__ct__", 6);
|
||||
int is_destructor = STREQN (physname, "__dt__", 6);
|
||||
|
||||
if (is_constructor || is_destructor)
|
||||
{
|
||||
physname += 6;
|
||||
}
|
||||
|
||||
fputs_filtered (methodname, stream);
|
||||
|
||||
if (physname && (*physname != 0))
|
||||
{
|
||||
int i = 0;
|
||||
int len = 0;
|
||||
char storec;
|
||||
char *argname;
|
||||
fputs_filtered (" (", stream);
|
||||
/* we must demangle this */
|
||||
while isdigit
|
||||
(physname[0])
|
||||
{
|
||||
while isdigit
|
||||
(physname[len])
|
||||
{
|
||||
len++;
|
||||
}
|
||||
i = strtol (physname, &argname, 0);
|
||||
physname += len;
|
||||
storec = physname[i];
|
||||
physname[i] = 0;
|
||||
fputs_filtered (physname, stream);
|
||||
physname[i] = storec;
|
||||
physname += i;
|
||||
if (physname[0] != 0)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
}
|
||||
}
|
||||
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
|
||||
pascal_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
|
||||
struct type *type;
|
||||
struct ui_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:
|
||||
fprintf_filtered (stream, "^");
|
||||
pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
break; /* pointer should be handled normally in pascal */
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
pascal_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
|
||||
pascal_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_filtered (stream, "(");
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, "function ");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "procedure ");
|
||||
}
|
||||
|
||||
if (passed_a_ptr)
|
||||
{
|
||||
fprintf_filtered (stream, " ");
|
||||
pascal_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
|
||||
fprintf_filtered (stream, "::");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_REF:
|
||||
pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
|
||||
fprintf_filtered (stream, "&");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, "function ");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "procedure ");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, "(");
|
||||
fprintf_filtered (stream, "array ");
|
||||
if (TYPE_LENGTH (type) >= 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0
|
||||
&& TYPE_ARRAY_UPPER_BOUND_TYPE (type) != BOUND_CANNOT_BE_DETERMINED)
|
||||
fprintf_filtered (stream, "[%d..%d] ",
|
||||
TYPE_ARRAY_LOWER_BOUND_VALUE (type),
|
||||
TYPE_ARRAY_UPPER_BOUND_VALUE (type)
|
||||
);
|
||||
fprintf_filtered (stream, "of ");
|
||||
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_STRING:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_COMPLEX:
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
case TYPE_CODE_TEMPLATE:
|
||||
/* These types need no prefix. They are listed here so that
|
||||
gcc -Wall will reveal any types that haven't been handled. */
|
||||
break;
|
||||
default:
|
||||
error ("type not handled in pascal_type_print_varspec_prefix()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pascal_type_print_args (type, stream)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
{
|
||||
int i;
|
||||
struct type **args;
|
||||
|
||||
/* fprintf_filtered (stream, "(");
|
||||
no () for procedures !! */
|
||||
args = TYPE_ARG_TYPES (type);
|
||||
if (args != NULL)
|
||||
{
|
||||
if ((args[1] != NULL && args[1]->code != TYPE_CODE_VOID) ||
|
||||
(args[2] != NULL))
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
}
|
||||
if (args[1] == NULL)
|
||||
{
|
||||
fprintf_filtered (stream, "...");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1;
|
||||
args[i] != NULL && args[i]->code != TYPE_CODE_VOID;
|
||||
i++)
|
||||
{
|
||||
pascal_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 (" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((args[1] != NULL && args[1]->code != TYPE_CODE_VOID) ||
|
||||
(args[2] != NULL))
|
||||
{
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pascal_print_func_args (struct type *type, struct ui_file *stream)
|
||||
{
|
||||
int i, len = TYPE_NFIELDS (type);
|
||||
if (len)
|
||||
{
|
||||
fprintf_filtered (stream, "(");
|
||||
}
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
fputs_filtered (", ", stream);
|
||||
wrap_here (" ");
|
||||
}
|
||||
/* can we find if it is a var parameter ??
|
||||
if ( TYPE_FIELD(type, i) == )
|
||||
{
|
||||
fprintf_filtered (stream, "var ");
|
||||
} */
|
||||
pascal_print_type (TYPE_FIELD_TYPE (type, i), "" /* TYPE_FIELD_NAME seems invalid ! */
|
||||
,stream, -1, 0);
|
||||
}
|
||||
if (len)
|
||||
{
|
||||
fprintf_filtered (stream, ")");
|
||||
}
|
||||
}
|
||||
|
||||
/* Print any array sizes, function arguments or close parentheses
|
||||
needed after the variable name (to describe its type).
|
||||
Args work like pascal_type_print_varspec_prefix. */
|
||||
|
||||
static void
|
||||
pascal_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
|
||||
struct type *type;
|
||||
struct ui_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, ")");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_MEMBER:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, ")");
|
||||
pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_METHOD:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, ")");
|
||||
pascal_type_print_method_args ("",
|
||||
"",
|
||||
stream);
|
||||
/* pascal_type_print_args (type, stream); */
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, " : ");
|
||||
pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0);
|
||||
pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_REF:
|
||||
pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
if (passed_a_ptr)
|
||||
fprintf_filtered (stream, ")");
|
||||
if (!demangled_args)
|
||||
pascal_print_func_args (type, stream);
|
||||
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, " : ");
|
||||
pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, 0);
|
||||
pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
|
||||
passed_a_ptr, 0);
|
||||
}
|
||||
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_STRING:
|
||||
case TYPE_CODE_BITSTRING:
|
||||
case TYPE_CODE_COMPLEX:
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
case TYPE_CODE_TEMPLATE:
|
||||
/* These types do not need a suffix. They are listed so that
|
||||
gcc -Wall will report types that may not have been considered. */
|
||||
break;
|
||||
default:
|
||||
error ("type not handled in pascal_type_print_varspec_suffix()");
|
||||
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 positive means print details about the type (e.g. enum values),
|
||||
and print structure elements passing SHOW - 1 for show.
|
||||
SHOW negative means just print the type name or struct tag if there is one.
|
||||
If there is no name, print something sensible but concise like
|
||||
"struct {...}".
|
||||
SHOW zero means just print the type name or struct tag if there is one.
|
||||
If there is no name, print something sensible but not as concise like
|
||||
"struct {int x; int y;}".
|
||||
|
||||
LEVEL is the number of spaces to indent by.
|
||||
We increase it for some recursive calls. */
|
||||
|
||||
void
|
||||
pascal_type_print_base (type, stream, show, level)
|
||||
struct type *type;
|
||||
struct ui_file *stream;
|
||||
int show;
|
||||
int level;
|
||||
{
|
||||
register int i;
|
||||
register int len;
|
||||
register int lastval;
|
||||
enum
|
||||
{
|
||||
s_none, s_public, s_private, s_protected
|
||||
}
|
||||
section_type;
|
||||
QUIT;
|
||||
|
||||
wrap_here (" ");
|
||||
if (type == NULL)
|
||||
{
|
||||
fputs_filtered ("<type unknown>", stream);
|
||||
return;
|
||||
}
|
||||
|
||||
/* void pointer */
|
||||
if ((TYPE_CODE (type) == TYPE_CODE_PTR) && (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID))
|
||||
{
|
||||
fprintf_filtered (stream,
|
||||
TYPE_NAME (type) ? TYPE_NAME (type) : "pointer");
|
||||
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;
|
||||
}
|
||||
|
||||
CHECK_TYPEDEF (type);
|
||||
|
||||
switch (TYPE_CODE (type))
|
||||
{
|
||||
case TYPE_CODE_TYPEDEF:
|
||||
case TYPE_CODE_PTR:
|
||||
case TYPE_CODE_MEMBER:
|
||||
case TYPE_CODE_REF:
|
||||
/* case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_METHOD: */
|
||||
pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ARRAY:
|
||||
/* pascal_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
|
||||
pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
pascal_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); */
|
||||
pascal_print_type (TYPE_TARGET_TYPE (type), NULL, stream, 0, 0);
|
||||
break;
|
||||
|
||||
case TYPE_CODE_FUNC:
|
||||
case TYPE_CODE_METHOD:
|
||||
/*
|
||||
pascal_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
|
||||
only after args !! */
|
||||
break;
|
||||
case TYPE_CODE_STRUCT:
|
||||
if (TYPE_TAG_NAME (type) != NULL)
|
||||
{
|
||||
fputs_filtered (TYPE_TAG_NAME (type), stream);
|
||||
fputs_filtered (" = ", stream);
|
||||
}
|
||||
if (HAVE_CPLUS_STRUCT (type))
|
||||
{
|
||||
fprintf_filtered (stream, "class ");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "record ");
|
||||
}
|
||||
goto struct_union;
|
||||
|
||||
case TYPE_CODE_UNION:
|
||||
if (TYPE_TAG_NAME (type) != NULL)
|
||||
{
|
||||
fputs_filtered (TYPE_TAG_NAME (type), stream);
|
||||
fputs_filtered (" = ", stream);
|
||||
}
|
||||
fprintf_filtered (stream, "case <?> of ");
|
||||
|
||||
struct_union:
|
||||
wrap_here (" ");
|
||||
if (show < 0)
|
||||
{
|
||||
/* If we just printed a tag name, no need to print anything else. */
|
||||
if (TYPE_TAG_NAME (type) == NULL)
|
||||
fprintf_filtered (stream, "{...}");
|
||||
}
|
||||
else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
|
||||
{
|
||||
pascal_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 (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
|
||||
&& is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
|
||||
continue;
|
||||
|
||||
/* If this is a pascal object or class we can print the
|
||||
various 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 ");
|
||||
}
|
||||
pascal_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");
|
||||
|
||||
/* Pbject pascal: 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);
|
||||
char *name = type_name_no_tag (type);
|
||||
/* this is GNU C++ specific
|
||||
how can we know constructor/destructor?
|
||||
It might work for GNU pascal */
|
||||
for (j = 0; j < len2; j++)
|
||||
{
|
||||
char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
|
||||
|
||||
int is_constructor = STREQN (physname, "__ct__", 6);
|
||||
int is_destructor = STREQN (physname, "__dt__", 6);
|
||||
|
||||
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_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_filtered (stream, "<undefined type> %s;\n",
|
||||
TYPE_FN_FIELD_PHYSNAME (f, j));
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_constructor)
|
||||
{
|
||||
fprintf_filtered (stream, "constructor ");
|
||||
}
|
||||
else if (is_destructor)
|
||||
{
|
||||
fprintf_filtered (stream, "destructor ");
|
||||
}
|
||||
else if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) != 0 &&
|
||||
TYPE_CODE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))) != TYPE_CODE_VOID)
|
||||
{
|
||||
fprintf_filtered (stream, "function ");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf_filtered (stream, "procedure ");
|
||||
}
|
||||
/* this does not work, no idea why !! */
|
||||
|
||||
pascal_type_print_method_args (physname,
|
||||
method_name,
|
||||
stream);
|
||||
|
||||
if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) != 0 &&
|
||||
TYPE_CODE (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j))) != TYPE_CODE_VOID)
|
||||
{
|
||||
fputs_filtered (" : ", stream);
|
||||
type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
|
||||
"", stream, -1);
|
||||
}
|
||||
if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
|
||||
fprintf_filtered (stream, "; virtual");
|
||||
|
||||
fprintf_filtered (stream, ";\n");
|
||||
}
|
||||
}
|
||||
fprintfi_filtered (level, stream, "end");
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ENUM:
|
||||
if (TYPE_TAG_NAME (type) != NULL)
|
||||
{
|
||||
fputs_filtered (TYPE_TAG_NAME (type), stream);
|
||||
if (show > 0)
|
||||
fputs_filtered (" ", stream);
|
||||
}
|
||||
/* enum is just defined by
|
||||
type enume_name = (enum_member1,enum_member2,...) */
|
||||
fprintf_filtered (stream, " = ");
|
||||
wrap_here (" ");
|
||||
if (show < 0)
|
||||
{
|
||||
/* If we just printed a tag name, no need to print anything else. */
|
||||
if (TYPE_TAG_NAME (type) == NULL)
|
||||
fprintf_filtered (stream, "(...)");
|
||||
}
|
||||
else if (show > 0 || TYPE_TAG_NAME (type) == NULL)
|
||||
{
|
||||
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, "record <unknown>");
|
||||
break;
|
||||
|
||||
case TYPE_CODE_ERROR:
|
||||
fprintf_filtered (stream, "<unknown type>");
|
||||
break;
|
||||
|
||||
/* this probably does not work for enums */
|
||||
case TYPE_CODE_RANGE:
|
||||
{
|
||||
struct type *target = TYPE_TARGET_TYPE (type);
|
||||
if (target == NULL)
|
||||
target = builtin_type_long;
|
||||
print_type_scalar (target, TYPE_LOW_BOUND (type), stream);
|
||||
fputs_filtered ("..", stream);
|
||||
print_type_scalar (target, TYPE_HIGH_BOUND (type), stream);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_CODE_SET:
|
||||
fputs_filtered ("set of ", stream);
|
||||
pascal_print_type (TYPE_INDEX_TYPE (type), "", stream,
|
||||
show - 1, level);
|
||||
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
|
||||
{
|
||||
/* At least for dump_symtab, it is important that this not be
|
||||
an error (). */
|
||||
fprintf_filtered (stream, "<invalid unnamed pascal type code %d>",
|
||||
TYPE_CODE (type));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
1145
gdb/p-valprint.c
Normal file
1145
gdb/p-valprint.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user