#include "command.h"
#include "language.h"
#include "parser-defs.h"
+#include "gdbcmd.h"
+#include "symfile.h" /* for overlay functions */
\f
/* Global variables declared in parser-defs.h (and commented there). */
struct expression *expout;
int paren_depth;
int comma_terminates;
\f
+#ifdef MAINTENANCE_CMDS
+static int expressiondebug = 0;
+#endif
+
static void
free_funcalls PARAMS ((void));
static void
prefixify_expression PARAMS ((struct expression *));
-static int
-length_of_subexp PARAMS ((struct expression *, int));
-
static void
prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int));
#endif
+/* The generic method for targets to specify how their registers are named.
+ The mapping can be derived from three sources: reg_names; std_regs; or
+ a target specific alias hook. */
+
+int
+target_map_name_to_register (str, len)
+ char *str;
+ int len;
+{
+ int i;
+
+ /* First try target specific aliases. We try these first because on some
+ systems standard names can be context dependent (eg. $pc on a
+ multiprocessor can be could be any of several PCs). */
+#ifdef REGISTER_NAME_ALIAS_HOOK
+ i = REGISTER_NAME_ALIAS_HOOK (str, len);
+ if (i >= 0)
+ return i;
+#endif
+
+ /* Search architectural register name space. */
+ for (i = 0; i < NUM_REGS; i++)
+ if (reg_names[i] && len == strlen (reg_names[i])
+ && STREQN (str, reg_names[i], len))
+ {
+ return i;
+ }
+
+ /* Try standard aliases */
+ for (i = 0; i < num_std_regs; i++)
+ if (std_regs[i].name && len == strlen (std_regs[i].name)
+ && STREQN (str, std_regs[i].name, len))
+ {
+ return std_regs[i].regnum;
+ }
+
+ return -1;
+}
/* Begin counting arguments for a function call,
saving the data about any containing call. */
void
write_exp_elt_dblcst (expelt)
- double expelt;
+ DOUBLEST expelt;
{
union exp_element tmp;
struct type *text_symbol_type;
struct type *data_symbol_type;
{
+ CORE_ADDR addr;
+
write_exp_elt_opcode (OP_LONG);
write_exp_elt_type (lookup_pointer_type (builtin_type_void));
- write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
+
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (overlay_debugging)
+ addr = symbol_overlayed_address (addr, SYMBOL_BFD_SECTION (msymbol));
+ write_exp_elt_longcst ((LONGEST) addr);
+
write_exp_elt_opcode (OP_LONG);
write_exp_elt_opcode (UNOP_MEMVAL);
write_exp_elt_opcode (UNOP_MEMVAL);
}
\f
+/* Recognize tokens that start with '$'. These include:
+
+ $regname A native register name or a "standard
+ register name".
+
+ $variable A convenience variable with a name chosen
+ by the user.
+
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
+
+ $$digits Value history with index <digits> relative
+ to the last value. I.E. $$0 is the last
+ value, $$1 is the one previous to that, $$2
+ is the one previous to $$1, etc.
+
+ $ | $0 | $$0 The last value in the value history.
+
+ $$ An abbreviation for the second to the last
+ value in the value history, I.E. $$1
+
+ */
+
+void
+write_dollar_variable (str)
+ struct stoken str;
+{
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that). */
+
+ int negate = 0;
+ int i = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (str.length >= 2 && str.ptr[1] == '$')
+ {
+ negate = 1;
+ i = 2;
+ }
+ if (i == str.length)
+ {
+ /* Just dollars (one or two) */
+ i = - negate;
+ goto handle_last;
+ }
+ /* Is the rest of the token digits? */
+ for (; i < str.length; i++)
+ if (!(str.ptr[i] >= '0' && str.ptr[i] <= '9'))
+ break;
+ if (i == str.length)
+ {
+ i = atoi (str.ptr + 1 + negate);
+ if (negate)
+ i = - i;
+ goto handle_last;
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+ i = target_map_name_to_register( str.ptr + 1, str.length - 1 );
+ if( i >= 0 )
+ goto handle_register;
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern (lookup_internalvar (copy_name (str) + 1));
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ return;
+ handle_last:
+ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) i);
+ write_exp_elt_opcode (OP_LAST);
+ return;
+ handle_register:
+ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst (i);
+ write_exp_elt_opcode (OP_REGISTER);
+ return;
+}
+\f
/* Return a null-terminated temporary copy of the name
of a string token. */
/* Return the number of exp_elements in the subexpression of EXPR
whose last exp_element is at index ENDPOS - 1 in EXPR. */
-static int
+int
length_of_subexp (expr, endpos)
register struct expression *expr;
register int endpos;
/* fall through */
case OP_M2_STRING:
case OP_STRING:
+ case OP_NAME:
case OP_EXPRSTRING:
oplen = longest_to_int (expr->elts[endpos - 2].longconst);
oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
/* fall through */
case OP_M2_STRING:
case OP_STRING:
+ case OP_NAME:
case OP_EXPRSTRING:
oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
/* Convert expression from postfix form as generated by yacc
parser, to a prefix form. */
- DUMP_EXPRESSION (expout, gdb_stdout, "before conversion to prefix form");
+#ifdef MAINTENANCE_CMDS
+ if (expressiondebug)
+ dump_prefix_expression (expout, gdb_stdout,
+ "before conversion to prefix form");
+#endif /* MAINTENANCE_CMDS */
+
prefixify_expression (expout);
- DUMP_EXPRESSION (expout, gdb_stdout, "after conversion to prefix form");
+
+#ifdef MAINTENANCE_CMDS
+ if (expressiondebug)
+ dump_postfix_expression (expout, gdb_stdout,
+ "after conversion to prefix form");
+#endif /* MAINTENANCE_CMDS */
*stringptr = lexptr;
return expout;
init_type (TYPE_CODE_INT, 1, 0,
"<variable (not text or data), no debug info>",
NULL);
+
+#ifdef MAINTENANCE_CMDS
+ add_show_from_set (
+ add_set_cmd ("expressiondebug", class_maintenance, var_zinteger,
+ (char *)&expressiondebug,
+ "Set expression debugging.\n\
+When non-zero, the internal representation of expressions will be printed.",
+ &setlist),
+ &showlist);
+#endif
}