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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Parse an expression from text in a string,
and return the result as a struct expression pointer.
come first in the result. */
#include "defs.h"
+#include "gdb_string.h"
#include "symtab.h"
#include "gdbtypes.h"
#include "frame.h"
#include "command.h"
#include "language.h"
#include "parser-defs.h"
-
+\f
+/* Global variables declared in parser-defs.h (and commented there). */
+struct expression *expout;
+int expout_size;
+int expout_ptr;
+struct block *expression_context_block;
+struct block *innermost_block;
+int arglist_len;
+union type_stack_elt *type_stack;
+int type_stack_depth, type_stack_size;
+char *lexptr;
+char *namecopy;
+int paren_depth;
+int comma_terminates;
+\f
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 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;
+ }
+
+ /* Try target specific aliases */
+#ifdef REGISTER_NAME_ALIAS_HOOK
+ return REGISTER_NAME_ALIAS_HOOK (str, len);
+#endif
+
+ 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;
write_exp_elt_longcst ((LONGEST) bits);
}
-/* Type that corresponds to the address given in a minimal symbol. */
-
-static struct type *msymbol_addr_type;
-
/* Add the appropriate elements for a minimal symbol to the end of
- the expression. */
+ the expression. The rationale behind passing in text_symbol_type and
+ data_symbol_type was so that Modula-2 could pass in WORD for
+ data_symbol_type. Perhaps it still is useful to have those types vary
+ based on the language, but they no longer have names like "int", so
+ the initial rationale is gone. */
+
+static struct type *msym_text_symbol_type;
+static struct type *msym_data_symbol_type;
+static struct type *msym_unknown_symbol_type;
void
write_exp_msymbol (msymbol, text_symbol_type, data_symbol_type)
struct type *data_symbol_type;
{
write_exp_elt_opcode (OP_LONG);
- write_exp_elt_type (msymbol_addr_type);
+ write_exp_elt_type (lookup_pointer_type (builtin_type_void));
write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
write_exp_elt_opcode (OP_LONG);
{
case mst_text:
case mst_file_text:
- write_exp_elt_type (text_symbol_type);
+ case mst_solib_trampoline:
+ write_exp_elt_type (msym_text_symbol_type);
break;
case mst_data:
case mst_file_data:
case mst_bss:
case mst_file_bss:
- write_exp_elt_type (data_symbol_type);
+ write_exp_elt_type (msym_data_symbol_type);
break;
default:
- write_exp_elt_type (builtin_type_char);
+ write_exp_elt_type (msym_unknown_symbol_type);
break;
}
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;
oplen = 3;
break;
+ case OP_COMPLEX:
+ oplen = 1;
+ args = 2;
+ break;
+
case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
oplen = 3;
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
break;
args = 1;
break;
+ case OP_LABELED:
case STRUCTOP_STRUCT:
case STRUCTOP_PTR:
args = 1;
/* 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);
break;
break;
case TERNOP_COND:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
args = 3;
break;
/* Modula-2 */
case MULTI_SUBSCRIPT:
- oplen=3;
+ oplen = 3;
args = 1 + longest_to_int (expr->elts[endpos- 2].longconst);
break;
oplen = 3;
break;
+ case OP_COMPLEX:
+ oplen = 1;
+ args = 2;
+ break;
+
case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
oplen = 3;
args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
break;
case STRUCTOP_STRUCT:
case STRUCTOP_PTR:
+ case OP_LABELED:
args = 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);
break;
break;
case TERNOP_COND:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
args = 3;
break;
/* Modula-2 */
case MULTI_SUBSCRIPT:
- oplen=3;
+ oplen = 3;
args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
break;
break;
case tp_array:
array_size = pop_type_int ();
- if (array_size != -1)
- {
- range_type =
- create_range_type ((struct type *) NULL,
- builtin_type_int, 0,
- array_size - 1);
- follow_type =
- create_array_type ((struct type *) NULL,
- follow_type, range_type);
- }
- else
- follow_type = lookup_pointer_type (follow_type);
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0,
+ array_size >= 0 ? array_size - 1 : 0);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ if (array_size < 0)
+ TYPE_ARRAY_UPPER_BOUND_TYPE(follow_type)
+ = BOUND_CANNOT_BE_DETERMINED;
break;
case tp_function:
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
follow_type = lookup_function_type (follow_type);
break;
}
type_stack = (union type_stack_elt *)
xmalloc (type_stack_size * sizeof (*type_stack));
- /* We don't worry too much about what the name of this type is
- because the name should rarely appear in output to the user. */
-
- msymbol_addr_type =
- init_type (TYPE_CODE_PTR, TARGET_PTR_BIT / HOST_CHAR_BIT, 0,
- "void *", NULL);
+ msym_text_symbol_type =
+ init_type (TYPE_CODE_FUNC, 1, 0, "<text variable, no debug info>", NULL);
+ TYPE_TARGET_TYPE (msym_text_symbol_type) = builtin_type_int;
+ msym_data_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<data variable, no debug info>", NULL);
+ msym_unknown_symbol_type =
+ init_type (TYPE_CODE_INT, 1, 0,
+ "<variable (not text or data), no debug info>",
+ NULL);
}