diff --git a/src/array.c b/src/array.c index aee1a4f9e06212cee72a5038eab0a9e32da083ec..887ec3277ddcd93039a23b04870afd07de078c0d 100644 --- a/src/array.c +++ b/src/array.c @@ -23,7 +23,7 @@ #include "stuff.h" #include "bignum.h" -RCSID("$Id: array.c,v 1.92 2000/10/20 10:05:40 grubba Exp $"); +RCSID("$Id: array.c,v 1.93 2000/11/08 20:03:45 hubbe Exp $"); PMOD_EXPORT struct array empty_array= { @@ -404,9 +404,6 @@ PMOD_EXPORT struct array *array_remove(struct array *v,INT32 index) struct array *a; #ifdef PIKE_DEBUG - if(v->refs>1) - fatal("Array remove on array with many references.\n"); - if(index<0 || index >= v->size) fatal("Illegal argument to array_remove.\n"); #endif @@ -660,54 +657,121 @@ INT32 *get_order(struct array *v, cmpfun fun) return current_order; } -static int set_svalue_cmpfun(struct svalue *a, struct svalue *b) +static INLINE int set_svalue_cmpfun(struct svalue *a, struct svalue *b) { - INT32 tmp; - if((tmp=(a->type - b->type))) return tmp; - switch(a->type) + INT32 def,fun; + if(a->type == b->type) { - case T_FLOAT: - if(a->u.float_number < b->u.float_number) return -1; - if(a->u.float_number > b->u.float_number) return 1; - return 0; + switch(a->type) + { + case T_FLOAT: + if(a->u.float_number < b->u.float_number) return -1; + if(a->u.float_number > b->u.float_number) return 1; + return 0; + + case T_FUNCTION: + if(a->u.refs < b->u.refs) return -1; + if(a->u.refs > b->u.refs) return 1; + return a->subtype - b->subtype; + + case T_INT: + if(a->u.integer < b->u.integer) return -1; + if(a->u.integer > b->u.integer) return 1; + return 0; + + default: + if(a->u.refs < b->u.refs) return -1; + if(a->u.refs > b->u.refs) return 1; + return 0; - case T_FUNCTION: - if(a->u.refs < b->u.refs) return -1; - if(a->u.refs > b->u.refs) return 1; - return a->subtype - b->subtype; + case T_OBJECT: + if(a->u.object == b->u.object) return 0; + if(a->u.refs < b->u.refs) { def=-1; break; } + if(a->u.refs > b->u.refs) { def=1; break; } + def=0; + break; + } + }else{ + def=a->type - b->type; + } - case T_INT: - if(a->u.integer < b->u.integer) return -1; - if(a->u.integer > b->u.integer) return 1; + if(a->type == T_OBJECT && a->u.object->prog && + FIND_LFUN(a->u.object->prog,LFUN_LT) != -1) + { + push_svalue(b); + apply_lfun(a->u.object,LFUN_LT,1); + if(!IS_ZERO(sp-1)) + { + pop_stack(); + return -1; + }else{ + pop_stack(); + } + + push_svalue(b); + apply_lfun(a->u.object,LFUN_GT,1); + if(!IS_ZERO(sp-1)) + { + pop_stack(); + return 1; + }else{ + pop_stack(); + } return 0; + } - default: - if(a->u.refs < b->u.refs) return -1; - if(a->u.refs > b->u.refs) return 1; + if(b->type == T_OBJECT && b->u.object->prog && + FIND_LFUN(b->u.object->prog,LFUN_LT) != -1) + { + push_svalue(a); + apply_lfun(b->u.object,LFUN_LT,1); + if(!IS_ZERO(sp-1)) + { + pop_stack(); + return 1; + }else{ + pop_stack(); + } + + push_svalue(a); + apply_lfun(b->u.object,LFUN_GT,1); + if(!IS_ZERO(sp-1)) + { + pop_stack(); + return -1; + }else{ + pop_stack(); + } return 0; } + + return def; } static int switch_svalue_cmpfun(struct svalue *a, struct svalue *b) { - if(a->type != b->type) return a->type - b->type; - switch(a->type) + if(a->type == b->type) { - case T_INT: - if(a->u.integer < b->u.integer) return -1; - if(a->u.integer > b->u.integer) return 1; - return 0; - - case T_FLOAT: - if(a->u.float_number < b->u.float_number) return -1; - if(a->u.float_number > b->u.float_number) return 1; - return 0; - - case T_STRING: - return DO_NOT_WARN((int)my_quick_strcmp(a->u.string, b->u.string)); - - default: - return set_svalue_cmpfun(a,b); + switch(a->type) + { + case T_INT: + if(a->u.integer < b->u.integer) return -1; + if(a->u.integer > b->u.integer) return 1; + return 0; + + case T_FLOAT: + if(a->u.float_number < b->u.float_number) return -1; + if(a->u.float_number > b->u.float_number) return 1; + return 0; + + case T_STRING: + return DO_NOT_WARN((int)my_quick_strcmp(a->u.string, b->u.string)); + + default: + return set_svalue_cmpfun(a,b); + } + }else{ + return a->type - b->type; } } @@ -826,13 +890,18 @@ INT32 set_lookup(struct array *a, struct svalue *s) #ifdef PIKE_DEBUG if(d_flag > 1) array_check_type_field(a); #endif - /* face it, it's not there */ - if( (((2 << s->type) -1) & a->type_field) == 0) - return -1; + /* objects may have `< `> operators, evil stuff! */ + if(s->type != T_OBJECT && !(a->flags & BIT_OBJECT)) + { + /* face it, it's not there */ + if( (((2 << s->type) -1) & a->type_field) == 0) + return -1; + /* face it, it's not there */ - if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0) - return ~a->size; + if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0) + return ~a->size; + } return low_lookup(a,s,set_svalue_cmpfun); } @@ -843,12 +912,16 @@ INT32 switch_lookup(struct array *a, struct svalue *s) #ifdef PIKE_DEBUG if(d_flag > 1) array_check_type_field(a); #endif - if( (((2 << s->type) -1) & a->type_field) == 0) - return -1; + /* objects may have `< `> operators, evil stuff! */ + if(s->type != T_OBJECT && !(a->flags & BIT_OBJECT)) + { + if( (((2 << s->type) -1) & a->type_field) == 0) + return -1; - /* face it, it's not there */ - if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0) - return ~a->size; + /* face it, it's not there */ + if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0) + return ~a->size; + } return low_lookup(a,s,switch_svalue_cmpfun); } @@ -982,6 +1055,7 @@ union anything *array_get_item_ptr(struct array *a, */ INT32 * merge(struct array *a,struct array *b,INT32 opcode) { + ONERROR r; INT32 ap,bp,i,*ret,*ptr; ap=bp=0; @@ -1011,6 +1085,7 @@ INT32 * merge(struct array *a,struct array *b,INT32 opcode) } ptr=ret=(INT32 *)xalloc(sizeof(INT32)*(a->size + b->size + 1)); + SET_ONERROR(r, free,ret); ptr++; while(ap < a->size && bp < b->size) @@ -1034,6 +1109,8 @@ INT32 * merge(struct array *a,struct array *b,INT32 opcode) *ret = DO_NOT_WARN((INT32)(ptr-ret-1)); + UNSET_ONERROR(r); + return ret; } @@ -1169,6 +1246,7 @@ static int array_merge_fun(INT32 *a, INT32 *b) */ PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array *b,INT32 op) { + ONERROR r1,r2,r3; INT32 *zipper; struct array *tmpa,*tmpb,*ret; @@ -1176,21 +1254,27 @@ PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array * if(orderb) { free((char *)orderb); orderb=0; } ordera=get_set_order(a); + orderb=get_set_order(b); + tmpa=reorder_and_copy_array(a,ordera); + SET_ONERROR(r1,do_free_array,tmpa); - orderb=get_set_order(b); tmpb=reorder_and_copy_array(b,orderb); + SET_ONERROR(r2,do_free_array,tmpb); zipper=merge(tmpa,tmpb,op); + SET_ONERROR(r3,free,zipper); fsort((char *)(zipper+1),*zipper,sizeof(INT32),(fsortfun)array_merge_fun); - free((char *)ordera); + free((char *)orderb); + free((char *)ordera); orderb=ordera=0; + ret=array_zip(tmpa,tmpb,zipper); - free_array(tmpa); - free_array(tmpb); - free((char *)zipper); + UNSET_ONERROR(r3); free((char *)zipper); + UNSET_ONERROR(r2); free_array(tmpb); + UNSET_ONERROR(r1); free_array(tmpa); return ret; } @@ -1211,6 +1295,7 @@ PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array * */ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct array *b,INT32 op) { + ONERROR r1,r2,r3,r4,r5; INT32 ap,bp,i; struct svalue *arra,*arrb; struct array *ret; @@ -1223,12 +1308,16 @@ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct arr } #endif + SET_ONERROR(r1,do_free_array,a); + SET_ONERROR(r2,do_free_array,b); + if(a->refs==1 || !a->size) { arra=ITEM(a); }else{ arra=(struct svalue *)xalloc(a->size*sizeof(struct svalue)); MEMCPY(arra,ITEM(a),a->size*sizeof(struct svalue)); + SET_ONERROR(r3,free,arra); } if(b->refs==1 || !b->size) @@ -1237,12 +1326,14 @@ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct arr }else{ arrb=(struct svalue *)xalloc(b->size*sizeof(struct svalue)); MEMCPY(arrb,ITEM(b),b->size*sizeof(struct svalue)); + SET_ONERROR(r4,free,arrb); } set_sort_svalues(arra,arra+a->size-1); set_sort_svalues(arrb,arrb+b->size-1); ret=low_allocate_array(0,32); + SET_ONERROR(r5,do_free_array,ret); ap=bp=0; while(ap < a->size && bp < b->size) @@ -1269,12 +1360,26 @@ PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct arr while(bp<b->size) ret=append_array(ret,arrb + bp++); - if(arra != ITEM(a)) free((char *)arra); - if(arrb != ITEM(b)) free((char *)arrb); + UNSET_ONERROR(r5); - free_array(a); + if(arrb != ITEM(b)) + { + UNSET_ONERROR(r4); + free((char *)arrb); + } + + if(arra != ITEM(a)) + { + UNSET_ONERROR(r3); + free((char *)arra); + } + + UNSET_ONERROR(r2); free_array(b); + UNSET_ONERROR(r1); + free_array(a); + return ret; } @@ -1287,6 +1392,9 @@ PMOD_EXPORT struct array *merge_array_without_order(struct array *a, INT32 op) { #if 0 + /* FIXME: If this routine is ever reinstated, it has to be + * fixed to use ONERROR + */ INT32 *zipper; struct array *tmpa,*tmpb,*ret; @@ -1318,6 +1426,7 @@ PMOD_EXPORT struct array *merge_array_without_order(struct array *a, } /* subtract an array from another */ + PMOD_EXPORT struct array *subtract_arrays(struct array *a, struct array *b) { #ifdef PIKE_DEBUG diff --git a/src/docode.c b/src/docode.c index 8f4d879fd17025d84ac4240f8bc25fc3562992d6..0a3023e43094b1e035ac0bc86fd47a6a3ceacc96 100644 --- a/src/docode.c +++ b/src/docode.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: docode.c,v 1.83 2000/09/26 22:19:02 hubbe Exp $"); +RCSID("$Id: docode.c,v 1.84 2000/11/08 20:03:45 hubbe Exp $"); #include "las.h" #include "program.h" #include "pike_types.h" @@ -958,6 +958,10 @@ static int do_docode2(node *n, INT16 flags) #endif f_aggregate(cases); + + /* FIXME: get_switch_order might possibly be able to + * throw errors, add a catch around this! -Hubbe + */ order=get_switch_order(Pike_sp[-1].u.array); if (!Pike_compiler->num_parse_error) { diff --git a/src/encode.c b/src/encode.c index e199eba38e809356ab0fea7fa6fcd58cb5356a2e..48a11fd929ba06105e2f1bf8c826b6833bbca59f 100644 --- a/src/encode.c +++ b/src/encode.c @@ -25,7 +25,7 @@ #include "version.h" #include "bignum.h" -RCSID("$Id: encode.c,v 1.76 2000/10/04 05:12:12 hubbe Exp $"); +RCSID("$Id: encode.c,v 1.77 2000/11/08 20:03:45 hubbe Exp $"); /* #define ENCODE_DEBUG */ @@ -468,6 +468,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) /* This doesn't let bignums through. That's necessary as * long as they aren't handled deterministically by the * sort function. */ + /* They should be hanled deterministically now - Hubbe */ error("Canonical encoding requires basic types in indices.\n"); } order = get_switch_order(Pike_sp[-2].u.array); diff --git a/src/mapping.c b/src/mapping.c index 7d3368664b7461df0a1315fbbc0f49f1783685c2..ba9da14492e3f28d50f0ee937758cdb2028c2f41 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: mapping.c,v 1.110 2000/11/01 23:30:36 grubba Exp $"); +RCSID("$Id: mapping.c,v 1.111 2000/11/08 20:03:45 hubbe Exp $"); #include "main.h" #include "object.h" #include "mapping.h" @@ -1321,6 +1321,7 @@ PMOD_EXPORT struct mapping *copy_mapping(struct mapping *m) PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op) { + ONERROR r1,r2,r3,r4,r5; struct array *ai, *av; struct array *bi, *bv; struct array *ci, *cv; @@ -1335,7 +1336,11 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, #endif ai=mapping_indices(a); + SET_ONERROR(r1,do_free_array,ai); + av=mapping_values(a); + SET_ONERROR(r2,do_free_array,av); + if(ai->size > 1) { zipper=get_set_order(ai); @@ -1345,7 +1350,11 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, } bi=mapping_indices(b); + SET_ONERROR(r3,do_free_array,bi); + bv=mapping_values(b); + SET_ONERROR(r4,do_free_array,bv); + if(bi->size > 1) { zipper=get_set_order(bi); @@ -1357,13 +1366,15 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, zipper=merge(ai,bi,op); ci=array_zip(ai,bi,zipper); - free_array(ai); - free_array(bi); + + UNSET_ONERROR(r4); free_array(bi); + UNSET_ONERROR(r3); free_array(ai); cv=array_zip(av,bv,zipper); - free_array(av); - free_array(bv); - + + UNSET_ONERROR(r2); free_array(bv); + UNSET_ONERROR(r1); free_array(av); + free((char *)zipper); m=mkmapping(ci, cv); @@ -1376,13 +1387,16 @@ PMOD_EXPORT struct mapping *merge_mappings(struct mapping *a, struct mapping *b, PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a, struct array *b, INT32 op) { + ONERROR r1,r2; struct array *ai, *av; struct array *ci = NULL, *cv = NULL; INT32 *zipper = NULL; struct mapping *m; ai=mapping_indices(a); + SET_ONERROR(r1,do_free_array,ai); av=mapping_values(a); + SET_ONERROR(r2,do_free_array,av); if(ai->size > 1) { zipper=get_set_order(ai); @@ -1407,8 +1421,8 @@ PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a, fatal("merge_mapping_array on other than AND or SUB\n"); } - free_array(ai); - free_array(av); + UNSET_ONERROR(r2); free_array(av); + UNSET_ONERROR(r1); free_array(ai); free((char *)zipper); @@ -1422,6 +1436,7 @@ PMOD_EXPORT struct mapping *merge_mapping_array_ordered(struct mapping *a, PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a, struct array *b, INT32 op) { + ONERROR r1; struct array *b_temp; INT32 *zipper; struct mapping *m; @@ -1430,8 +1445,9 @@ PMOD_EXPORT struct mapping *merge_mapping_array_unordered(struct mapping *a, { zipper=get_set_order(b); b_temp=reorder_and_copy_array(b,zipper); + SET_ONERROR(r1,do_free_array,b_temp); m=merge_mapping_array_ordered(a,b_temp,op); - free_array(b_temp); + UNSET_ONERROR(r1); free_array(b_temp); } else m=merge_mapping_array_ordered(a,b,op); diff --git a/src/multiset.c b/src/multiset.c index d916baa318c26057f62d735798773567b896784a..e0510d29eed27034f7579f3552c0f29b5f30cd40 100644 --- a/src/multiset.c +++ b/src/multiset.c @@ -17,7 +17,7 @@ #include "gc.h" #include "security.h" -RCSID("$Id: multiset.c,v 1.28 2000/09/14 19:58:43 mast Exp $"); +RCSID("$Id: multiset.c,v 1.29 2000/11/08 20:03:46 hubbe Exp $"); struct multiset *first_multiset; @@ -26,7 +26,11 @@ static struct multiset *gc_mark_multiset_pos = 0; PMOD_EXPORT int multiset_member(struct multiset *l, struct svalue *ind) { - return set_lookup(l->ind, ind) >= 0; + int i; + add_ref(l->ind); + i=set_lookup(l->ind, ind) >= 0; + free_array(l->ind); + return i; } /* @@ -77,17 +81,51 @@ PMOD_EXPORT void do_free_multiset(struct multiset *l) free_multiset(l); } +#define BEGIN() do{ \ + struct array *ind=l->ind; \ + struct array *ind_bak=ind; \ + if(ind->refs > 1) \ + { \ + ind=copy_array(l->ind); \ + free_array(l->ind); \ + l->ind=ind; \ + } \ + add_ref(ind) + +#define END() \ + if(l->ind == ind_bak) \ + { \ + free_array(l->ind); \ + l->ind=ind; \ + }else{ \ + free_array(ind); \ + } \ +}while(0) + PMOD_EXPORT void order_multiset(struct multiset *l) { INT32 *order; int flags; if(l->ind->size < 2) return; - order = get_set_order(l->ind); - flags = l->ind->flags; - l->ind = order_array(l->ind, order); - l->ind->flags = flags; + + BEGIN(); + +#if 0 + + order = get_set_order(ind); + flags = ind->flags; + ind = order_array(ind, order); + ind->flags = flags; free((char *)order); +#else + { + extern void set_sort_svalues(struct svalue *, struct svalue *); + set_sort_svalues(ITEM(ind),ITEM(ind)+ind->size-1); + } +#endif + + END(); } PMOD_EXPORT struct multiset *mkmultiset(struct array *ind) @@ -99,16 +137,18 @@ PMOD_EXPORT struct multiset *mkmultiset(struct array *ind) } PMOD_EXPORT void multiset_insert(struct multiset *l, - struct svalue *ind) + struct svalue *v) { INT32 i; - i=set_lookup(l->ind, ind); + BEGIN(); + i=set_lookup(ind, v); if(i < 0) { - int flags = l->ind->flags; - l->ind=array_insert(l->ind, ind, ~i); - l->ind->flags = flags; + int flags = ind->flags; + ind=array_insert(ind, v, ~i); + ind->flags = flags; } + END(); } #if 0 @@ -118,27 +158,33 @@ struct array *multiset_indices(struct multiset *l) } #endif -PMOD_EXPORT void multiset_delete(struct multiset *l,struct svalue *ind) +PMOD_EXPORT void multiset_delete(struct multiset *l,struct svalue *v) { INT32 i; - i=set_lookup(l->ind, ind); + BEGIN(); + i=set_lookup(ind, v); if(i >= 0) { - int flags = l->ind->flags; - l->ind=array_remove(l->ind, i); - l->ind->flags = flags; + int flags = ind->flags; + ind=array_remove(ind, i); + ind->flags = flags; } + END(); } PMOD_EXPORT void check_multiset_for_destruct(struct multiset *l) { /* Horrifying worst case!!!!! */ INT32 i; - int flags = l->ind->flags; - while( (i=array_find_destructed_object(l->ind)) >= 0) - l->ind=array_remove(l->ind, i); - l->ind->flags = flags; + BEGIN(); + { + int flags = ind->flags; + while( (i=array_find_destructed_object(ind)) >= 0) + ind=array_remove(ind, i); + ind->flags = flags; + } + END(); } PMOD_EXPORT struct multiset *copy_multiset(struct multiset *tmp)