diff --git a/src/operators.c b/src/operators.c index fa7b28b1134197070c64b983624182e6af083d45..9dec0f1529aba787422a56b84c9b523cfc78693d 100644 --- a/src/operators.c +++ b/src/operators.c @@ -5,7 +5,7 @@ \*/ #include <math.h> #include "global.h" -RCSID("$Id: operators.c,v 1.23 1998/01/26 19:59:57 hubbe Exp $"); +RCSID("$Id: operators.c,v 1.24 1998/02/20 01:00:42 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "multiset.h" @@ -936,6 +936,41 @@ void o_multiply(void) { switch(TWO_TYPES(sp[-2].type,sp[-1].type)) { + case TWO_TYPES(T_ARRAY, T_INT): + { + struct array *ret; + struct svalue *pos; + INT32 e; + if(sp[-1].u.integer < 0) + error("Cannot multiply array by negative number.\n"); + ret=allocate_array(sp[-2].u.array->size * sp[-1].u.integer); + pos=ret->item; + for(e=0;e<sp[-1].u.integer;e++,pos+=sp[-2].u.array->size) + assign_svalues_no_free(pos, + sp[-2].u.array->item, + sp[-2].u.array->size, + sp[-2].u.array->type_field); + ret->type_field=sp[-2].u.array->type_field; + pop_n_elems(2); + push_array(ret); + return; + } + case TWO_TYPES(T_STRING, T_INT): + { + struct pike_string *ret; + char *pos; + INT32 e; + if(sp[-1].u.integer < 0) + error("Cannot multiply string by negative number.\n"); + ret=begin_shared_string(sp[-2].u.string->len * sp[-1].u.integer); + pos=ret->str; + for(e=0;e<sp[-1].u.integer;e++,pos+=sp[-2].u.string->len) + MEMCPY(pos,sp[-2].u.string->str,sp[-2].u.string->len); + pop_n_elems(2); + push_string(end_shared_string(ret)); + return; + } + case TWO_TYPES(T_ARRAY,T_STRING): { struct pike_string *ret; @@ -954,7 +989,7 @@ void o_multiply(void) ret=implode_array(sp[-2].u.array, sp[-1].u.array); pop_n_elems(2); push_array(ret); - break; + return; } case TWO_TYPES(T_FLOAT,T_FLOAT): @@ -1028,6 +1063,170 @@ void o_divide(void) { if(call_lfun(LFUN_DIVIDE, LFUN_RDIVIDE)) return; + + switch(TWO_TYPES(sp[-2].type,sp[-1].type)) + { + case TWO_TYPES(T_STRING,T_INT): + { + struct array *a; + char *pos=sp[-2].u.string->str; + INT32 size,e,len; + + len=sp[-1].u.integer; + if(!len) + error("Division by zero.\n"); + + size=sp[-2].u.string->len / len; + if(len<0) + { + len=-len; + pos+=size % len; + } + a=allocate_array(size); + for(e=0;e<size;e++) + { + a->item[e].u.string=make_shared_binary_string(pos,len); + a->item[e].type=T_STRING; + pos+=len; + } + a->type_field=BIT_STRING; + pop_n_elems(2); + push_array(a); + return; + } + + case TWO_TYPES(T_STRING,T_FLOAT): + { + struct array *a; + INT32 last,pos,e,size; + double len; + + len=sp[-1].u.float_number; + if(len==0.0) + error("Division by zero.\n"); + + if(len<0) + { + len=-len; + size=(INT32)ceil( ((double)sp[-2].u.string->len) / len); + a=allocate_array(size); + + for(last=sp[-2].u.string->len,e=0;e<size;e++) + { + pos=sp[-2].u.string->len - (INT32)((e+1)*len); + a->item[e].u.string=make_shared_binary_string( + sp[-2].u.string->str + pos, + last-pos); + last=pos; + } + pos=0; + a->item[e].u.string=make_shared_binary_string( + sp[-2].u.string->str + pos, + last-pos); + }else{ + size=(INT32)ceil( ((double)sp[-2].u.string->len) / len); + a=allocate_array(size); + + for(last=0,e=0;e<size;e++) + { + pos=(INT32)((e+1)*len); + a->item[e].u.string=make_shared_binary_string( + sp[-2].u.string->str + last, + pos-last); + last=pos; + } + pos=sp[2].u.string->len; + a->item[e].u.string=make_shared_binary_string( + sp[-2].u.string->str + last, + pos-last); + } + a->type_field=BIT_STRING; + pop_n_elems(2); + push_array(a); + break; + } + + + case TWO_TYPES(T_ARRAY, T_INT): + { + struct array *a; + INT32 size,e,len,pos=0; + + len=sp[-1].u.integer; + if(!len) + error("Division by zero.\n"); + + size=sp[-2].u.array->size / len; + if(len<0) + { + len=-len; + pos+=size % len; + } + a=allocate_array(size); + for(e=0;e<size;e++) + { + a->item[e].u.array=friendly_slice_array(sp[-2].u.array, + pos, + pos+len); + a->item[e].type=T_ARRAY; + pos+=len; + } + a->type_field=BIT_ARRAY; + pop_n_elems(2); + push_array(a); + return; + } + + case TWO_TYPES(T_ARRAY,T_FLOAT): + { + struct array *a; + INT32 last,pos,e,size; + double len; + + len=sp[-1].u.float_number; + if(len==0.0) + error("Division by zero.\n"); + + if(len<0) + { + len=-len; + size=(INT32)ceil( ((double)sp[-2].u.array->size) / len); + a=allocate_array(size); + + for(last=sp[-2].u.array->size,e=0;e<size;e++) + { + pos=sp[-2].u.array->size - (INT32)((e+1)*len); + a->item[e].u.array=friendly_slice_array(sp[-2].u.array, + pos, + last); + last=pos; + } + a->item[e].u.array=slice_array(sp[-2].u.array, + 0, + last); + }else{ + size=(INT32)ceil( ((double)sp[-2].u.array->size) / len); + a=allocate_array(size); + + for(last=0,e=0;e<size;e++) + { + pos=(INT32)((e+1)*len); + a->item[e].u.array=friendly_slice_array(sp[-2].u.array, + last, + pos); + last=pos; + } + a->item[e].u.array=slice_array(sp[-2].u.array, + last, + sp[2].u.array->size); + } + a->type_field=BIT_ARRAY; + pop_n_elems(2); + push_array(a); + break; + } + } + error("Division on different types.\n"); } @@ -1111,6 +1310,40 @@ void o_mod(void) if(call_lfun(LFUN_MOD, LFUN_RMOD)) return; + switch(TWO_TYPES(sp[-2].type,sp[-1].type)) + { + case TWO_TYPES(T_STRING,T_INT): + { + struct pike_string *s=sp[-2].u.string; + INT32 tmp,base; + if(!sp[-1].u.integer) + error("Modulo by zero.\n"); + + tmp=s->len % sp[-1].u.integer; + base=s->len<0 ? 0 : s->len - tmp; + s=make_shared_binary_string(s->str + base, tmp); + pop_n_elems(2); + push_string(s); + return; + } + + + case TWO_TYPES(T_ARRAY,T_INT): + { + struct array *a=sp[-2].u.array; + INT32 tmp,base; + if(!sp[-1].u.integer) + error("Modulo by zero.\n"); + + tmp=a->size % sp[-1].u.integer; + base=a->size<0 ? 0 : a->size - tmp; + a=slice_array(a,base,base+tmp); + pop_n_elems(2); + push_array(a); + return; + } + } + error("Modulo on different types.\n"); } @@ -1464,9 +1697,25 @@ void init_operators(void) add_efun2("`<<",f_lsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_lsh); add_efun2("`>>",f_rsh,SHIFT_TYPE,OPT_TRY_OPTIMIZE,0,generate_rsh); - add_efun2("`*",f_multiply,"!function(!object...:mixed)&function(mixed...:mixed)|function(array(array),array:array)|function(int...:int)|!function(int...:mixed)&function(float|int...:float)|function(string*,string:string)",OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); - - add_efun2("`/",f_divide,"function(mixed,object:mixed)|function(array,array:array(array))|function(object,mixed:mixed)|function(int,int:int)|function(float|int,float:float)|function(float,int:float)|function(string,string:string*)",OPT_TRY_OPTIMIZE,0,generate_divide); + add_efun2("`*",f_multiply, + "!function(!object...:mixed)&function(mixed...:mixed)|" + "function(array(array),array:array)|" + "function(int...:int)|" + "!function(int...:mixed)&function(float|int...:float)|" + "function(string*,string:string)|" + "function(array,int:array)|" + "function(string,int:string)", + OPT_TRY_OPTIMIZE,optimize_binary,generate_multiply); + + add_efun2("`/",f_divide, + "function(mixed,object:mixed)|" + "function(array,array|int|float:array(array))|" + "function(object,mixed:mixed)|" + "function(int,int:int)|" + "function(float|int,float:float)|" + "function(float,int:float)|" + "function(string,string|int|float:string*)", + OPT_TRY_OPTIMIZE,0,generate_divide); add_efun2("`%",f_mod,"function(mixed,object:mixed)|function(object,mixed:mixed)|function(int,int:int)|!function(int,int:mixed)&function(int|float,int|float:float)",OPT_TRY_OPTIMIZE,0,generate_mod);