diff options
Diffstat (limited to 'gdb/valarith.c')
-rw-r--r-- | gdb/valarith.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/gdb/valarith.c b/gdb/valarith.c index 03bc1e1..adf0044 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -27,6 +27,8 @@ anyone else from sharing it farther. Help stamp out software hoarding! START_FILE +value value_x_binop (); + value value_add (arg1, arg2) value arg1, arg2; @@ -107,7 +109,172 @@ value_subscript (array, idx) { return value_ind (value_add (array, idx)); } + +/* 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. */ + +int +binop_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++). */ + +value +value_x_binop (arg1, arg2, op, otherop) + value arg1, arg2; + int op, otherop; +{ + value * argvec; + char *ptr; + char tstr[13]; + + 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 ("friend functions not implemented yet"); + + 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+9; + 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, "structure"); + if (argvec[0]) + return call_function (argvec[0], 2, argvec + 1); + else error ("member function %s not found", tstr); +} + +/* 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++). */ + +value +value_x_unop (arg1, op) + value arg1; + int op; +{ + value * argvec; + char *ptr; + char tstr[13]; + + 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 ("friend functions not implemented yet"); + + 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+9; + 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, "structure"); + if (argvec[0]) + return call_function (argvec[0], 1, argvec + 1); + else error ("member function %s not found", tstr); +} + /* 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. */ @@ -219,6 +386,14 @@ value_binop (arg1, arg2, op) v = v1 || v2; break; + case BINOP_MIN: + v = v1 < v2 ? v1 : v2; + break; + + case BINOP_MAX: + v = v1 > v2 ? v1 : v2; + break; + default: error ("Invalid binary operation on numbers."); } |