pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:40:
/* This calculation should always give some margin based on the size. */ /* It utilizes that log10(256) ~= 2.4 < 5/2. */ /* One extra char for the sign and one for the \0 terminator. */ #define MAX_INT_SPRINTF_LEN (2 + (SIZEOF_INT_TYPE * 5 + 1) / 2) /* Enough to hold a Pike float or int in textform */ #define MAX_NUM_BUF (MAXIMUM(MAX_INT_SPRINTF_LEN,MAX_FLOAT_SPRINTF_LEN)) static int has_lfun( enum LFUN lfun, int arg );
+
static int call_lfun(enum LFUN left, enum LFUN right);
static int call_lhs_lfun( enum LFUN lfun, int arg ); void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind) { switch(TYPEOF(*what)) { case T_ARRAY: simple_array_index_no_free(to,what->u.array,ind); break;
pike.git/src/operators.c:1319:
#endif /* PIKE_DEBUG */ apply_low(o, i, e); args -= e; /* Replace the object with the result. */ assign_svalue(Pike_sp-(args+1), Pike_sp-1); pop_stack(); return args; } }
+
static int pair_add()
+
{
+
if(TYPEOF(sp[-1]) == PIKE_T_OBJECT ||
+
TYPEOF(sp[-2]) == PIKE_T_OBJECT)
+
{
+
if(TYPEOF(sp[-2]) == PIKE_T_OBJECT &&
+
/* Note: pairwise add always has an extra reference! */
+
sp[-2].u.object->refs == 2 &&
+
call_lhs_lfun(LFUN_ADD_EQ,2))
+
return 1; /* optimized version of +. */
+
if(call_lfun(LFUN_ADD, LFUN_RADD))
+
return 1; /* standard editon */
+
}
+
+
+
if (TYPEOF(sp[-2]) != TYPEOF(sp[-1]))
+
{
+
if(IS_UNDEFINED(sp-2))
+
{
+
stack_swap();
+
pop_stack();
+
return 1;
+
}
+
+
if(IS_UNDEFINED(sp-1))
+
{
+
pop_stack();
+
return 1;
+
}
+
+
/* string + X && X + string -> string */
+
if( TYPEOF(Pike_sp[-2]) == PIKE_T_STRING )
+
o_cast_to_string();
+
else if( TYPEOF(Pike_sp[-1]) == PIKE_T_STRING )
+
{
+
stack_swap();
+
o_cast_to_string();
+
stack_swap();
+
}
+
else if( TYPEOF(Pike_sp[-2]) == PIKE_T_FLOAT )
+
{
+
if( TYPEOF(Pike_sp[-1]) == PIKE_T_INT )
+
{
+
Pike_sp[-1].u.float_number = Pike_sp[-1].u.integer;
+
TYPEOF(Pike_sp[-1]) = PIKE_T_FLOAT;
+
}
+
}
+
else if( TYPEOF(Pike_sp[-1]) == PIKE_T_FLOAT )
+
{
+
if( TYPEOF(Pike_sp[-2]) == PIKE_T_INT )
+
{
+
Pike_sp[-2].u.float_number = Pike_sp[-2].u.integer;
+
TYPEOF(Pike_sp[-2]) = PIKE_T_FLOAT;
+
}
+
}
+
+
if (TYPEOF(sp[-2]) != TYPEOF(sp[-1]))
+
return 0;
+
}
+
+
/* types now identical. */
+
switch(TYPEOF(sp[-1]))
+
{
+
/*
+
Note: these cases mainly tend to happen when there is an object
+
in the argument list. otherwise pairwise addition is not done
+
using this code.
+
*/
+
case PIKE_T_INT:
+
{
+
INT_TYPE res;
+
if (DO_INT_TYPE_ADD_OVERFLOW(sp[-2].u.integer, sp[-1].u.integer, &res))
+
{
+
convert_svalue_to_bignum(sp-2);
+
call_lfun(LFUN_ADD,LFUN_RADD);
+
return 1;
+
}
+
sp[-2].u.integer = res;
+
sp--;
+
}
+
return 1;
+
case PIKE_T_FLOAT:
+
sp[-2].u.float_number += sp[-1].u.float_number;
+
sp--;
+
return 1;
+
case PIKE_T_STRING:
+
Pike_sp[-2].u.string = add_and_free_shared_strings(Pike_sp[-2].u.string,
+
Pike_sp[-1].u.string);
+
Pike_sp--;
+
return 1;
+
+
case PIKE_T_ARRAY:
+
push_array( add_arrays(sp-2,2) );
+
stack_swap(); pop_stack();
+
stack_swap(); pop_stack();
+
return 1;
+
case PIKE_T_MAPPING:
+
push_mapping( add_mappings(sp-2,2) );
+
stack_swap(); pop_stack();
+
stack_swap(); pop_stack();
+
return 1;
+
case PIKE_T_MULTISET:
+
push_multiset( add_multisets(sp-2,2) );
+
stack_swap(); pop_stack();
+
stack_swap(); pop_stack();
+
return 1;
+
case PIKE_T_OBJECT:
+
return call_lfun(LFUN_ADD,LFUN_RADD);
+
}
+
return 0;
+
}
+
/*! @decl mixed `+(mixed arg) *! @decl mixed `+(object arg, mixed ... more) *! @decl int `+(int arg, int ... more) *! @decl float `+(float|int arg, float|int ... more) *! @decl string `+(string|float|int arg, string|float|int ... more) *! @decl array `+(array arg, array ... more) *! @decl mapping `+(mapping arg, mapping ... more) *! @decl multiset `+(multiset arg, multiset ... more) *! *! Addition/concatenation.
pike.git/src/operators.c:1398:
*! in Pike 7.0. *! *! @seealso *! @[`-()], @[lfun::`+()], @[lfun::``+()] */ PMOD_EXPORT void f_add(INT32 args) { INT_TYPE e,size; TYPE_FIELD types;
+
if(!args)
+
SIMPLE_WRONG_NUM_ARGS_ERROR("`+", 1);
+
tail_recurse: if (args == 1) return; types=0; for(e=-args;e<0;e++) types |= 1<<TYPEOF(sp[e]); switch(types) { default:
-
if(!args)
+
{
-
SIMPLE_WRONG_NUM_ARGS_ERROR("`+", 1);
-
}else{
-
if(types & BIT_OBJECT)
-
{
-
struct
object
*
o;
-
struct program *p;
-
int i;
-
-
if(TYPEOF(sp[-args])
=
= T_OBJECT &&
sp
[
-args
].u.object->prog)
-
{
-
/* The first argument is an object. */
-
o = sp[-args].u.object
;
-
p = o->prog->inherits[SUBTYPEOF(sp[-args])].prog;
-
if(o->refs==1 &&
-
(i = FIND
_
LFUN(p, LFUN_ADD_EQ)) != -1)
-
{
-
apply_low(o, i, args-1);
-
stack_pop_keep_top();
-
return;
-
}
-
if((i = FIND_LFUN(p, LFUN_ADD)) != -1)
-
{
-
apply_low(o, i, args-1);
-
free_
svalue(
sp-2
);
-
sp[-2]=sp[-1];
-
sp--;
-
dmalloc_touch_svalue(sp);
-
return;
-
}
-
}
-
+
struct
svalue
*
s
=sp-args;
+
push
_svalue(
s
);
for(e=1;e<args;e++) {
-
if(TYPEOF(sp[e-args]) == T
_
OBJECT &&
-
(
p = (o = sp[e-args].u.object
)
->prog) &&
-
(
i = FIND
_
LFUN
(
p->inherits[SUBTYPEOF(sp[e-args]
)
].prog,
-
LFUN_RADD
)
) != -1)
+
push
_
svalue
(
s+e
)
;
+
if
(
!pair
_
add
())
{
-
/* There'
s
an
object
with
a
lfun::``+()
at
argument
@[e].
*/
-
if ((args = low
_
rop
(
o, i, e, args
))
>
1)
{
-
goto
tail
_
recurse
;
+
Pike_error("Addition
on
unsupported
types:
%
s
+
%s\nm",
+
get_name_of_type
(
TYPEOF
(
sp[-1]))
,
+
get
_
name_of_type(TYPEOF(*s)))
;
}
-
+
}
+
assign_svalue(s,sp-1);
+
pop_n_elems(sp-s-1);
return; }
-
}
-
}
-
}
+
-
switch(TYPEOF(sp[-args]))
-
{
-
case T_PROGRAM:
-
case T_FUNCTION:
-
SIMPLE_ARG_TYPE_ERROR("`+", 1,
-
"string|object|int|float|array|mapping|multiset");
-
}
-
bad_arg_error("`+", sp-args, args, 1,
-
"string|object|int|float|array|mapping|multiset", sp-args,
-
"Incompatible types\n");
-
return; /* compiler hint */
-
+
case BIT_STRING: { struct pike_string *r; PCHARP buf; ptrdiff_t tmp; int max_shift=0; size=0; for(e=-args;e<0;e++) {