#include "defs.h"
#include "gdb_obstack.h"
#include "bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "expression.h"
#include "value.h"
#include "gdbcore.h"
#include "command.h"
#include "gdbcmd.h"
#include "target.h"
#include "language.h"
#include "cp-abi.h"
#include "typeprint.h"
#include "gdb_string.h"
#include <errno.h>
#include "exceptions.h"
extern int objectprint;
extern void _initialize_typeprint (void);
static void ptype_command (char *, int);
static struct type *ptype_eval (struct expression *);
static void whatis_command (char *, int);
static void whatis_exp (char *, int);
void
typedef_print (struct type *type, struct symbol *new, struct ui_file *stream)
{
CHECK_TYPEDEF (type);
switch (current_language->la_language)
{
#ifdef _LANG_c
case language_c:
case language_cplus:
case language_objc:
case language_objcplus:
fprintf_filtered (stream, "typedef ");
type_print (type, "", stream, 0);
if (TYPE_NAME ((SYMBOL_TYPE (new))) == 0
|| strcmp (TYPE_NAME ((SYMBOL_TYPE (new))), DEPRECATED_SYMBOL_NAME (new)) != 0)
fprintf_filtered (stream, " %s", SYMBOL_PRINT_NAME (new));
break;
#endif
#ifdef _LANG_m2
case language_m2:
fprintf_filtered (stream, "TYPE ");
if (!TYPE_NAME (SYMBOL_TYPE (new))
|| strcmp (TYPE_NAME ((SYMBOL_TYPE (new))), DEPRECATED_SYMBOL_NAME (new)) != 0)
fprintf_filtered (stream, "%s = ", SYMBOL_PRINT_NAME (new));
else
fprintf_filtered (stream, "<builtin> = ");
type_print (type, "", stream, 0);
break;
#endif
#ifdef _LANG_pascal
case language_pascal:
fprintf_filtered (stream, "type ");
fprintf_filtered (stream, "%s = ", SYMBOL_PRINT_NAME (new));
type_print (type, "", stream, 0);
break;
#endif
default:
error (_("Language not supported."));
}
fprintf_filtered (stream, ";\n");
}
void
type_print (struct type *type, char *varstring, struct ui_file *stream,
int show)
{
LA_PRINT_TYPE (type, varstring, stream, show, 0);
}
char *
type_sprint (struct type *type, char *varstring, int show)
{
struct ui_file *stb;
struct cleanup *wipe;
long length;
char *type_name;
stb = mem_fileopen ();
wipe = make_cleanup_ui_file_delete (stb);
type_print (type, varstring, stb, show);
type_name = ui_file_xstrdup (stb, &length);
do_cleanups (wipe);
return type_name;
}
static int single_quote_typename = 1;
int
set_single_quote_typename (int new_value)
{
int old_value = single_quote_typename;
single_quote_typename = new_value;
return old_value;
}
int
get_single_quote_typename ()
{
return single_quote_typename;
}
char *
type_sprint_quoted (struct type *type, char *varstring, int show)
{
char *ret_val;
struct gdb_exception e;
int old_value = set_single_quote_typename (1);
TRY_CATCH (e, RETURN_MASK_ERROR)
{
ret_val = type_sprint (type, varstring, show);
}
set_single_quote_typename (old_value);
if (e.reason != NO_ERROR)
throw_exception (e);
return ret_val;
}
static void
whatis_exp (char *exp, int show)
{
struct expression *expr;
struct value *val;
struct cleanup *old_chain = NULL;
struct type *real_type = NULL;
struct type *type;
int full = 0;
int top = -1;
int using_enc = 0;
if (exp)
{
innermost_block = NULL;
expr = parse_expression (exp);
old_chain = make_cleanup (free_current_contents, &expr);
val = evaluate_type (expr);
}
else
val = access_value_history (0);
type = value_type (val);
if (objectprint)
{
if (((TYPE_CODE (type) == TYPE_CODE_PTR) ||
(TYPE_CODE (type) == TYPE_CODE_REF))
&&
(TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
{
real_type = value_rtti_target_type (val, &full, &top, &using_enc);
if (real_type)
{
if (TYPE_CODE (type) == TYPE_CODE_PTR)
real_type = lookup_pointer_type (real_type);
else
real_type = lookup_reference_type (real_type);
}
}
else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
real_type = value_rtti_type (val, &full, &top, &using_enc);
}
if (!real_type)
{
real_type = get_closure_dynamic_type (val);
if (real_type)
full = 1;
}
printf_filtered ("type = ");
if (real_type)
{
printf_filtered ("/* real type = ");
type_print (real_type, "", gdb_stdout, -1);
if (! full)
printf_filtered (" (incomplete object)");
printf_filtered (" */\n");
}
type_print (type, "", gdb_stdout, show);
printf_filtered ("\n");
if (exp)
do_cleanups (old_chain);
}
static void
whatis_command (char *exp, int from_tty)
{
whatis_exp (exp, -1);
}
static struct type *
ptype_eval (struct expression *exp)
{
if (exp->elts[0].opcode == OP_TYPE)
{
return (exp->elts[1].type);
}
else
{
return (NULL);
}
}
static void
ptype_command (char *typename, int from_tty)
{
struct type *type;
struct expression *expr;
struct cleanup *old_chain;
if (typename == NULL)
{
whatis_exp (typename, 1);
}
else
{
innermost_block = NULL;
expr = parse_expression (typename);
old_chain = make_cleanup (free_current_contents, &expr);
type = ptype_eval (expr);
if (type != NULL)
{
printf_filtered ("type = ");
type_print (type, "", gdb_stdout, 1);
printf_filtered ("\n");
do_cleanups (old_chain);
}
else
{
do_cleanups (old_chain);
whatis_exp (typename, 1);
}
}
}
void
print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream)
{
unsigned int i;
unsigned len;
CHECK_TYPEDEF (type);
switch (TYPE_CODE (type))
{
case TYPE_CODE_ENUM:
len = TYPE_NFIELDS (type);
for (i = 0; i < len; i++)
{
if (TYPE_FIELD_BITPOS (type, i) == val)
{
break;
}
}
if (i < len)
{
fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
}
else
{
print_longest (stream, 'd', 0, val);
}
break;
case TYPE_CODE_INT:
print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
break;
case TYPE_CODE_CHAR:
LA_PRINT_CHAR ((unsigned char) val, stream);
break;
case TYPE_CODE_BOOL:
fprintf_filtered (stream, val ? "TRUE" : "FALSE");
break;
case TYPE_CODE_RANGE:
print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
return;
case TYPE_CODE_UNDEF:
case TYPE_CODE_PTR:
case TYPE_CODE_ARRAY:
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_FUNC:
case TYPE_CODE_FLT:
case TYPE_CODE_VOID:
case TYPE_CODE_SET:
case TYPE_CODE_STRING:
case TYPE_CODE_ERROR:
case TYPE_CODE_MEMBER:
case TYPE_CODE_METHOD:
case TYPE_CODE_REF:
case TYPE_CODE_NAMESPACE:
error (_("internal error: unhandled type in print_type_scalar"));
break;
default:
error (_("Invalid type code in symbol table."));
}
gdb_flush (stream);
}
void
maintenance_print_type (char *typename, int from_tty)
{
struct value *val;
struct type *type;
struct cleanup *old_chain;
struct expression *expr;
if (typename != NULL)
{
innermost_block = NULL;
expr = parse_expression (typename);
old_chain = make_cleanup (free_current_contents, &expr);
if (expr->elts[0].opcode == OP_TYPE)
{
type = expr->elts[1].type;
}
else
{
val = evaluate_type (expr);
type = value_type (val);
}
if (type != NULL)
{
recursive_dump_type (type, 0);
}
do_cleanups (old_chain);
}
}
void
_initialize_typeprint (void)
{
add_com ("ptype", class_vars, ptype_command, _("\
Print definition of type TYPE.\n\
Argument may be a type name defined by typedef, or \"struct STRUCT-TAG\"\n\
or \"class CLASS-NAME\" or \"union UNION-TAG\" or \"enum ENUM-TAG\".\n\
The selected stack frame's lexical context is used to look up the name."));
add_com ("whatis", class_vars, whatis_command,
_("Print data type of expression EXP."));
}