📄 valarith.c
字号:
/* Perform arithmetic and other operations on values, for GDB. Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.This file is part of GDB.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "defs.h"#include "value.h"#include "symtab.h"#include "gdbtypes.h"#include "expression.h"#include "target.h"#include <string.h>static valuevalue_subscripted_rvalue PARAMS ((value, value));valuevalue_add (arg1, arg2) value arg1, arg2;{ register value valint, valptr; register int len; COERCE_ARRAY (arg1); COERCE_ARRAY (arg2); if ((TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_PTR) && (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_INT || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT)) /* Exactly one argument is a pointer, and one is an integer. */ { if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) { valptr = arg1; valint = arg2; } else { valptr = arg2; valint = arg1; } len = TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (valptr))); if (len == 0) len = 1; /* For (void *) */ return value_from_longest (VALUE_TYPE (valptr), value_as_long (valptr) + (len * value_as_long (valint))); } return value_binop (arg1, arg2, BINOP_ADD);}valuevalue_sub (arg1, arg2) value arg1, arg2;{ COERCE_ARRAY (arg1); COERCE_ARRAY (arg2); if (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_PTR) { if (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_INT) { /* pointer - integer. */ return value_from_longest (VALUE_TYPE (arg1), value_as_long (arg1) - (TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) * value_as_long (arg2))); } else if (VALUE_TYPE (arg1) == VALUE_TYPE (arg2)) { /* pointer to <type x> - pointer to <type x>. */ return value_from_longest (builtin_type_long, /* FIXME -- should be ptrdiff_t */ (value_as_long (arg1) - value_as_long (arg2)) / TYPE_LENGTH (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)))); } else { error ("\First argument of `-' is a pointer and second argument is neither\n\an integer nor a pointer of the same type."); } } return value_binop (arg1, arg2, BINOP_SUB);}/* Return the value of ARRAY[IDX]. */valuevalue_subscript (array, idx) value array, idx;{ if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_ARRAY && VALUE_LVAL (array) != lval_memory) return value_subscripted_rvalue (array, idx); else return value_ind (value_add (array, idx));}/* Return the value of EXPR[IDX], expr an aggregate rvalue (eg, a vector register). This routine used to promote floats to doubles, but no longer does. */static valuevalue_subscripted_rvalue (array, idx) value array, idx;{ struct type *elt_type = TYPE_TARGET_TYPE (VALUE_TYPE (array)); int elt_size = TYPE_LENGTH (elt_type); int elt_offs = elt_size * longest_to_int (value_as_long (idx)); value v; if (elt_offs >= TYPE_LENGTH (VALUE_TYPE (array))) error ("no such vector element"); v = allocate_value (elt_type); memcpy (VALUE_CONTENTS (v), VALUE_CONTENTS (array) + elt_offs, elt_size); if (VALUE_LVAL (array) == lval_internalvar) VALUE_LVAL (v) = lval_internalvar_component; else VALUE_LVAL (v) = not_lval; VALUE_ADDRESS (v) = VALUE_ADDRESS (array); VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs; VALUE_BITSIZE (v) = elt_size * 8; return v;}/* Check to see if either argument is a structure. This is called so we know whether to go ahead with the normal binop or look for a user defined function instead. For now, we do not overload the `=' operator. */intbinop_user_defined_p (op, arg1, arg2) enum exp_opcode op; value arg1, arg2;{ if (op == BINOP_ASSIGN) return 0; return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT || TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_STRUCT || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT) || (TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_REF && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg2))) == TYPE_CODE_STRUCT));}/* Check to see if argument is a structure. This is called so we know whether to go ahead with the normal unop or look for a user defined function instead. For now, we do not overload the `&' operator. */int unop_user_defined_p (op, arg1) enum exp_opcode op; value arg1;{ if (op == UNOP_ADDR) return 0; return (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_STRUCT || (TYPE_CODE (VALUE_TYPE (arg1)) == TYPE_CODE_REF && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1))) == TYPE_CODE_STRUCT));}/* We know either arg1 or arg2 is a structure, so try to find the right user defined function. Create an argument vector that calls arg1.operator @ (arg1,arg2) and return that value (where '@' is any binary operator which is legal for GNU C++). OP is the operatore, and if it is BINOP_ASSIGN_MODIFY, then OTHEROP is the opcode saying how to modify it. Otherwise, OTHEROP is unused. */valuevalue_x_binop (arg1, arg2, op, otherop) value arg1, arg2; enum exp_opcode op, otherop;{ value * argvec; char *ptr; char tstr[13]; int static_memfuncp; COERCE_REF (arg1); COERCE_REF (arg2); COERCE_ENUM (arg1); COERCE_ENUM (arg2); /* now we know that what we have to do is construct our arg vector and find the right function to call it with. */ if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) error ("Can't do that binary op on that type"); /* FIXME be explicit */ argvec = (value *) alloca (sizeof (value) * 4); argvec[1] = value_addr (arg1); argvec[2] = arg2; argvec[3] = 0; /* make the right function name up */ strcpy(tstr, "operator__"); ptr = tstr+8; switch (op) { case BINOP_ADD: strcpy(ptr,"+"); break; case BINOP_SUB: strcpy(ptr,"-"); break; case BINOP_MUL: strcpy(ptr,"*"); break; case BINOP_DIV: strcpy(ptr,"/"); break; case BINOP_REM: strcpy(ptr,"%"); break; case BINOP_LSH: strcpy(ptr,"<<"); break; case BINOP_RSH: strcpy(ptr,">>"); break; case BINOP_LOGAND: strcpy(ptr,"&"); break; case BINOP_LOGIOR: strcpy(ptr,"|"); break; case BINOP_LOGXOR: strcpy(ptr,"^"); break; case BINOP_AND: strcpy(ptr,"&&"); break; case BINOP_OR: strcpy(ptr,"||"); break; case BINOP_MIN: strcpy(ptr,"<?"); break; case BINOP_MAX: strcpy(ptr,">?"); break; case BINOP_ASSIGN: strcpy(ptr,"="); break; case BINOP_ASSIGN_MODIFY: switch (otherop) { case BINOP_ADD: strcpy(ptr,"+="); break; case BINOP_SUB: strcpy(ptr,"-="); break; case BINOP_MUL: strcpy(ptr,"*="); break; case BINOP_DIV: strcpy(ptr,"/="); break; case BINOP_REM: strcpy(ptr,"%="); break; case BINOP_LOGAND: strcpy(ptr,"&="); break; case BINOP_LOGIOR: strcpy(ptr,"|="); break; case BINOP_LOGXOR: strcpy(ptr,"^="); break; default: error ("Invalid binary operation specified."); } break; case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break; case BINOP_EQUAL: strcpy(ptr,"=="); break; case BINOP_NOTEQUAL: strcpy(ptr,"!="); break; case BINOP_LESS: strcpy(ptr,"<"); break; case BINOP_GTR: strcpy(ptr,">"); break; case BINOP_GEQ: strcpy(ptr,">="); break; case BINOP_LEQ: strcpy(ptr,"<="); break; default: error ("Invalid binary operation specified."); } argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure"); if (argvec[0]) { if (static_memfuncp) { argvec[1] = argvec[0]; argvec++; } return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1); } error ("member function %s not found", tstr);#ifdef lint return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);#endif}/* We know that arg1 is a structure, so try to find a unary user defined operator that matches the operator in question. Create an argument vector that calls arg1.operator @ (arg1) and return that value (where '@' is (almost) any unary operator which is legal for GNU C++). */valuevalue_x_unop (arg1, op) value arg1; enum exp_opcode op;{ value * argvec; char *ptr; char tstr[13]; int static_memfuncp; COERCE_ENUM (arg1); /* now we know that what we have to do is construct our arg vector and find the right function to call it with. */ if (TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_STRUCT) error ("Can't do that unary op on that type"); /* FIXME be explicit */ argvec = (value *) alloca (sizeof (value) * 3); argvec[1] = value_addr (arg1); argvec[2] = 0; /* make the right function name up */ strcpy(tstr,"operator__"); ptr = tstr+8; switch (op) { case UNOP_PREINCREMENT: strcpy(ptr,"++"); break; case UNOP_PREDECREMENT: strcpy(ptr,"++"); break; case UNOP_POSTINCREMENT: strcpy(ptr,"++"); break; case UNOP_POSTDECREMENT: strcpy(ptr,"++"); break; case UNOP_ZEROP: strcpy(ptr,"!"); break; case UNOP_LOGNOT: strcpy(ptr,"~"); break; case UNOP_NEG: strcpy(ptr,"-"); break; default: error ("Invalid binary operation specified."); } argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure"); if (argvec[0]) { if (static_memfuncp) { argvec[1] = argvec[0]; argvec++; } return call_function_by_hand (argvec[0], 1 - static_memfuncp, argvec + 1); } error ("member function %s not found", tstr); return 0; /* For lint -- never reached */}/* Perform a binary operation on two integers or two floats. Does not support addition and subtraction on pointers; use value_add or value_sub if you want to handle those possibilities. */valuevalue_binop (arg1, arg2, op) value arg1, arg2; enum exp_opcode op;{ register value val; COERCE_ENUM (arg1); COERCE_ENUM (arg2); if ((TYPE_CODE (VALUE_TYPE (arg1)) != TYPE_CODE_FLT &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -