/* Evaluate expressions for GDB.
- Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GDB.
-GDB is free software; you can redistribute it and/or modify
+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 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
-GDB is distributed in the hope that it will be useful,
+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 GDB; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
-#include "param.h"
#include "symtab.h"
+#include "gdbtypes.h"
#include "value.h"
#include "expression.h"
#include "target.h"
+#include "frame.h"
-#define NULL_TYPE ((struct type *)0)
+/* Values of NOSIDE argument to eval_subexp. */
+enum noside
+{ EVAL_NORMAL,
+ EVAL_SKIP, /* Only effect is to increment pos. */
+ EVAL_AVOID_SIDE_EFFECTS /* Don't modify any variables or
+ call any functions. The value
+ returned will have the correct
+ type, and will have an
+ approximately correct lvalue
+ type (inaccuracy: anything that is
+ listed as being in a register in
+ the function in which it was
+ declared will be lval_register). */
+};
+
+/* Prototypes for local functions. */
+
+static value
+evaluate_subexp_for_sizeof PARAMS ((struct expression *, int *));
+
+static value
+evaluate_subexp_with_coercion PARAMS ((struct expression *, int *,
+ enum noside));
+
+static value
+evaluate_subexp_for_address PARAMS ((struct expression *, int *,
+ enum noside));
+
+static value
+evaluate_subexp PARAMS ((struct type *, struct expression *, int *,
+ enum noside));
\f
/* Parse the string EXP as a C expression, evaluate it,
parse_and_eval_address (exp)
char *exp;
{
- struct expression *expr = parse_c_expression (exp);
+ struct expression *expr = parse_expression (exp);
register CORE_ADDR addr;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
- addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
+ addr = value_as_pointer (evaluate_expression (expr));
do_cleanups (old_chain);
return addr;
}
parse_and_eval_address_1 (expptr)
char **expptr;
{
- struct expression *expr = parse_c_1 (expptr, 0, 0);
+ struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0);
register CORE_ADDR addr;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
- addr = (CORE_ADDR) value_as_long (evaluate_expression (expr));
+ addr = value_as_pointer (evaluate_expression (expr));
do_cleanups (old_chain);
return addr;
}
parse_and_eval (exp)
char *exp;
{
- struct expression *expr = parse_c_expression (exp);
+ struct expression *expr = parse_expression (exp);
register value val;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
parse_to_comma_and_eval (expp)
char **expp;
{
- struct expression *expr = parse_c_1 (expp, 0, 1);
+ struct expression *expr = parse_exp_1 (expp, (struct block *) 0, 1);
register value val;
register struct cleanup *old_chain
= make_cleanup (free_current_contents, &expr);
}
\f
/* Evaluate an expression in internal prefix form
- such as is constructed by expread.y.
+ such as is constructed by parse.y.
See expression.h for info on the format of an expression. */
static value evaluate_subexp_for_sizeof ();
static value evaluate_subexp_with_coercion ();
-/* Values of NOSIDE argument to eval_subexp. */
-enum noside
-{ EVAL_NORMAL,
- EVAL_SKIP, /* Only effect is to increment pos. */
- EVAL_AVOID_SIDE_EFFECTS, /* Don't modify any variables or
- call any functions. The value
- returned will have the correct
- type, and will have an
- approximately correct lvalue
- type (inaccuracy: anything that is
- listed as being in a register in
- the function in which it was
- declared will be lval_register). */
-};
-
value
evaluate_expression (exp)
struct expression *exp;
int tem;
register int pc, pc2, oldpos;
register value arg1, arg2, arg3;
+ struct type *type;
int nargs;
value *argvec;
tem = strlen (&exp->elts[pc + 2].string);
(*pos) += 3 + ((tem + sizeof (union exp_element))
/ sizeof (union exp_element));
- return value_static_field (exp->elts[pc + 1].type,
- &exp->elts[pc + 2].string, -1);
+ arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
+ 0,
+ exp->elts[pc + 1].type,
+ &exp->elts[pc + 2].string,
+ expect_type);
+ if (arg1 == NULL)
+ error ("There is no field named %s", &exp->elts[pc + 2].string);
+ return arg1;
case OP_LONG:
(*pos) += 3;
- return value_from_long (exp->elts[pc + 1].type,
+ return value_from_longest (exp->elts[pc + 1].type,
exp->elts[pc + 2].longconst);
case OP_DOUBLE:
case OP_LAST:
(*pos) += 2;
- return access_value_history ((int) exp->elts[pc + 1].longconst);
+ return
+ access_value_history (longest_to_int (exp->elts[pc + 1].longconst));
case OP_REGISTER:
(*pos) += 2;
- return value_of_register ((int) exp->elts[pc + 1].longconst);
+ return value_of_register (longest_to_int (exp->elts[pc + 1].longconst));
case OP_INTERNALVAR:
(*pos) += 2;
{
int fnptr;
- nargs = (int) exp->elts[pc + 1].longconst + 1;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
- fnptr = (int) value_as_long (arg1);
+ fnptr = longest_to_int (value_as_long (arg1));
+ /* FIXME-tiemann: this is way obsolete. */
if (fnptr < 128)
{
struct type *basetype;
struct type *fntype = lookup_pointer_type (TYPE_FN_FIELD_TYPE (f, j));
if (TYPE_VPTR_FIELDNO (basetype) < 0)
- TYPE_VPTR_FIELDNO (basetype)
- = fill_in_vptr_fieldno (basetype);
+ fill_in_vptr_fieldno (basetype);
VALUE_TYPE (base) = basetype;
vtbl = value_field (base, TYPE_VPTR_FIELDNO (basetype));
/* Hair for method invocations */
int tem2;
- nargs = (int) exp->elts[pc + 1].longconst + 1;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1;
/* First, evaluate the structure into arg2 */
pc2 = (*pos)++;
tem2 = strlen (&exp->elts[pc2 + 1].string);
}
else
{
- nargs = (int) exp->elts[pc + 1].longconst;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
tem = 0;
}
argvec = (value *) alloca (sizeof (value) * (nargs + 2));
? "structure" : "structure pointer");
if (VALUE_OFFSET (temp))
{
- arg2 = value_from_long (builtin_type_long,
+ arg2 = value_from_longest (lookup_pointer_type (VALUE_TYPE (temp)),
value_as_long (arg2)+VALUE_OFFSET (temp));
- VALUE_TYPE (arg2) = lookup_pointer_type (VALUE_TYPE (temp));
argvec[1] = arg2;
}
if (static_memfuncp)
else
error ("Expression of type other than \"Function returning ...\" used as function");
}
- return target_call_function (argvec[0], nargs, argvec + 1);
+ return call_function_by_hand (argvec[0], nargs, argvec + 1);
case STRUCTOP_STRUCT:
tem = strlen (&exp->elts[pc + 1].string);
goto nosideret;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
- &exp->elts[pc + 1].string),
+ &exp->elts[pc + 1].string,
+ 1),
lval_memory);
else
{
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (lookup_struct_elt_type (TYPE_TARGET_TYPE
(VALUE_TYPE (arg1)),
- &exp->elts[pc + 1].string),
+ &exp->elts[pc + 1].string,
+ 1),
lval_memory);
else
{
case STRUCTOP_MEMBER:
arg1 = evaluate_subexp_for_address (exp, pos, noside);
- arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- /* Now, convert these values to an address. */
- if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
- || ((TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
- != TYPE_CODE_MEMBER)
- && (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2)))
- != TYPE_CODE_METHOD)))
- error ("non-pointer-to-member value used in pointer-to-member construct");
- arg3 = value_from_long (builtin_type_long,
- value_as_long (arg1) + value_as_long (arg2));
- VALUE_TYPE (arg3) =
- lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
- return value_ind (arg3);
-
+ goto handle_pointer_to_member;
case STRUCTOP_MPTR:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ handle_pointer_to_member:
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR)
+ goto bad_pointer_to_member;
+ type = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+ if (TYPE_CODE (type) == TYPE_CODE_METHOD)
+ error ("not implemented: pointer-to-method in pointer-to-member construct");
+ if (TYPE_CODE (type) != TYPE_CODE_MEMBER)
+ goto bad_pointer_to_member;
/* Now, convert these values to an address. */
- if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_PTR
- || (TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_MEMBER
- && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) != TYPE_CODE_METHOD))
- error ("non-pointer-to-member value used in pointer-to-member construct");
- arg3 = value_from_long (builtin_type_long,
- value_as_long (arg1) + value_as_long (arg2));
- VALUE_TYPE (arg3) =
- lookup_pointer_type (TYPE_TARGET_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))));
+ arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
+ arg1);
+ arg3 = value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+ value_as_long (arg1) + value_as_long (arg2));
return value_ind (arg3);
+ bad_pointer_to_member:
+ error("non-pointer-to-member value used in pointer-to-member construct");
case BINOP_ASSIGN:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
return arg1;
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_assign (arg1, arg2);
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_add (arg1, arg2);
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_sub (arg1, arg2);
if (noside == EVAL_SKIP)
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
if (noside == EVAL_AVOID_SIDE_EFFECTS
- && op == BINOP_DIV)
+ && (op == BINOP_DIV || op == BINOP_REM))
return value_zero (VALUE_TYPE (arg1), not_lval);
else
return value_binop (arg1, arg2, op);
VALUE_LVAL (arg1));
if (binop_user_defined_p (op, arg1, arg2))
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
else
return value_subscript (arg1, arg2);
if (binop_user_defined_p (op, arg1, arg2))
{
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_zerop (arg1);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(tem ? EVAL_SKIP : noside));
- return value_from_long (builtin_type_int,
+ return value_from_longest (builtin_type_int,
(LONGEST) (!tem && !value_zerop (arg2)));
}
if (binop_user_defined_p (op, arg1, arg2))
{
arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_zerop (arg1);
arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
(!tem ? EVAL_SKIP : noside));
- return value_from_long (builtin_type_int,
+ return value_from_longest (builtin_type_int,
(LONGEST) (!tem || !value_zerop (arg2)));
}
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
{
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_equal (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) tem);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_NOTEQUAL:
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
{
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_equal (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ return value_from_longest (builtin_type_int, (LONGEST) ! tem);
}
case BINOP_LESS:
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
{
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_less (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) tem);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_GTR:
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
{
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
tem = value_less (arg2, arg1);
- return value_from_long (builtin_type_int, (LONGEST) tem);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_GEQ:
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
{
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
- tem = value_less (arg1, arg2);
- return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ tem = value_less (arg2, arg1) || value_equal (arg1, arg2);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_LEQ:
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
{
- return value_x_binop (arg1, arg2, op, 0);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
}
else
{
- tem = value_less (arg2, arg1);
- return value_from_long (builtin_type_int, (LONGEST) ! tem);
+ tem = value_less (arg1, arg2) || value_equal (arg1, arg2);
+ return value_from_longest (builtin_type_int, (LONGEST) tem);
}
case BINOP_REPEAT:
error ("Non-integral right operand for \"@\" operator.");
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return allocate_repeat_value (VALUE_TYPE (arg1),
- (int) value_as_long (arg2));
+ longest_to_int (value_as_long (arg2)));
else
- return value_repeat (arg1, (int) value_as_long (arg2));
+ return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
case BINOP_COMMA:
evaluate_subexp (NULL_TYPE, exp, pos, noside);
return value_neg (arg1);
case UNOP_LOGNOT:
+ /* C++: check for and handle destructor names. */
+ op = exp->elts[*pos].opcode;
+
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (noside == EVAL_SKIP)
goto nosideret;
- if (unop_user_defined_p (op, arg1))
- return value_x_unop (arg1, op);
+ if (unop_user_defined_p (UNOP_LOGNOT, arg1))
+ return value_x_unop (arg1, UNOP_LOGNOT);
else
return value_lognot (arg1);
if (unop_user_defined_p (op, arg1))
return value_x_unop (arg1, op);
else
- return value_from_long (builtin_type_int,
+ return value_from_longest (builtin_type_int,
(LONGEST) value_zerop (arg1));
case UNOP_IND:
goto nosideret;
}
- if (op == OP_SCOPE)
- {
- char *name = &exp->elts[pc+3].string;
- int temm = strlen (name);
- struct type *domain = exp->elts[pc+2].type;
- (*pos) += 2 + (temm + sizeof (union exp_element)) / sizeof (union exp_element);
- arg1 = value_struct_elt_for_address (domain, expect_type, name);
- if (arg1)
- return arg1;
- error ("no field `%s' in structure", name);
- }
- else
- return evaluate_subexp_for_address (exp, pos, noside);
+ return evaluate_subexp_for_address (exp, pos, noside);
case UNOP_SIZEOF:
if (noside == EVAL_SKIP)
return value_zero (exp->elts[pc + 1].type, lval_memory);
else
return value_at_lazy (exp->elts[pc + 1].type,
- (CORE_ADDR) value_as_long (arg1));
+ value_as_pointer (arg1));
case UNOP_PREINCREMENT:
arg1 = evaluate_subexp (expect_type, exp, pos, noside);
}
else
{
- arg2 = value_add (arg1, value_from_long (builtin_type_char,
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
return value_assign (arg1, arg2);
}
}
else
{
- arg2 = value_sub (arg1, value_from_long (builtin_type_char,
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
return value_assign (arg1, arg2);
}
}
else
{
- arg2 = value_add (arg1, value_from_long (builtin_type_char,
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
value_assign (arg1, arg2);
return arg1;
}
else
{
- arg2 = value_sub (arg1, value_from_long (builtin_type_char,
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
(LONGEST) 1));
value_assign (arg1, arg2);
return arg1;
}
nosideret:
- return value_from_long (builtin_type_long, (LONGEST) 1);
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
}
\f
/* Evaluate a subexpression of EXP, at index *POS,
{
enum exp_opcode op;
register int pc;
+ struct symbol *var;
pc = (*pos);
op = exp->elts[pc].opcode;
evaluate_subexp (NULL_TYPE, exp, pos, noside));
case OP_VAR_VALUE:
+ var = exp->elts[pc + 1].symbol;
+
+ /* C++: The "address" of a reference should yield the address
+ * of the object pointed to. Let value_addr() deal with it. */
+ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF)
+ goto default_case;
+
(*pos) += 3;
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type =
- lookup_pointer_type (SYMBOL_TYPE (exp->elts[pc + 1].symbol));
- enum address_class sym_class =
- SYMBOL_CLASS (exp->elts[pc + 1].symbol);
+ lookup_pointer_type (SYMBOL_TYPE (var));
+ enum address_class sym_class = SYMBOL_CLASS (var);
if (sym_class == LOC_CONST
|| sym_class == LOC_CONST_BYTES
value_zero (type, not_lval);
}
else
- return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
+ return locate_var_value (var, (FRAME) 0);
default:
+ default_case:
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
value x = evaluate_subexp (NULL_TYPE, exp, pos, noside);
if (VALUE_LVAL (x) == lval_memory)
- return value_zero (TYPE_POINTER_TYPE (VALUE_TYPE (x)),
+ return value_zero (lookup_pointer_type (VALUE_TYPE (x)),
not_lval);
else
error ("Attempt to take address of non-lval");
register enum exp_opcode op;
register int pc;
register value val;
+ struct symbol *var;
pc = (*pos);
op = exp->elts[pc].opcode;
switch (op)
{
case OP_VAR_VALUE:
- if (TYPE_CODE (SYMBOL_TYPE (exp->elts[pc + 1].symbol)) == TYPE_CODE_ARRAY)
+ var = exp->elts[pc + 1].symbol;
+ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ARRAY)
{
(*pos) += 3;
- val = locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
- return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (exp->elts[pc + 1].symbol))),
+ val = locate_var_value (var, (FRAME) 0);
+ return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))),
val);
}
default:
case UNOP_IND:
(*pos)++;
val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_long (builtin_type_int, (LONGEST)
+ return value_from_longest (builtin_type_int, (LONGEST)
TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
case UNOP_MEMVAL:
(*pos) += 3;
- return value_from_long (builtin_type_int,
+ return value_from_longest (builtin_type_int,
(LONGEST) TYPE_LENGTH (exp->elts[pc + 1].type));
case OP_VAR_VALUE:
(*pos) += 3;
- return value_from_long (builtin_type_int,
+ return value_from_longest (builtin_type_int,
(LONGEST) TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
default:
val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_long (builtin_type_int,
+ return value_from_longest (builtin_type_int,
(LONGEST) TYPE_LENGTH (VALUE_TYPE (val)));
}
}
+
+/* Parse a type expression in the string [P..P+LENGTH). */
+
+struct type *
+parse_and_eval_type (p, length)
+ char *p;
+ int length;
+{
+ char *tmp = (char *)alloca (length + 4);
+ struct expression *expr;
+ tmp[0] = '(';
+ (void) memcpy (tmp+1, p, length);
+ tmp[length+1] = ')';
+ tmp[length+2] = '0';
+ tmp[length+3] = '\0';
+ expr = parse_expression (tmp);
+ if (expr->elts[0].opcode != UNOP_CAST)
+ error ("Internal error in eval_type.");
+ return expr->elts[1].type;
+}