pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:1320:
#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 void add_strings(INT32 args)
+
{
+
struct pike_string *r;
+
PCHARP buf;
+
ptrdiff_t tmp;
+
int max_shift=0;
+
ptrdiff_t size=0,e;
+
int num=0;
+
+
for(e=-args;e<0;e++)
+
{
+
if(sp[e].u.string->len != 0) num++;
+
size += sp[e].u.string->len;
+
if(sp[e].u.string->size_shift > max_shift)
+
max_shift=sp[e].u.string->size_shift;
+
}
+
+
/* All strings are empty. */
+
if(num == 0)
+
{
+
pop_n_elems(args-1);
+
return;
+
}
+
+
/* Only one string has length. */
+
if(num == 1)
+
{
+
for(e=-args;e<0;e++)
+
{
+
if( sp[e].u.string->len )
+
{
+
if( e != -args )
+
{
+
r = sp[e].u.string;
+
sp[e].u.string = sp[-args].u.string;
+
sp[-args].u.string = r;
+
}
+
}
+
}
+
pop_n_elems(args-1);
+
return;
+
}
+
+
tmp=sp[-args].u.string->len;
+
r=new_realloc_shared_string(sp[-args].u.string,size,max_shift);
+
mark_free_svalue (sp - args);
+
buf=MKPCHARP_STR_OFF(r,tmp);
+
for(e=-args+1;e<0;e++)
+
{
+
if( sp[e].u.string->len )
+
{
+
update_flags_for_add( r, sp[e].u.string );
+
pike_string_cpy(buf,sp[e].u.string);
+
INC_PCHARP(buf,sp[e].u.string->len);
+
free_string(sp[e].u.string);
+
}
+
}
+
Pike_sp -= args-1;
+
SET_SVAL(sp[-1], T_STRING, 0, string, low_end_shared_string(r));
+
}
+
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 +. */
pike.git/src/operators.c:1508:
*! *! The treatment of @[UNDEFINED] was new *! in Pike 7.0. *! *! @seealso *! @[`-()], @[lfun::`+()], @[lfun::``+()] */ PMOD_EXPORT void f_add(INT32 args) { INT_TYPE e,size;
-
TYPE_FIELD types;
+
TYPE_FIELD types
=0
;
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:
-
+
pairwise_add:
{ struct svalue *s=sp-args; push_svalue(s); for(e=1;e<args;e++) { push_svalue(s+e); if(!pair_add()) { 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; } case BIT_STRING:
-
{
-
struct pike
_
string *r;
-
PCHARP buf;
-
ptrdiff_t tmp;
-
int max_shift=0;
-
-
size=0;
-
for
(
e=-
args
;e<0;e++
)
-
{
-
size+=sp[e].u.string->len
;
-
if(sp[e].u.string->size_shift > max_shift)
-
max_shift=sp[e].u.string->size_shift;
-
}
-
-
if(size == sp[-args].u.string->len)
-
{
-
pop_n_elems(args-1);
+
add
_
strings
(args);
return;
-
}
-
else if(args == 2 && (size == sp[-1].u.string->len))
-
{
-
stack_swap();
-
pop_stack();
-
return;
-
}
+
-
tmp=sp[-args].u.string->len;
-
r=new_realloc_shared_string(sp[-args].u.string,size,max_shift);
-
mark_free_svalue (sp - args);
-
buf=MKPCHARP_STR_OFF(r,tmp);
-
for(e=-args+1;e<0;e++)
-
{
-
if( sp[e].u.string->len )
-
{
-
update_flags_for_add( r, sp[e].u.string );
-
pike_string_cpy(buf,sp[e].u.string);
-
INC_PCHARP(buf,sp[e].u.string->len);
-
}
-
}
-
SET_SVAL(sp[-args], T_STRING, 0, string, low_end_shared_string(r));
-
-
for(e=-args+1;e<0;e++)
-
free_string(sp[e].u.string);
-
-
sp-=args-1;
-
-
break;
-
}
-
+
case BIT_STRING | BIT_INT: case BIT_STRING | BIT_FLOAT: case BIT_STRING | BIT_FLOAT | BIT_INT:
-
+
if ((TYPEOF(sp[-args]) != T_STRING) && (TYPEOF(sp[1-args]) != T_STRING))
{
-
struct
pike_string
*r;
-
PCHARP buf;
-
char buffer[MAX_NUM_BUF];
-
int max_shift=0, len;
-
-
if ((TYPEOF(sp[-args]) != T_STRING) && (TYPEOF(sp[1-args]) != T_STRING)) {
-
struct svalue *save_sp = sp;
-
/*
We
need
to
perform
a
normal
addition
first.
-
*/
-
for
(e=-args; e < 0; e++) {
-
if (TYPEOF(save
_
sp[e]) == T_STRING)
-
break
;
-
*(sp++) = save_sp[e];
-
dmalloc_touch_svalue(Pike_sp-1);
+
/
*
Note:
Could
easily
use
pairwise
add
until
at
first
string
. */
+
goto
pairwise
_
add
;
}
-
/* Perform the addition. */
-
f_add(args+e);
-
dmalloc_touch_svalue(Pike_sp-1);
-
save_sp[--e] = *(--sp);
-
#ifdef PIKE_DEBUG
-
if (sp != save_sp) {
-
Pike_fatal("f_add(): Lost track of stack %p != %p\n", sp, save_sp);
-
}
-
#endif /* PIKE_DEBUG */
-
/* Perform the rest of the addition. */
-
f_add(-e);
-
#ifdef PIKE_DEBUG
-
if (sp != save_sp + 1 + e) {
-
Pike_fatal("f_add(): Lost track of stack (2) %p != %p\n",
-
sp, save_sp + 1 + e);
-
}
-
#endif /* PIKE_DEBUG */
-
/* Adjust the stack. */
-
save_sp[-args] = sp[-1];
-
sp = save_sp + 1 - args;
-
return;
-
} else {
-
e = -args;
-
}
-
-
size=0;
+
for(e=-args;e<0;e++) {
-
switch
(TYPEOF(sp[e]))
+
if
(
TYPEOF(sp[e])
!= PIKE_T_STRING
)
{
-
case
T
_
STRING:
-
size+
=sp[e]
.u.string->len
;
-
if(sp[e].u.string->size
_
shift > max_shift)
-
max_shift=sp[e].u.string->size_shift
;
-
break;
-
-
case T
_
INT:
-
size += MAX
_
INT
_
SPRINTF_LEN
;
-
break;
-
-
case
T_FLOAT:
-
size +
=
MAX
_
FLOAT_SPRINTF_LEN
;
-
break
;
+
*Pike
_
sp
=
sp[e];
+
Pike
_
sp++
;
+
o
_
cast
_
to
_
string()
;
/*
free:s
old
sp[e]
*/
+
sp[e-1]
=
Pike
_
sp[-1]
;
+
Pike_sp--
;
} }
-
+
add_strings(args);
+
return;
-
r=begin_wide_shared_string(size,max_shift);
-
buf=MKPCHARP_STR(r);
-
size=0;
-
-
for(e=-args;e<0;e++)
-
{
-
switch(TYPEOF(sp[e]))
-
{
-
case T_STRING:
-
pike_string_cpy(buf,sp[e].u.string);
-
INC_PCHARP(buf,sp[e].u.string->len);
-
break;
-
-
case T_INT:
-
sprintf(buffer,"%"PRINTPIKEINT"d",sp[e].u.integer);
-
#ifdef PIKE_DEBUG
-
if (strlen (buffer) > MAX_INT_SPRINTF_LEN)
-
Pike_fatal ("Formatted integer %s is %"PRINTSIZET"u, "
-
"longer than assumed max %"PRINTSIZET"u.\n",
-
buffer, strlen (buffer), MAX_INT_SPRINTF_LEN);
-
#endif
-
goto append_buffer;
-
-
case T_FLOAT:
-
sprintf(buffer,"%.*"PRINTPIKEFLOAT"g",
-
PIKEFLOAT_DIG, sp[e].u.float_number);
-
/* See comment for T_FLOAT in o_cast_to_string. */
-
if (!strchr (buffer, '.') && !strchr (buffer, 'e'))
-
strcat (buffer, ".0");
-
#ifdef PIKE_DEBUG
-
if (strlen (buffer) > MAX_FLOAT_SPRINTF_LEN)
-
Pike_fatal ("Formatted float %s is %"PRINTSIZET"u, "
-
"longer than assumed max %"PRINTSIZET"u.\n",
-
buffer, strlen (buffer), MAX_FLOAT_SPRINTF_LEN);
-
#endif
-
-
append_buffer:
-
len = strlen(buffer);
-
switch(max_shift)
-
{
-
case 0:
-
convert_0_to_0((p_wchar0 *)buf.ptr,buffer,len);
-
break;
-
-
case 1:
-
convert_0_to_1((p_wchar1 *)buf.ptr,(p_wchar0 *)buffer,len);
-
break;
-
-
case 2:
-
convert_0_to_2((p_wchar2 *)buf.ptr,(p_wchar0 *)buffer,len);
-
break;
-
}
-
INC_PCHARP(buf,len);
-
}
-
}
-
r = realloc_unlinked_string(r, SUBTRACT_PCHARP(buf, MKPCHARP_STR(r)));
-
r = low_end_shared_string(r);
-
pop_n_elems(args);
-
push_string(r);
-
break;
-
}
-
+
case BIT_INT: {
-
int of = 0;
+
size = 0; for(e = -args; e < 0; e++) { if (DO_INT_TYPE_ADD_OVERFLOW(size, sp[e].u.integer, &size)) { convert_svalue_to_bignum(sp-args); f_add(args); return; } }