06983f1996-09-22Fredrik Hübinette (Hubbe) /*\ ||| This file a part of Pike, and is copyright by Fredrik Hubinette ||| Pike is distributed as GPL (General Public License) ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" #include "array.h" #include "multiset.h" #include "svalue.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) #include "error.h" #include "dynamic_buffer.h" #include "interpret.h" #include "builtin_functions.h" #include "gc.h"
7e97c31999-01-21Fredrik Hübinette (Hubbe) #include "security.h"
06983f1996-09-22Fredrik Hübinette (Hubbe) 
3619041999-10-29Martin Stjernholm RCSID("$Id: multiset.c,v 1.16 1999/10/29 03:36:48 mast Exp $");
24ddc71998-03-28Henrik Grubbström (Grubba) 
06983f1996-09-22Fredrik Hübinette (Hubbe) struct multiset *first_multiset; int multiset_member(struct multiset *l, struct svalue *ind) { return set_lookup(l->ind, ind) >= 0; } /* * allocate and init a new multiset */
1a3e1b1999-04-13Fredrik Hübinette (Hubbe) struct multiset *allocate_multiset(struct array *ind)
06983f1996-09-22Fredrik Hübinette (Hubbe) { struct multiset *l; GC_ALLOC(); l=ALLOC_STRUCT(multiset); l->next = first_multiset; l->prev = 0; l->refs = 1; l->ind=ind; if(first_multiset) first_multiset->prev = l; first_multiset=l;
7e97c31999-01-21Fredrik Hübinette (Hubbe)  INITIALIZE_PROT(l);
06983f1996-09-22Fredrik Hübinette (Hubbe)  return l; } /* * free a multiset */ void really_free_multiset(struct multiset *l) {
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(l->refs) fatal("really free multiset on multiset with nonzero refs.\n"); #endif free_array(l->ind);
7e97c31999-01-21Fredrik Hübinette (Hubbe)  FREE_PROT(l);
06983f1996-09-22Fredrik Hübinette (Hubbe) 
4d58591996-12-04Fredrik Hübinette (Hubbe)  if(l->prev) l->prev->next = l->next; else first_multiset = l->next;
06983f1996-09-22Fredrik Hübinette (Hubbe) 
4d58591996-12-04Fredrik Hübinette (Hubbe)  if(l->next) l->next->prev = l->prev;
06983f1996-09-22Fredrik Hübinette (Hubbe)  free((char *)l); GC_FREE(); }
1a3e1b1999-04-13Fredrik Hübinette (Hubbe)  void order_multiset(struct multiset *l)
06983f1996-09-22Fredrik Hübinette (Hubbe) { INT32 *order;
3619041999-10-29Martin Stjernholm  int flags;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(l->ind->size < 2) return;
06983f1996-09-22Fredrik Hübinette (Hubbe)  order = get_set_order(l->ind);
3619041999-10-29Martin Stjernholm  flags = l->ind->flags;
06983f1996-09-22Fredrik Hübinette (Hubbe)  l->ind = order_array(l->ind, order);
3619041999-10-29Martin Stjernholm  l->ind->flags = flags;
06983f1996-09-22Fredrik Hübinette (Hubbe)  free((char *)order); } struct multiset *mkmultiset(struct array *ind) { struct multiset *l; l=allocate_multiset(copy_array(ind)); order_multiset(l); return l; } void multiset_insert(struct multiset *l, struct svalue *ind) { INT32 i; i=set_lookup(l->ind, ind); if(i < 0) {
3619041999-10-29Martin Stjernholm  int flags = l->ind->flags;
06983f1996-09-22Fredrik Hübinette (Hubbe)  l->ind=array_insert(l->ind, ind, ~i);
3619041999-10-29Martin Stjernholm  l->ind->flags = flags;
06983f1996-09-22Fredrik Hübinette (Hubbe)  } } #if 0 struct array *multiset_indices(struct multiset *l) { return l->ind; } #endif void multiset_delete(struct multiset *l,struct svalue *ind) { INT32 i; i=set_lookup(l->ind, ind);
3619041999-10-29Martin Stjernholm  if(i >= 0) { int flags = l->ind->flags; l->ind=array_remove(l->ind, i); l->ind->flags = flags; }
06983f1996-09-22Fredrik Hübinette (Hubbe) } void check_multiset_for_destruct(struct multiset *l) {
3619041999-10-29Martin Stjernholm /* Horrifying worst case!!!!! */
06983f1996-09-22Fredrik Hübinette (Hubbe)  INT32 i;
3619041999-10-29Martin Stjernholm  int flags = l->ind->flags;
06983f1996-09-22Fredrik Hübinette (Hubbe)  while( (i=array_find_destructed_object(l->ind)) >= 0) l->ind=array_remove(l->ind, i);
3619041999-10-29Martin Stjernholm  l->ind->flags = flags;
06983f1996-09-22Fredrik Hübinette (Hubbe) } struct multiset *copy_multiset(struct multiset *tmp) { check_multiset_for_destruct(tmp); return allocate_multiset(copy_array(tmp->ind)); } struct multiset *merge_multisets(struct multiset *a, struct multiset *b, INT32 operator) { struct multiset *ret; INT32 *zipper; check_multiset_for_destruct(a); check_multiset_for_destruct(b); zipper=merge(a->ind,b->ind,operator); ret=allocate_multiset(array_zip(a->ind,b->ind,zipper)); free((char *)zipper); return ret; } struct multiset *add_multisets(struct svalue *argp,INT32 args) { struct multiset *ret,*a,*b; switch(args) { case 0: ret=allocate_multiset(allocate_array_no_init(0,0)); break; case 1: ret=copy_multiset(argp->u.multiset); break; case 2:
71f3a21998-11-22Fredrik Hübinette (Hubbe)  ret=merge_multisets(argp[0].u.multiset,argp[1].u.multiset,PIKE_ARRAY_OP_ADD);
06983f1996-09-22Fredrik Hübinette (Hubbe)  break; case 3:
71f3a21998-11-22Fredrik Hübinette (Hubbe)  a=merge_multisets(argp[0].u.multiset, argp[1].u.multiset, PIKE_ARRAY_OP_ADD); ret=merge_multisets(a, argp[2].u.multiset, PIKE_ARRAY_OP_ADD);
06983f1996-09-22Fredrik Hübinette (Hubbe)  free_multiset(a); break; default: a=add_multisets(argp,args/2); b=add_multisets(argp+args/2,args-args/2);
71f3a21998-11-22Fredrik Hübinette (Hubbe)  ret=merge_multisets(a,b,PIKE_ARRAY_OP_ADD);
06983f1996-09-22Fredrik Hübinette (Hubbe)  free_multiset(a); free_multiset(b); break; } return ret; } int multiset_equal_p(struct multiset *a, struct multiset *b, struct processing *p) { if(a == b) return 1; check_multiset_for_destruct(a); return array_equal_p(a->ind, b->ind, p); } void describe_multiset(struct multiset *l,struct processing *p,int indent) { struct processing doing; int e; char buf[40]; if(!l->ind->size) { my_strcat("(< >)"); return; } doing.next=p; doing.pointer_a=(void *)l; for(e=0;p;e++,p=p->next) { if(p->pointer_a == (void *)l) { sprintf(buf,"@%d",e); my_strcat(buf); return; } }
93c8a61999-09-24Fredrik Noring  sprintf(buf, l->ind->size == 1 ? "(< /* %ld element */\n" : "(< /* %ld elements */\n", (long)l->ind->size);
06983f1996-09-22Fredrik Hübinette (Hubbe)  my_strcat(buf); describe_array_low(l->ind,&doing,indent); my_putchar('\n'); for(e=2; e<indent; e++) my_putchar(' '); my_strcat(">)"); } node * make_node_from_multiset(struct multiset *l) { if(check_that_array_is_constant(l->ind)) { struct svalue s; s.type=T_MULTISET; s.subtype=0; s.u.multiset=l; return mkconstantsvaluenode(&s); }else{ return mkefuncallnode("mkmultiset",make_node_from_array(l->ind)); } } void f_aggregate_multiset(INT32 args) { struct multiset *l; f_aggregate(args); l=allocate_multiset(sp[-1].u.array); order_multiset(l); sp[-1].type=T_MULTISET; sp[-1].u.multiset=l; } struct multiset *copy_multiset_recursively(struct multiset *l, struct processing *p) { struct processing doing; struct multiset *ret; doing.next=p; doing.pointer_a=(void *)l; for(;p;p=p->next) { if(p->pointer_a == (void *)l) { ret=(struct multiset *)p->pointer_b;
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(ret);
06983f1996-09-22Fredrik Hübinette (Hubbe)  return ret; } } ret=allocate_multiset( & empty_array ); doing.pointer_b=(void *)ret; ret->ind=copy_array_recursively(l->ind,&doing); order_multiset(ret); return ret; } void gc_mark_multiset_as_referenced(struct multiset *l) { if(gc_mark(l)) gc_mark_array_as_referenced(l->ind); }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_check_all_multisets(void)
06983f1996-09-22Fredrik Hübinette (Hubbe) { struct multiset *l; for(l=first_multiset;l;l=l->next) gc_check(l->ind); }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_mark_all_multisets(void)
06983f1996-09-22Fredrik Hübinette (Hubbe) { struct multiset *l; for(l=first_multiset;l;l=l->next) if(gc_is_referenced(l)) gc_mark_multiset_as_referenced(l); }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_free_all_unreferenced_multisets(void)
06983f1996-09-22Fredrik Hübinette (Hubbe) { struct multiset *l,*next; for(l=first_multiset;l;l=next) { if(gc_do_free(l)) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(l);
06983f1996-09-22Fredrik Hübinette (Hubbe)  free_svalues(ITEM(l->ind), l->ind->size, l->ind->type_field); l->ind->size=0; next=l->next; free_multiset(l); }else{ next=l->next; } } }
c3c7031996-12-04Fredrik Hübinette (Hubbe) void count_memory_in_multisets(INT32 *num_, INT32 *size_) { struct multiset *m; INT32 size=0, num=0; for(m=first_multiset;m;m=m->next) { num++; size+=sizeof(struct multiset); } *num_=num; *size_=size; }
61e9a01998-01-25Fredrik Hübinette (Hubbe)