#include "dfp.h"
#include <math.h>
#include "infcall.h"
+#include "exceptions.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C). */
}
}
+/* Try to find an operator named OPERATOR which takes NARGS arguments
+ specified in ARGS. If the operator found is a static member operator
+ *STATIC_MEMFUNP will be set to 1, and otherwise 0.
+ The search if performed through find_overload_match which will handle
+ member operators, non member operators, operators imported implicitly or
+ explicitly, and perform correct overload resolution in all of the above
+ situations or combinations thereof. */
+
+static struct value *
+value_user_defined_cpp_op (struct value **args, int nargs, char *operator,
+ int *static_memfuncp)
+{
+
+ struct symbol *symp = NULL;
+ struct value *valp = NULL;
+ struct type **arg_types;
+ int i;
+
+ arg_types = (struct type **) alloca (nargs * (sizeof (struct type *)));
+ /* Prepare list of argument types for overload resolution */
+ for (i = 0; i < nargs; i++)
+ arg_types[i] = value_type (args[i]);
+
+ find_overload_match (arg_types, nargs, operator, BOTH /* could be method */,
+ 0 /* strict match */, &args[0], /* objp */
+ NULL /* pass NULL symbol since symbol is unknown */,
+ &valp, &symp, static_memfuncp, 0);
+
+ if (valp)
+ return valp;
+
+ if (symp)
+ {
+ /* This is a non member function and does not
+ expect a reference as its first argument
+ rather the explicit structure. */
+ args[0] = value_ind (args[0]);
+ return value_of_variable (symp, 0);
+ }
+
+ error (_("Could not find %s."), operator);
+}
+
+/* Lookup user defined operator NAME. Return a value representing the
+ function, otherwise return NULL. */
+
+static struct value *
+value_user_defined_op (struct value **argp, struct value **args, char *name,
+ int *static_memfuncp, int nargs)
+{
+ struct value *result = NULL;
+
+ if (current_language->la_language == language_cplus)
+ result = value_user_defined_cpp_op (args, nargs, name, static_memfuncp);
+ else
+ result = value_struct_elt (argp, args, name, static_memfuncp,
+ "structure");
+
+ return result;
+}
+
/* 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
error (_("Invalid binary operation specified."));
}
- argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure");
+ argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
+ &static_memfuncp, 2);
if (argvec[0])
{
}
return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
}
- error (_("member function %s not found"), tstr);
+ throw_error (NOT_FOUND_ERROR,
+ _("member function %s not found"), tstr);
#ifdef lint
return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
#endif
case UNOP_IND:
strcpy (ptr, "*");
break;
+ case STRUCTOP_PTR:
+ strcpy (ptr, "->");
+ break;
default:
error (_("Invalid unary operation specified."));
}
- argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure");
+ argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
+ &static_memfuncp, nargs);
if (argvec[0])
{
}
return call_function_by_hand (argvec[0], nargs, argvec + 1);
}
- error (_("member function %s not found"), tstr);
+ throw_error (NOT_FOUND_ERROR,
+ _("member function %s not found"), tstr);
+
return 0; /* For lint -- never reached */
}
\f
Does not support addition and subtraction on pointers;
use value_ptradd, value_ptrsub or value_ptrdiff for those operations. */
-struct value *
-value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
+static struct value *
+scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
{
struct value *val;
struct type *type1, *type2, *result_type;
return val;
}
+
+/* Performs a binary operation on two vector operands by calling scalar_binop
+ for each pair of vector components. */
+
+static struct value *
+vector_binop (struct value *val1, struct value *val2, enum exp_opcode op)
+{
+ struct value *val, *tmp, *mark;
+ struct type *type1, *type2, *eltype1, *eltype2, *result_type;
+ int t1_is_vec, t2_is_vec, elsize, i;
+ LONGEST low_bound1, high_bound1, low_bound2, high_bound2;
+
+ type1 = check_typedef (value_type (val1));
+ type2 = check_typedef (value_type (val2));
+
+ t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type1)) ? 1 : 0;
+ t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type2)) ? 1 : 0;
+
+ if (!t1_is_vec || !t2_is_vec)
+ error (_("Vector operations are only supported among vectors"));
+
+ if (!get_array_bounds (type1, &low_bound1, &high_bound1)
+ || !get_array_bounds (type2, &low_bound2, &high_bound2))
+ error (_("Could not determine the vector bounds"));
+
+ eltype1 = check_typedef (TYPE_TARGET_TYPE (type1));
+ eltype2 = check_typedef (TYPE_TARGET_TYPE (type2));
+ elsize = TYPE_LENGTH (eltype1);
+
+ if (TYPE_CODE (eltype1) != TYPE_CODE (eltype2)
+ || elsize != TYPE_LENGTH (eltype2)
+ || TYPE_UNSIGNED (eltype1) != TYPE_UNSIGNED (eltype2)
+ || low_bound1 != low_bound2 || high_bound1 != high_bound2)
+ error (_("Cannot perform operation on vectors with different types"));
+
+ val = allocate_value (type1);
+ mark = value_mark ();
+ for (i = 0; i < high_bound1 - low_bound1 + 1; i++)
+ {
+ tmp = value_binop (value_subscript (val1, i),
+ value_subscript (val2, i), op);
+ memcpy (value_contents_writeable (val) + i * elsize,
+ value_contents_all (tmp),
+ elsize);
+ }
+ value_free_to_mark (mark);
+
+ return val;
+}
+
+/* Perform a binary operation on two operands. */
+
+struct value *
+value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
+{
+ struct value *val;
+ struct type *type1 = check_typedef (value_type (arg1));
+ struct type *type2 = check_typedef (value_type (arg2));
+ int t1_is_vec = (TYPE_CODE (type1) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type1));
+ int t2_is_vec = (TYPE_CODE (type2) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type2));
+
+ if (!t1_is_vec && !t2_is_vec)
+ val = scalar_binop (arg1, arg2, op);
+ else if (t1_is_vec && t2_is_vec)
+ val = vector_binop (arg1, arg2, op);
+ else
+ {
+ /* Widen the scalar operand to a vector. */
+ struct value **v = t1_is_vec ? &arg2 : &arg1;
+ struct type *t = t1_is_vec ? type2 : type1;
+
+ if (TYPE_CODE (t) != TYPE_CODE_FLT
+ && TYPE_CODE (t) != TYPE_CODE_DECFLOAT
+ && !is_integral_type (t))
+ error (_("Argument to operation not a number or boolean."));
+
+ *v = value_cast (t1_is_vec ? type1 : type2, *v);
+ val = vector_binop (arg1, arg2, op);
+ }
+
+ return val;
+}
\f
/* Simulate the C operator ! -- return 1 if ARG1 contains zero. */
{
return value_from_longest (type, value_as_long (arg1));
}
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
+ {
+ struct value *val = allocate_value (type);
+
+ memcpy (value_contents_raw (val), value_contents (arg1),
+ TYPE_LENGTH (type));
+ return val;
+ }
else
{
error ("Argument to positive operation not a number.");
{
return value_from_longest (type, -value_as_long (arg1));
}
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
+ {
+ struct value *tmp, *val = allocate_value (type);
+ struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+ int i, n = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+
+ for (i = 0; i < n; i++)
+ {
+ tmp = value_neg (value_subscript (arg1, i));
+ memcpy (value_contents_writeable (val) + i * TYPE_LENGTH (eltype),
+ value_contents_all (tmp), TYPE_LENGTH (eltype));
+ }
+ return val;
+ }
else
{
error (_("Argument to negate operation not a number."));
value_complement (struct value *arg1)
{
struct type *type;
+ struct value *val;
arg1 = coerce_ref (arg1);
type = check_typedef (value_type (arg1));
- if (!is_integral_type (type))
- error (_("Argument to complement operation not an integer or boolean."));
+ if (is_integral_type (type))
+ val = value_from_longest (type, ~value_as_long (arg1));
+ else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
+ {
+ struct value *tmp;
+ struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+ int i, n = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+
+ val = allocate_value (type);
+ for (i = 0; i < n; i++)
+ {
+ tmp = value_complement (value_subscript (arg1, i));
+ memcpy (value_contents_writeable (val) + i * TYPE_LENGTH (eltype),
+ value_contents_all (tmp), TYPE_LENGTH (eltype));
+ }
+ }
+ else
+ error (_("Argument to complement operation not an integer, boolean."));
- return value_from_longest (type, ~value_as_long (arg1));
+ return val;
}
\f
/* The INDEX'th bit of SET value whose value_type is TYPE,