/* Print in infix form a struct expression.
- Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+ Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2003, 2007, 2008, 2009 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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "symtab.h"
#include "value.h"
#include "language.h"
#include "parser-defs.h"
+#include "user-regs.h" /* For user_reg_map_regnum_to_name. */
+#include "target.h"
+#include "gdb_string.h"
+#include "block.h"
+#include "objfiles.h"
+#include "gdb_assert.h"
+#include "valprint.h"
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
-/* Prototypes for local functions */
-
-static void
-print_subexp PARAMS ((struct expression *, int *, GDB_FILE *, enum precedence));
-
void
-print_expression (exp, stream)
- struct expression *exp;
- GDB_FILE *stream;
+print_expression (struct expression *exp, struct ui_file *stream)
{
int pc = 0;
print_subexp (exp, &pc, stream, PREC_NULL);
if the precedence of the main operator of this subexpression is less,
parentheses are needed here. */
-static void
-print_subexp (exp, pos, stream, prec)
- register struct expression *exp;
- register int *pos;
- GDB_FILE *stream;
- enum precedence prec;
+void
+print_subexp (struct expression *exp, int *pos,
+ struct ui_file *stream, enum precedence prec)
+{
+ exp->language_defn->la_exp_desc->print_subexp (exp, pos, stream, prec);
+}
+
+/* Standard implementation of print_subexp for use in language_defn
+ vectors. */
+void
+print_subexp_standard (struct expression *exp, int *pos,
+ struct ui_file *stream, enum precedence prec)
{
- register unsigned tem;
- register const struct op_print *op_print_tab;
- register int pc;
+ unsigned tem;
+ const struct op_print *op_print_tab;
+ int pc;
unsigned nargs;
- register char *op_str;
+ char *op_str;
int assign_modify = 0;
enum exp_opcode opcode;
enum precedence myprec = PREC_NULL;
/* Set to 1 for a right-associative operator. */
int assoc = 0;
- value_ptr val;
+ struct value *val;
char *tempstr = NULL;
op_print_tab = exp->language_defn->la_op_print_tab;
return;
case OP_LONG:
- (*pos) += 3;
- value_print (value_from_longest (exp->elts[pc + 1].type,
- exp->elts[pc + 2].longconst),
- stream, 0, Val_no_prettyprint);
+ {
+ struct value_print_options opts;
+ get_raw_print_options (&opts);
+ (*pos) += 3;
+ value_print (value_from_longest (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst),
+ stream, &opts);
+ }
return;
case OP_DOUBLE:
- (*pos) += 3;
- value_print (value_from_double (exp->elts[pc + 1].type,
- exp->elts[pc + 2].doubleconst),
- stream, 0, Val_no_prettyprint);
+ {
+ struct value_print_options opts;
+ get_raw_print_options (&opts);
+ (*pos) += 3;
+ value_print (value_from_double (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].doubleconst),
+ stream, &opts);
+ }
return;
case OP_VAR_VALUE:
b = exp->elts[pc + 1].block;
if (b != NULL
&& BLOCK_FUNCTION (b) != NULL
- && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)) != NULL)
+ && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)) != NULL)
{
- fputs_filtered (SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)), stream);
+ fputs_filtered (SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)), stream);
fputs_filtered ("::", stream);
}
- fputs_filtered (SYMBOL_SOURCE_NAME (exp->elts[pc + 2].symbol), stream);
+ fputs_filtered (SYMBOL_PRINT_NAME (exp->elts[pc + 2].symbol), stream);
}
return;
return;
case OP_REGISTER:
- (*pos) += 2;
- fprintf_filtered (stream, "$%s",
- REGISTER_NAME (longest_to_int (exp->elts[pc + 1].longconst)));
- return;
+ {
+ const char *name = &exp->elts[pc + 2].string;
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
+ fprintf_filtered (stream, "$%s", name);
+ return;
+ }
case OP_BOOL:
(*pos) += 2;
return;
case OP_NAME:
- case OP_EXPRSTRING:
nargs = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
fputs_filtered (&exp->elts[pc + 2].string, stream);
return;
case OP_STRING:
- nargs = longest_to_int (exp->elts[pc + 1].longconst);
- (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
- /* LA_PRINT_STRING will print using the current repeat count threshold.
- If necessary, we can temporarily set it to zero, or pass it as an
- additional parameter to LA_PRINT_STRING. -fnf */
- LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 1, 0);
+ {
+ struct value_print_options opts;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ /* LA_PRINT_STRING will print using the current repeat count threshold.
+ If necessary, we can temporarily set it to zero, or pass it as an
+ additional parameter to LA_PRINT_STRING. -fnf */
+ get_user_print_options (&opts);
+ LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 1, 0,
+ &opts);
+ }
return;
case OP_BITSTRING:
fprintf_unfiltered (stream, "B'<unimplemented>'");
return;
+ case OP_OBJC_NSSTRING: /* Objective-C Foundation Class NSString constant. */
+ {
+ struct value_print_options opts;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ fputs_filtered ("@\"", stream);
+ get_user_print_options (&opts);
+ LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 1, 0,
+ &opts);
+ fputs_filtered ("\"", stream);
+ }
+ return;
+
+ case OP_OBJC_MSGCALL:
+ { /* Objective C message (method) call. */
+ char *selector;
+ (*pos) += 3;
+ nargs = longest_to_int (exp->elts[pc + 2].longconst);
+ fprintf_unfiltered (stream, "[");
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ if (0 == target_read_string (exp->elts[pc + 1].longconst,
+ &selector, 1024, NULL))
+ {
+ error (_("bad selector"));
+ return;
+ }
+ if (nargs)
+ {
+ char *s, *nextS;
+ s = alloca (strlen (selector) + 1);
+ strcpy (s, selector);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ nextS = strchr (s, ':');
+ gdb_assert (nextS); /* Make sure we found ':'. */
+ *nextS = '\0';
+ fprintf_unfiltered (stream, " %s: ", s);
+ s = nextS + 1;
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ }
+ else
+ {
+ fprintf_unfiltered (stream, " %s", selector);
+ }
+ fprintf_unfiltered (stream, "]");
+ /* "selector" was malloc'd by target_read_string. Free it. */
+ xfree (selector);
+ return;
+ }
+
case OP_ARRAY:
(*pos) += 3;
nargs = longest_to_int (exp->elts[pc + 2].longconst);
nargs++;
tem = 0;
if (exp->elts[pc + 4].opcode == OP_LONG
- && exp->elts[pc + 5].type == builtin_type_char
+ && exp->elts[pc + 5].type
+ == builtin_type (exp->gdbarch)->builtin_char
&& exp->language_defn->la_language == language_c)
{
/* Attempt to print C character arrays using string syntax.
while (tem < nargs)
{
if (exp->elts[pc].opcode != OP_LONG
- || exp->elts[pc + 1].type != builtin_type_char)
+ || exp->elts[pc + 1].type
+ != builtin_type (exp->gdbarch)->builtin_char)
{
/* Not a simple array of char, use regular array printing. */
tem = 0;
}
if (tem > 0)
{
- LA_PRINT_STRING (stream, tempstr, nargs - 1, 1, 0);
+ struct value_print_options opts;
+ get_user_print_options (&opts);
+ LA_PRINT_STRING (stream, tempstr, nargs - 1, 1, 0,
+ &opts);
(*pos) = pc;
}
else
{
- int is_chill = exp->language_defn->la_language == language_chill;
- fputs_filtered (is_chill ? " [" : " {", stream);
+ fputs_filtered (" {", stream);
for (tem = 0; tem < nargs; tem++)
{
if (tem != 0)
}
print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
}
- fputs_filtered (is_chill ? "]" : "}", stream);
+ fputs_filtered ("}", stream);
}
return;
case OP_LABELED:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
-
- if (exp->language_defn->la_language == language_chill)
- {
- fputs_filtered (".", stream);
- fputs_filtered (&exp->elts[pc + 2].string, stream);
- fputs_filtered (exp->elts[*pos].opcode == OP_LABELED ? ", "
- : ": ",
- stream);
- }
- else
- {
- /* Gcc support both these syntaxes. Unsure which is preferred. */
+ /* Gcc support both these syntaxes. Unsure which is preferred. */
#if 1
- fputs_filtered (&exp->elts[pc + 2].string, stream);
- fputs_filtered (": ", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered (": ", stream);
#else
- fputs_filtered (".", stream);
- fputs_filtered (&exp->elts[pc + 2].string, stream);
- fputs_filtered ("=", stream);
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered ("=", stream);
#endif
- }
print_subexp (exp, pos, stream, PREC_SUFFIX);
return;
fputs_filtered (&exp->elts[pc + 2].string, stream);
return;
+ case STRUCTOP_MEMBER:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (".*", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
+ case STRUCTOP_MPTR:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("->*", stream);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
case BINOP_SUBSCRIPT:
print_subexp (exp, pos, stream, PREC_SUFFIX);
fputs_filtered ("[", stream);
(*pos) += 2;
if ((int) prec > (int) PREC_PREFIX)
fputs_filtered ("(", stream);
- if (exp->elts[pc + 1].type->code == TYPE_CODE_FUNC &&
+ if (TYPE_CODE (exp->elts[pc + 1].type) == TYPE_CODE_FUNC &&
exp->elts[pc + 3].opcode == OP_LONG)
{
+ struct value_print_options opts;
+
/* We have a minimal symbol fn, probably. It's encoded
as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
Swallow the OP_LONG (including both its opcodes); ignore
its type; print the value in the type of the MEMVAL. */
(*pos) += 4;
val = value_at_lazy (exp->elts[pc + 1].type,
- (CORE_ADDR) exp->elts[pc + 5].longconst,
- NULL);
- value_print (val, stream, 0, Val_no_prettyprint);
+ (CORE_ADDR) exp->elts[pc + 5].longconst);
+ get_raw_print_options (&opts);
+ value_print (val, stream, &opts);
}
else
{
fputs_filtered (")", stream);
return;
+ case UNOP_MEMVAL_TLS:
+ (*pos) += 3;
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered ("(", stream);
+ fputs_filtered ("{", stream);
+ type_print (exp->elts[pc + 2].type, "", stream, 0);
+ fputs_filtered ("} ", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered (")", stream);
+ return;
+
case BINOP_ASSIGN_MODIFY:
opcode = exp->elts[pc + 1].opcode;
(*pos) += 2;
if (op_print_tab[tem].opcode != opcode)
/* Not found; don't try to keep going because we don't know how
to interpret further elements. */
- error ("Invalid expression");
+ error (_("Invalid expression"));
break;
/* C++ ops */
fputs_filtered ("this", stream);
return;
+ /* Objective-C ops */
+
+ case OP_OBJC_SELF:
+ ++(*pos);
+ fputs_filtered ("self", stream); /* The ObjC equivalent of "this". */
+ return;
+
/* Modula-2 ops */
case MULTI_SUBSCRIPT:
case BINOP_INCL:
case BINOP_EXCL:
- error ("print_subexp: Not implemented.");
+ error (_("print_subexp: Not implemented."));
/* Default ops */
/* Not found; don't try to keep going because we don't know how
to interpret further elements. For example, this happens
if opcode is OP_TYPE. */
- error ("Invalid expression");
+ error (_("Invalid expression"));
}
/* Note that PREC_BUILTIN will always emit parentheses. */
a string. NULL indicates that the opcode was not found in the
current language table. */
char *
-op_string (op)
- enum exp_opcode op;
+op_string (enum exp_opcode op)
{
int tem;
- register const struct op_print *op_print_tab;
+ const struct op_print *op_print_tab;
op_print_tab = current_language->la_op_print_tab;
for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
/* Support for dumping the raw data from expressions in a human readable
form. */
-static char *op_name PARAMS ((int opcode));
+static char *op_name (struct expression *, enum exp_opcode);
+static int dump_subexp_body (struct expression *exp, struct ui_file *, int);
+
+/* Name for OPCODE, when it appears in expression EXP. */
static char *
-op_name (opcode)
- int opcode;
+op_name (struct expression *exp, enum exp_opcode opcode)
+{
+ return exp->language_defn->la_exp_desc->op_name (opcode);
+}
+
+/* Default name for the standard operator OPCODE (i.e., one defined in
+ the definition of enum exp_opcode). */
+
+char *
+op_name_standard (enum exp_opcode opcode)
{
switch (opcode)
{
return "BINOP_MIN";
case BINOP_MAX:
return "BINOP_MAX";
- case BINOP_SCOPE:
- return "BINOP_SCOPE";
case STRUCTOP_MEMBER:
return "STRUCTOP_MEMBER";
case STRUCTOP_MPTR:
return "UNOP_CAST";
case UNOP_MEMVAL:
return "UNOP_MEMVAL";
+ case UNOP_MEMVAL_TLS:
+ return "UNOP_MEMVAL_TLS";
case UNOP_NEG:
return "UNOP_NEG";
case UNOP_LOGICAL_NOT:
return "STRUCTOP_PTR";
case OP_THIS:
return "OP_THIS";
+ case OP_OBJC_SELF:
+ return "OP_OBJC_SELF";
case OP_SCOPE:
return "OP_SCOPE";
case OP_TYPE:
}
void
-dump_prefix_expression (exp, stream, note)
- struct expression *exp;
- GDB_FILE *stream;
- char *note;
+dump_raw_expression (struct expression *exp, struct ui_file *stream,
+ char *note)
{
int elt;
char *opcode_name;
fprintf_filtered (stream, "Dump of expression @ ");
gdb_print_host_address (exp, stream);
- fprintf_filtered (stream, ", %s:\nExpression: `", note);
- if (exp->elts[0].opcode != OP_TYPE)
- print_expression (exp, stream);
- else
- fprintf_filtered (stream, "Type printing not yet supported....");
- fprintf_filtered (stream, "'\n\tLanguage %s, %d elements, %d bytes each.\n",
+ fprintf_filtered (stream, "'\n\tLanguage %s, %d elements, %ld bytes each.\n",
exp->language_defn->la_name, exp->nelts,
- sizeof (union exp_element));
+ (long) sizeof (union exp_element));
fprintf_filtered (stream, "\t%5s %20s %16s %s\n", "Index", "Opcode",
"Hex Value", "String Value");
for (elt = 0; elt < exp->nelts; elt++)
{
fprintf_filtered (stream, "\t%5d ", elt);
- opcode_name = op_name (exp->elts[elt].opcode);
+ opcode_name = op_name (exp, exp->elts[elt].opcode);
fprintf_filtered (stream, "%20s ", opcode_name);
print_longest (stream, 'd', 0, exp->elts[elt].longconst);
}
}
-static int dump_subexp PARAMS ((struct expression * exp, GDB_FILE * stream, int elt));
+/* Dump the subexpression of prefix expression EXP whose operator is at
+ position ELT onto STREAM. Returns the position of the next
+ subexpression in EXP. */
-static int
-dump_subexp (exp, stream, elt)
- struct expression *exp;
- GDB_FILE *stream;
- int elt;
+int
+dump_subexp (struct expression *exp, struct ui_file *stream, int elt)
{
static int indent = 0;
int i;
fprintf_filtered (stream, " ");
indent += 2;
- fprintf_filtered (stream, "%-20s ", op_name (exp->elts[elt].opcode));
+ fprintf_filtered (stream, "%-20s ", op_name (exp, exp->elts[elt].opcode));
+
+ elt = dump_subexp_body (exp, stream, elt);
+
+ indent -= 2;
+
+ return elt;
+}
+
+/* Dump the operands of prefix expression EXP whose opcode is at
+ position ELT onto STREAM. Returns the position of the next
+ subexpression in EXP. */
+
+static int
+dump_subexp_body (struct expression *exp, struct ui_file *stream, int elt)
+{
+ return exp->language_defn->la_exp_desc->dump_subexp_body (exp, stream, elt);
+}
+
+/* Default value for subexp_body in exp_descriptor vector. */
- switch (exp->elts[elt++].opcode)
+int
+dump_subexp_body_standard (struct expression *exp,
+ struct ui_file *stream, int elt)
+{
+ int opcode = exp->elts[elt++].opcode;
+
+ switch (opcode)
{
case TERNOP_COND:
case TERNOP_SLICE:
case BINOP_EXP:
case BINOP_MIN:
case BINOP_MAX:
- case BINOP_SCOPE:
case BINOP_INTDIV:
case BINOP_ASSIGN_MODIFY:
case BINOP_VAL:
case BINOP_IN:
case BINOP_RANGE:
case BINOP_END:
+ case STRUCTOP_MEMBER:
+ case STRUCTOP_MPTR:
elt = dump_subexp (exp, stream, elt);
case UNOP_NEG:
case UNOP_LOGICAL_NOT:
fprintf_filtered (stream, ", symbol @");
gdb_print_host_address (exp->elts[elt + 1].symbol, stream);
fprintf_filtered (stream, " (%s)",
- SYMBOL_NAME (exp->elts[elt + 1].symbol));
+ SYMBOL_PRINT_NAME (exp->elts[elt + 1].symbol));
elt += 3;
break;
case OP_LAST:
elt += 2;
break;
case OP_REGISTER:
- fprintf_filtered (stream, "Register %ld",
- (long) exp->elts[elt].longconst);
- elt += 2;
+ fprintf_filtered (stream, "Register $%s", &exp->elts[elt + 1].string);
+ elt += 3 + BYTES_TO_EXP_ELEM (exp->elts[elt].longconst + 1);
break;
case OP_INTERNALVAR:
fprintf_filtered (stream, "Internal var @");
break;
case OP_FUNCALL:
{
- int nargs;
+ int i, nargs;
nargs = longest_to_int (exp->elts[elt].longconst);
fprintf_filtered (stream, ")");
elt = dump_subexp (exp, stream, elt + 2);
break;
+ case UNOP_MEMVAL_TLS:
+ fprintf_filtered (stream, "TLS type @");
+ gdb_print_host_address (exp->elts[elt + 1].type, stream);
+ fprintf_filtered (stream, " (__thread /* \"%s\" */ ",
+ (exp->elts[elt].objfile == NULL ? "(null)"
+ : exp->elts[elt].objfile->name));
+ type_print (exp->elts[elt + 1].type, NULL, stream, 0);
+ fprintf_filtered (stream, ")");
+ elt = dump_subexp (exp, stream, elt + 3);
+ break;
case OP_TYPE:
fprintf_filtered (stream, "Type @");
gdb_print_host_address (exp->elts[elt].type, stream);
break;
default:
case OP_NULL:
- case STRUCTOP_MEMBER:
- case STRUCTOP_MPTR:
case MULTI_SUBSCRIPT:
case OP_F77_UNDETERMINED_ARGLIST:
case OP_COMPLEX:
case OP_THIS:
case OP_LABELED:
case OP_NAME:
- case OP_EXPRSTRING:
fprintf_filtered (stream, "Unknown format");
}
- indent -= 2;
-
return elt;
}
void
-dump_postfix_expression (exp, stream, note)
- struct expression *exp;
- GDB_FILE *stream;
- char *note;
+dump_prefix_expression (struct expression *exp, struct ui_file *stream)
{
int elt;
fprintf_filtered (stream, "Dump of expression @ ");
gdb_print_host_address (exp, stream);
- fprintf_filtered (stream, ", %s:\nExpression: `", note);
+ fputs_filtered (", after conversion to prefix form:\nExpression: `", stream);
if (exp->elts[0].opcode != OP_TYPE)
print_expression (exp, stream);
else
fputs_filtered ("Type printing not yet supported....", stream);
- fprintf_filtered (stream, "'\n\tLanguage %s, %d elements, %d bytes each.\n",
+ fprintf_filtered (stream, "'\n\tLanguage %s, %d elements, %ld bytes each.\n",
exp->language_defn->la_name, exp->nelts,
- sizeof (union exp_element));
+ (long) sizeof (union exp_element));
fputs_filtered ("\n", stream);
for (elt = 0; elt < exp->nelts;)