123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- /* Evaluate expressions for GDB.
- Copyright (C) 1986, 1987 Free Software Foundation, Inc.
- GDB is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone
- for the consequences of using it or for whether it serves any
- particular purpose or works at all, unless he says so in writing.
- Refer to the GDB General Public License for full details.
- Everyone is granted permission to copy, modify and redistribute GDB,
- but only under the conditions described in the GDB General Public
- License. A copy of this license is supposed to have been given to you
- along with GDB so you can know your rights and responsibilities. It
- should be in a file named COPYING. Among other things, the copyright
- notice and this notice must be preserved on all copies.
- In other words, go ahead and share GDB, but don't try to stop
- anyone else from sharing it farther. Help stamp out software hoarding!
- */
- #include "defs.h"
- #include "initialize.h"
- #include "symtab.h"
- #include "value.h"
- #include "expression.h"
- START_FILE
- /* Parse the string EXP as a C expression, evaluate it,
- and return the result as a number. */
- CORE_ADDR
- parse_and_eval_address (exp)
- char *exp;
- {
- struct expression *expr = parse_c_expression (exp);
- register CORE_ADDR addr;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
- addr = value_as_long (evaluate_expression (expr));
- do_cleanups (old_chain);
- return addr;
- }
- /* Like parse_and_eval_address but takes a pointer to a char * variable
- and advanced that variable across the characters parsed. */
- CORE_ADDR
- parse_and_eval_address_1 (expptr)
- char **expptr;
- {
- struct expression *expr = parse_c_1 (expptr, 0);
- register CORE_ADDR addr;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
- addr = value_as_long (evaluate_expression (expr));
- do_cleanups (old_chain);
- return addr;
- }
- value
- parse_and_eval (exp)
- char *exp;
- {
- struct expression *expr = parse_c_expression (exp);
- register value val;
- register struct cleanup *old_chain
- = make_cleanup (free_current_contents, &expr);
- val = evaluate_expression (expr);
- do_cleanups (old_chain);
- return val;
- }
- /* Evaluate an expression in internal prefix form
- such as is constructed by expread.y.
- See expression.h for info on the format of an expression. */
- static value evaluate_subexp ();
- static value evaluate_subexp_for_address ();
- 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,
- EVAL_AVOID_SIDE_EFFECTS,
- };
- value
- evaluate_expression (exp)
- struct expression *exp;
- {
- int pc = 0;
- return evaluate_subexp (exp, &pc, EVAL_NORMAL);
- }
- /* Evaluate an expression, avoiding all memory references
- and getting a value whose type alone is correct. */
- value
- evaluate_type (exp)
- struct expression *exp;
- {
- int pc = 0;
- return evaluate_subexp (exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
- }
- static value
- evaluate_subexp (exp, pos, noside)
- register struct expression *exp;
- register int *pos;
- enum noside noside;
- {
- enum exp_opcode op;
- int tem;
- register int pc;
- register value arg1, arg2;
- int nargs;
- value *argvec;
- pc = (*pos)++;
- op = exp->elts[pc].opcode;
- switch (op)
- {
- case OP_LONG:
- (*pos) += 3;
- return value_from_long (exp->elts[pc + 1].type,
- exp->elts[pc + 2].longconst);
- case OP_DOUBLE:
- (*pos) += 3;
- return value_from_double (exp->elts[pc + 1].type,
- exp->elts[pc + 2].doubleconst);
- case OP_VAR_VALUE:
- (*pos) += 2;
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_of_variable (exp->elts[pc + 1].symbol);
- case OP_LAST:
- (*pos) += 2;
- return access_value_history (exp->elts[pc + 1].longconst);
- case OP_REGISTER:
- (*pos) += 2;
- return value_of_register (exp->elts[pc + 1].longconst);
- case OP_INTERNALVAR:
- (*pos) += 2;
- return value_of_internalvar (exp->elts[pc + 1].internalvar);
- case OP_FUNCALL:
- (*pos) += 2;
- nargs = exp->elts[pc + 1].longconst;
- argvec = (value *) alloca (sizeof (value) * (nargs + 1));
- for (tem = 0; tem <= nargs; tem++)
- argvec[tem] = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- if (noside == EVAL_AVOID_SIDE_EFFECTS)
- return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
- return call_function (argvec[0], nargs, argvec + 1);
- case OP_STRING:
- tem = strlen (&exp->elts[pc + 1].string);
- (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_string (&exp->elts[pc + 1].string, tem);
- case TERNOP_COND:
- /* Skip third and second args to evaluate the first one. */
- arg1 = evaluate_subexp (exp, pos, noside);
- if (value_zerop (arg1))
- {
- evaluate_subexp (exp, pos, EVAL_SKIP);
- return evaluate_subexp (exp, pos, noside);
- }
- else
- {
- arg2 = evaluate_subexp (exp, pos, noside);
- evaluate_subexp (exp, pos, EVAL_SKIP);
- return arg2;
- }
- case STRUCTOP_STRUCT:
- tem = strlen (&exp->elts[pc + 1].string);
- (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_struct_elt (arg1, &exp->elts[pc + 1].string,
- "structure");
- case STRUCTOP_PTR:
- tem = strlen (&exp->elts[pc + 1].string);
- (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_struct_elt (arg1, &exp->elts[pc + 1].string,
- "structure pointer");
- case BINOP_ASSIGN:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- return value_assign (arg1, arg2);
- case BINOP_ASSIGN_MODIFY:
- (*pos) += 2;
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- op = exp->elts[pc + 1].opcode;
- if (op == BINOP_ADD)
- arg2 = value_add (arg1, arg2);
- else if (op == BINOP_SUB)
- arg2 = value_sub (arg1, arg2);
- else
- arg2 = value_binop (arg1, arg2, op);
- return value_assign (arg1, arg2);
- case BINOP_ADD:
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_add (arg1, arg2);
- case BINOP_SUB:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_sub (arg1, arg2);
- case BINOP_MUL:
- case BINOP_DIV:
- case BINOP_REM:
- case BINOP_LSH:
- case BINOP_RSH:
- case BINOP_LOGAND:
- case BINOP_LOGIOR:
- case BINOP_LOGXOR:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_binop (arg1, arg2, op);
- case BINOP_SUBSCRIPT:
- arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
- arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_subscript (arg1, arg2, op);
-
- case BINOP_AND:
- arg1 = evaluate_subexp (exp, pos, noside);
- tem = value_zerop (arg1);
- arg2 = evaluate_subexp (exp, pos,
- (tem ? EVAL_SKIP : noside));
- return value_from_long (builtin_type_int,
- !tem && !value_zerop (arg2));
- case BINOP_OR:
- arg1 = evaluate_subexp (exp, pos, noside);
- tem = value_zerop (arg1);
- arg2 = evaluate_subexp (exp, pos,
- (!tem ? EVAL_SKIP : noside));
- return value_from_long (builtin_type_int,
- !tem || !value_zerop (arg2));
- case BINOP_EQUAL:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- tem = value_equal (arg1, arg2);
- return value_from_long (builtin_type_int, tem);
- case BINOP_NOTEQUAL:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- tem = value_equal (arg1, arg2);
- return value_from_long (builtin_type_int, ! tem);
- case BINOP_LESS:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- tem = value_less (arg1, arg2);
- return value_from_long (builtin_type_int, tem);
- case BINOP_GTR:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- tem = value_less (arg2, arg1);
- return value_from_long (builtin_type_int, tem);
- case BINOP_GEQ:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- tem = value_less (arg1, arg2);
- return value_from_long (builtin_type_int, ! tem);
- case BINOP_LEQ:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- tem = value_less (arg2, arg1);
- return value_from_long (builtin_type_int, ! tem);
- case BINOP_REPEAT:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_repeat (arg1, value_as_long (arg2));
- case BINOP_COMMA:
- evaluate_subexp (exp, pos, noside);
- return evaluate_subexp (exp, pos, noside);
- case UNOP_NEG:
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_neg (arg1);
- case UNOP_LOGNOT:
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_lognot (arg1);
- case UNOP_ZEROP:
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_from_long (builtin_type_int, value_zerop (arg1));
- case UNOP_IND:
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_ind (arg1);
- case UNOP_ADDR:
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (exp, pos, EVAL_SKIP);
- goto nosideret;
- }
- return evaluate_subexp_for_address (exp, pos, noside);
- case UNOP_SIZEOF:
- if (noside == EVAL_SKIP)
- {
- evaluate_subexp (exp, pos, EVAL_SKIP);
- goto nosideret;
- }
- return evaluate_subexp_for_sizeof (exp, pos);
- case UNOP_CAST:
- (*pos) += 2;
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_cast (exp->elts[pc + 1].type, arg1);
- case UNOP_MEMVAL:
- (*pos) += 2;
- arg1 = evaluate_subexp (exp, pos, noside);
- if (noside == EVAL_SKIP)
- goto nosideret;
- return value_at (exp->elts[pc + 1].type, value_as_long (arg1));
- case UNOP_PREINCREMENT:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- return value_assign (arg1, arg2);
- case UNOP_PREDECREMENT:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- return value_assign (arg1, arg2);
- case UNOP_POSTINCREMENT:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = value_add (arg1, value_from_long (builtin_type_char, 1));
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- value_assign (arg1, arg2);
- return arg1;
- case UNOP_POSTDECREMENT:
- arg1 = evaluate_subexp (exp, pos, noside);
- arg2 = value_sub (arg1, value_from_long (builtin_type_char, 1));
- if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
- return arg1;
- value_assign (arg1, arg2);
- return arg1;
- }
- nosideret:
- return value_from_long (builtin_type_long, 1);
- }
- /* Evaluate a subexpression of EXP, at index *POS,
- and return the address of that subexpression.
- Advance *POS over the subexpression.
- If the subexpression isn't an lvalue, get an error.
- NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
- then only the type of the result need be correct. */
- static value
- evaluate_subexp_for_address (exp, pos, noside)
- register struct expression *exp;
- register int *pos;
- enum noside noside;
- {
- enum exp_opcode op;
- register int pc;
- pc = (*pos);
- op = exp->elts[pc].opcode;
- switch (op)
- {
- case UNOP_IND:
- (*pos)++;
- return evaluate_subexp (exp, pos, noside);
- case UNOP_MEMVAL:
- (*pos) += 3;
- return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
- evaluate_subexp (exp, pos, noside));
- case OP_VAR_VALUE:
- (*pos) += 3;
- return locate_var_value (exp->elts[pc + 1].symbol, (CORE_ADDR) 0);
- default:
- return value_addr (evaluate_subexp (exp, pos, noside));
- }
- }
- /* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
- When used in contexts where arrays will be coerced anyway,
- this is equivalent to `evaluate_subexp'
- but much faster because it avoids actually fetching array contents. */
- static value
- evaluate_subexp_with_coercion (exp, pos, noside)
- register struct expression *exp;
- register int *pos;
- enum noside noside;
- {
- register enum exp_opcode op;
- register int pc;
- register value val;
- 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)
- {
- (*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);
- }
- }
- return evaluate_subexp (exp, pos, noside);
- }
- /* Evaluate a subexpression of EXP, at index *POS,
- and return a value for the size of that subexpression.
- Advance *POS over the subexpression. */
- static value
- evaluate_subexp_for_sizeof (exp, pos)
- register struct expression *exp;
- register int *pos;
- {
- enum exp_opcode op;
- register int pc;
- value val;
- pc = (*pos);
- op = exp->elts[pc].opcode;
- switch (op)
- {
- /* This case is handled specially
- so that we avoid creating a value for the result type.
- If the result type is very big, it's desirable not to
- create a value unnecessarily. */
- case UNOP_IND:
- (*pos)++;
- val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_long (builtin_type_int,
- TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (val))));
- case UNOP_MEMVAL:
- (*pos) += 3;
- return value_from_long (builtin_type_int,
- TYPE_LENGTH (exp->elts[pc + 1].type));
- case OP_VAR_VALUE:
- (*pos) += 3;
- return value_from_long (builtin_type_int,
- TYPE_LENGTH (SYMBOL_TYPE (exp->elts[pc + 1].symbol)));
- default:
- val = evaluate_subexp (exp, pos, EVAL_AVOID_SIDE_EFFECTS);
- return value_from_long (builtin_type_int,
- TYPE_LENGTH (VALUE_TYPE (val)));
- }
- }
- static
- initialize ()
- { }
- END_FILE
|