cb22561995-10-11Fredrik Hübinette (Hubbe) /*\
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)
cb22561995-10-11Fredrik Hübinette (Hubbe) ||| See the files COPYING and DISCLAIMER for more information. \*/
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "global.h"
d6ac731998-04-20Henrik Grubbström (Grubba) RCSID("$Id: mapping.c,v 1.29 1998/04/20 18:53:17 grubba Exp $");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #include "main.h" #include "object.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "mapping.h" #include "svalue.h" #include "array.h"
bb55f81997-03-16Fredrik Hübinette (Hubbe) #include "pike_macros.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "language.h" #include "error.h"
9aa6fa1997-05-19Fredrik Hübinette (Hubbe) #include "pike_memory.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) #include "dynamic_buffer.h" #include "interpret.h"
515b6c1996-06-09Fredrik Hübinette (Hubbe) #include "las.h"
c94c371996-03-28Fredrik Hübinette (Hubbe) #include "gc.h"
5588271998-01-13Henrik Grubbström (Grubba) #include "stralloc.h"
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe) #define AVG_LINK_LENGTH 4 #define MIN_LINK_LENGTH 1
9076fa1997-02-17Fredrik Hübinette (Hubbe) #define MAP_SLOTS(X) ((X)?((X)+((X)>>4)+8):0)
515b6c1996-06-09Fredrik Hübinette (Hubbe) #define LOOP(m) for(e=0;e<m->hashsize;e++) for(k=m->hash[e];k;k=k->next) struct keypair { struct keypair *next; struct svalue ind, val; };
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *first_mapping;
06983f1996-09-22Fredrik Hübinette (Hubbe)  #ifdef DEBUG /* This function checks that the type field isn't lacking any bits. * It is used for debugging purposes only.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
06983f1996-09-22Fredrik Hübinette (Hubbe) static void check_mapping_type_fields(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k,**prev; TYPE_FIELD ind_types, val_types; ind_types=val_types=0;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  LOOP(m)
06983f1996-09-22Fredrik Hübinette (Hubbe)  { val_types |= 1 << k->val.type; ind_types |= 1 << k->ind.type; } if(val_types & ~(m->val_types)) fatal("Mapping value types out of order!\n"); if(ind_types & ~(m->ind_types)) fatal("Mapping indices types out of order!\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe)  /* This function allocates the hash table and svalue space for a mapping * struct. The size is the max number of indices that can fit in the * allocated space.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
515b6c1996-06-09Fredrik Hübinette (Hubbe) static void init_mapping(struct mapping *m, INT32 size) { char *tmp; INT32 e; INT32 hashsize,hashspace; #ifdef DEBUG if(size < 0) fatal("init_mapping with negative value.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(size) { hashsize=size / AVG_LINK_LENGTH + 1; if(!(hashsize & 1)) hashsize++; hashspace=hashsize+1; e=sizeof(struct keypair)*size+ sizeof(struct keypair *)*hashspace; tmp=(char *)xalloc(e); m->hash=(struct keypair **) tmp; m->hashsize=hashsize; tmp+=sizeof(struct keypair *)*hashspace; MEMSET((char *)m->hash, 0, sizeof(struct keypair *) * m->hashsize); m->free_list=(struct keypair *) tmp; for(e=1;e<size;e++) m->free_list[e-1].next = m->free_list + e; m->free_list[e-1].next=0; }else{ m->hashsize=0; m->hash=0; m->free_list=0; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m->ind_types = 0; m->val_types = 0; m->size = 0; }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function allocates an empty mapping with room for 'size' values
5267b71995-08-09Fredrik Hübinette (Hubbe)  */
14dae91997-01-26Fredrik Hübinette (Hubbe) struct mapping *allocate_mapping(int size)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  GC_ALLOC();
5267b71995-08-09Fredrik Hübinette (Hubbe)  m=ALLOC_STRUCT(mapping);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  init_mapping(m,size);
5267b71995-08-09Fredrik Hübinette (Hubbe)  m->next = first_mapping; m->prev = 0; m->refs = 1;
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(first_mapping) first_mapping->prev = m; first_mapping=m; return m; }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function should only be called by the free_mapping() macro. * It frees the storate used by the mapping.
5267b71995-08-09Fredrik Hübinette (Hubbe)  */ void really_free_mapping(struct mapping *m) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef DEBUG if(m->refs) fatal("really free mapping on mapping with nonzero refs.\n"); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  LOOP(m) { free_svalue(& k->val); free_svalue(& k->ind); } if(m->prev) m->prev->next = m->next; else first_mapping = m->next;
5267b71995-08-09Fredrik Hübinette (Hubbe)  if(m->next) m->next->prev = m->prev;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(m->hash) free((char *)m->hash);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free((char *)m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  GC_FREE();
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function is used to rehash a mapping without loosing the internal * order in each hash chain. This is to prevent mappings from becoming * very inefficient just after being rehashed. */
515b6c1996-06-09Fredrik Hübinette (Hubbe) static void mapping_rehash_backwards(struct mapping *m, struct keypair *p)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  unsigned INT32 h; struct keypair *tmp; if(!p) return; mapping_rehash_backwards(m,p->next); h=hash_svalue(& p->ind) % m->hashsize; tmp=m->free_list; m->free_list=tmp->next; tmp->next=m->hash[h]; m->hash[h]=tmp; tmp->ind=p->ind; tmp->val=p->val; m->size++; m->ind_types |= 1 << p->ind.type; m->val_types |= 1 << p->val.type;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function re-allocates a mapping. It adjusts the max no. of * values can be fitted into the mapping. It takes a bit of time to * run, but is used seldom enough not to degrade preformance significantly. */
515b6c1996-06-09Fredrik Hübinette (Hubbe) static struct mapping *rehash(struct mapping *m, int new_size)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe) #ifdef DEBUG INT32 tmp=m->size; #endif INT32 e,hashsize; struct keypair *k,**hash; hashsize=m->hashsize; hash=m->hash; init_mapping(m, new_size);
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(hash) { for(e=0;e<hashsize;e++) mapping_rehash_backwards(m, hash[e]); free((char *)hash); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  #ifdef DEBUG
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(m->size != tmp) fatal("Rehash failed, size not same any more.\n");
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  return m; }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function brings the type fields in the mapping up to speed. * I only use it when the type fields MUST be correct, which is not * very often. */
515b6c1996-06-09Fredrik Hübinette (Hubbe) void mapping_fix_type_field(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k; TYPE_FIELD ind_types, val_types; val_types = ind_types = 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
9076fa1997-02-17Fredrik Hübinette (Hubbe)  LOOP(m)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { val_types |= 1 << k->val.type; ind_types |= 1 << k->ind.type; } #ifdef DEBUG if(val_types & ~(m->val_types)) fatal("Mapping value types out of order!\n"); if(ind_types & ~(m->ind_types)) fatal("Mapping indices types out of order!\n"); #endif m->val_types = val_types; m->ind_types = ind_types;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
06983f1996-09-22Fredrik Hübinette (Hubbe) /* This function inserts key:val into the mapping m. * Same as doing m[key]=val; in pike. */
515b6c1996-06-09Fredrik Hübinette (Hubbe) void mapping_insert(struct mapping *m, struct svalue *key, struct svalue *val)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  unsigned INT32 h,h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); if(m->hashsize) { h=h2 % m->hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  #ifdef DEBUG
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(m->ind_types & (1 << key->type))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  for(prev= m->hash + h;(k=*prev);prev=&k->next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(is_eq(& k->ind, key)) { *prev=k->next; k->next=m->hash[h]; m->hash[h]=k; m->val_types |= 1 << val->type; assign_svalue(& k->val, val);
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  return; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } }
9076fa1997-02-17Fredrik Hübinette (Hubbe)  }else{ h=0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(!(k=m->free_list)) {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  rehash(m, m->size * 2 + 2); h=h2 % m->hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  k=m->free_list; } m->free_list=k->next; k->next=m->hash[h]; m->hash[h]=k; m->ind_types |= 1 << key->type; m->val_types |= 1 << val->type; assign_svalue_no_free(& k->ind, key); assign_svalue_no_free(& k->val, val); m->size++;
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) union anything *mapping_get_item_ptr(struct mapping *m, struct svalue *key, TYPE_T t)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  unsigned INT32 h, h2;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k, **prev;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  h2=hash_svalue(key); if(m->hashsize) { h=h2 % m->hashsize;
06983f1996-09-22Fredrik Hübinette (Hubbe)  #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe) 
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  for(prev= m->hash + h;(k=*prev);prev=&k->next)
9076fa1997-02-17Fredrik Hübinette (Hubbe)  { if(is_eq(& k->ind, key)) { *prev=k->next; k->next=m->hash[h]; m->hash[h]=k; if(k->val.type == t) return & ( k->val.u );
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
06983f1996-09-22Fredrik Hübinette (Hubbe) #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  return 0; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
9076fa1997-02-17Fredrik Hübinette (Hubbe)  }else{ h=0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
9076fa1997-02-17Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(!(k=m->free_list)) {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  rehash(m, m->size * 2 + 2); h=h2 % m->hashsize;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  k=m->free_list; } m->free_list=k->next; k->next=m->hash[h]; m->hash[h]=k; assign_svalue_no_free(& k->ind, key); k->val.type=T_INT; k->val.subtype=NUMBER_NUMBER; k->val.u.integer=0; m->ind_types |= 1 << key->type; m->val_types |= BIT_INT; m->size++; if(t != T_INT) return 0;
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe)  return & ( k->val.u );
515b6c1996-06-09Fredrik Hübinette (Hubbe) } void map_delete(struct mapping *m, struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  unsigned INT32 h; struct keypair *k, **prev;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(!m->size) return;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  h=hash_svalue(key) % m->hashsize;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  for(prev= m->hash + h;(k=*prev);prev=&k->next)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(is_eq(& k->ind, key)) { *prev=k->next; free_svalue(& k->ind); free_svalue(& k->val); k->next=m->free_list; m->free_list=k; m->size--; if(m->size < (m->hashsize + 1) * MIN_LINK_LENGTH) rehash(m, MAP_SLOTS(m->size));
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  } } void check_mapping_for_destruct(struct mapping *m) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k, **prev; TYPE_FIELD ind_types, val_types; #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(!m->size) return;
4ab0aa1996-09-23Fredrik Hübinette (Hubbe)  if((m->ind_types | m->val_types) & (BIT_OBJECT | BIT_FUNCTION))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  val_types = ind_types = 0;
06983f1996-09-22Fredrik Hübinette (Hubbe)  m->val_types |= BIT_INT;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  for(e=0;e<m->hashsize;e++) {
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  for(prev= m->hash + e;(k=*prev);)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { check_destructed(& k->val);
4ab0aa1996-09-23Fredrik Hübinette (Hubbe)  if((k->ind.type == T_OBJECT || k->ind.type == T_FUNCTION) && !k->ind.u.object->prog)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { *prev=k->next; free_svalue(& k->ind); free_svalue(& k->val); k->next=m->free_list; m->free_list=k; m->size--; }else{ val_types |= 1 << k->val.type; ind_types |= 1 << k->ind.type;
cb859e1996-09-23Fredrik Hübinette (Hubbe)  prev=&k->next;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } } if(MAP_SLOTS(m->size) < m->hashsize * MIN_LINK_LENGTH) rehash(m, MAP_SLOTS(m->size)); m->val_types = val_types; m->ind_types = ind_types; #ifdef DEBUG
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(d_flag > 1) check_mapping_type_fields(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe)  } }
06983f1996-09-22Fredrik Hübinette (Hubbe) struct svalue *low_mapping_lookup(struct mapping *m, struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  unsigned INT32 h; struct keypair *k, **prev; #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(!m->size) return 0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if((1 << key->type) & m->ind_types)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  h=hash_svalue(key) % m->hashsize;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  for(prev= m->hash + h;(k=*prev);prev=&k->next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { if(is_eq(& k->ind, key)) { *prev=k->next; k->next=m->hash[h]; m->hash[h]=k; return &k->val; } }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return 0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
14dae91997-01-26Fredrik Hübinette (Hubbe) struct svalue *low_mapping_string_lookup(struct mapping *m, struct pike_string *p) { struct svalue tmp; tmp.type=T_STRING; tmp.u.string=p; return low_mapping_lookup(m, &tmp); }
85f59e1998-01-08Fredrik Hübinette (Hubbe) struct svalue *simple_mapping_string_lookup(struct mapping *m, char *p) { struct pike_string *tmp; if((tmp=findstring(p))) return low_mapping_string_lookup(m,tmp); return 0; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) void mapping_index_no_free(struct svalue *dest, struct mapping *m, struct svalue *key)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct svalue *p;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((p=low_mapping_lookup(m,key)))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(p->type==T_INT) p->subtype=NUMBER_NUMBER;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  assign_svalue_no_free(dest, p); }else{ dest->type=T_INT; dest->u.integer=0; dest->subtype=NUMBER_UNDEFINED; }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) struct array *mapping_indices(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct array *a; struct svalue *s; struct keypair *k; a=allocate_array(m->size); s=ITEM(a); LOOP(m) assign_svalue(s++, & k->ind); a->type_field = m->ind_types;
06983f1996-09-22Fredrik Hübinette (Hubbe) #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return a; } struct array *mapping_values(struct mapping *m) { INT32 e; struct keypair *k; struct array *a; struct svalue *s; a=allocate_array(m->size); s=ITEM(a);
06983f1996-09-22Fredrik Hübinette (Hubbe)  LOOP(m) assign_svalue(s++, & k->val);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  a->type_field = m->val_types;
06983f1996-09-22Fredrik Hübinette (Hubbe)  #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return a; }
2043ba1998-02-10Fredrik Hübinette (Hubbe) struct array *mapping_to_array(struct mapping *m) { INT32 e; struct keypair *k; struct array *a; struct svalue *s; a=allocate_array(m->size); s=ITEM(a); LOOP(m) { struct array *b=allocate_array(2); assign_svalue(b->item+0, & k->ind); assign_svalue(b->item+1, & k->val); s->u.array=b; s->type=T_ARRAY; } a->type_field = BIT_ARRAY; return a; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) void mapping_replace(struct mapping *m,struct svalue *from, struct svalue *to) { INT32 e; struct keypair *k; LOOP(m) if(is_eq(& k->val, from)) assign_svalue(& k->val, to); m->val_types |= 1 << to->type;
06983f1996-09-22Fredrik Hübinette (Hubbe)  #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m); #endif
515b6c1996-06-09Fredrik Hübinette (Hubbe) } struct mapping *mkmapping(struct array *ind, struct array *val) { struct mapping *m; struct svalue *i,*v; INT32 e; #ifdef DEBUG if(ind->size != val->size) fatal("mkmapping on different sized arrays.\n"); #endif m=allocate_mapping(MAP_SLOTS(ind->size)); i=ITEM(ind); v=ITEM(val); for(e=0;e<ind->size;e++) mapping_insert(m, i++, v++); return m; } struct mapping *copy_mapping(struct mapping *m) { INT32 e; struct mapping *n; struct keypair *k; n=allocate_mapping(MAP_SLOTS(m->size));
06983f1996-09-22Fredrik Hübinette (Hubbe)  LOOP(m) mapping_insert(n, &k->ind, &k->val);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
36ce9c1996-10-08Fredrik Hübinette (Hubbe)  return n;
515b6c1996-06-09Fredrik Hübinette (Hubbe) } struct mapping *merge_mappings(struct mapping *a, struct mapping *b, INT32 op) { struct array *ai, *av; struct array *bi, *bv; struct array *ci, *cv;
5267b71995-08-09Fredrik Hübinette (Hubbe)  INT32 *zipper;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct mapping *m;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ai=mapping_indices(a); av=mapping_values(a);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(ai->size > 1) { zipper=get_set_order(ai); order_array(ai, zipper); order_array(av, zipper); free((char *)zipper); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  bi=mapping_indices(b); bv=mapping_values(b);
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(bi->size > 1) { zipper=get_set_order(bi); order_array(bi, zipper); order_array(bv, zipper); free((char *)zipper); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  zipper=merge(ai,bi,op);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ci=array_zip(ai,bi,zipper); free_array(ai); free_array(bi);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  cv=array_zip(av,bv,zipper); free_array(av); free_array(bv);
5267b71995-08-09Fredrik Hübinette (Hubbe)  free((char *)zipper);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m=mkmapping(ci, cv); free_array(ci); free_array(cv); return m;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) struct mapping *add_mappings(struct svalue *argp, INT32 args)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *ret,*a,*b; switch(args) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  case 0: return allocate_mapping(0); case 1: return copy_mapping(argp->u.mapping); case 2: return merge_mappings(argp[0].u.mapping, argp[1].u.mapping, OP_ADD);
5267b71995-08-09Fredrik Hübinette (Hubbe)  case 3: a=merge_mappings(argp[0].u.mapping,argp[1].u.mapping,OP_ADD); ret=merge_mappings(a,argp[2].u.mapping,OP_ADD); free_mapping(a);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe)  default: a=add_mappings(argp,args/2); b=add_mappings(argp+args/2,args-args/2); ret=merge_mappings(a,b,OP_ADD); free_mapping(a); free_mapping(b);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe)  } } int mapping_equal_p(struct mapping *a, struct mapping *b, struct processing *p) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct processing curr; struct keypair *k; INT32 e; if(a==b) return 1; if(a->size != b->size) return 0; curr.pointer_a = a; curr.pointer_b = b; curr.next = p; for( ;p ;p=p->next) if(p->pointer_a == (void *)a && p->pointer_b == (void *)b) return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe)  check_mapping_for_destruct(a); check_mapping_for_destruct(b);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  LOOP(a) { struct svalue *s;
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  if((s=low_mapping_lookup(b, & k->ind)))
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { if(!low_is_equal(s, &k->val, &curr)) return 0; }else{ return 0; } } return 1;
5267b71995-08-09Fredrik Hübinette (Hubbe) } void describe_mapping(struct mapping *m,struct processing *p,int indent) { struct processing doing;
61e9a01998-01-25Fredrik Hübinette (Hubbe)  INT32 e,d,q;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe)  char buf[40];
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(! m->size)
5267b71995-08-09Fredrik Hübinette (Hubbe)  { my_strcat("([ ])"); return; } doing.next=p; doing.pointer_a=(void *)m; for(e=0;p;e++,p=p->next) { if(p->pointer_a == (void *)m) {
f90e541995-08-17Fredrik Hübinette (Hubbe)  sprintf(buf,"@%ld",(long)e);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_strcat(buf); return; } }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  sprintf(buf,"([ /* %ld elements */\n",(long) m->size);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_strcat(buf);
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
61e9a01998-01-25Fredrik Hübinette (Hubbe)  q=0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  LOOP(m)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  if(q)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  my_putchar(','); my_putchar('\n');
36ce9c1996-10-08Fredrik Hübinette (Hubbe)  } else {
61e9a01998-01-25Fredrik Hübinette (Hubbe)  q=1;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
5267b71995-08-09Fredrik Hübinette (Hubbe)  for(d=0; d<indent; d++) my_putchar(' ');
515b6c1996-06-09Fredrik Hübinette (Hubbe)  describe_svalue(& k->ind, indent+2, p);
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_putchar(':');
515b6c1996-06-09Fredrik Hübinette (Hubbe)  describe_svalue(& k->val, indent+2, p);
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe)  my_putchar('\n'); for(e=2; e<indent; e++) my_putchar(' '); my_strcat("])"); } node * make_node_from_mapping(struct mapping *m) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k; INT32 e; mapping_fix_type_field(m); if((m->ind_types | m->val_types) & (BIT_FUNCTION | BIT_OBJECT))
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct array *ind, *val; node *n; ind=mapping_indices(m);
69d94d1997-04-23Fredrik Hübinette (Hubbe)  val=mapping_values(m);
3c04e81997-03-13Fredrik Hübinette (Hubbe)  n=mkefuncallnode("mkmapping", mknode(F_ARG_LIST, make_node_from_array(ind), make_node_from_array(val)));
515b6c1996-06-09Fredrik Hübinette (Hubbe)  free_array(ind); free_array(val); return n; }else{
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct svalue s;
3c04e81997-03-13Fredrik Hübinette (Hubbe)  if(!m->size) return mkefuncallnode("aggregate_mapping",0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  s.type=T_MAPPING; s.subtype=0; s.u.mapping=m; return mkconstantsvaluenode(&s); } } void f_m_delete(INT32 args) { if(args < 2) error("Too few arguments to m_delete.\n"); if(sp[-args].type != T_MAPPING)
fe3dd11997-09-08Henrik Grubbström (Grubba)  error("Bad argument 1 to m_delete.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe)  map_delete(sp[-args].u.mapping,sp+1-args); pop_n_elems(args-1); } void f_aggregate_mapping(INT32 args) { INT32 e;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe)  struct mapping *m; if(args & 1)
24697f1997-03-12Henrik Grubbström (Grubba)  error("Uneven number of arguments to aggregate_mapping.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  m=allocate_mapping(MAP_SLOTS(args / 2));
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  for(e=-args;e<0;e+=2) mapping_insert(m, sp+e, sp+e+1); pop_n_elems(args); push_mapping(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) } struct mapping *copy_mapping_recursively(struct mapping *m, struct processing *p) { struct processing doing; struct mapping *ret;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  INT32 e; struct keypair *k;
5267b71995-08-09Fredrik Hübinette (Hubbe)  doing.next=p; doing.pointer_a=(void *)m; for(;p;p=p->next) { if(p->pointer_a == (void *)m) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(ret=(struct mapping *)p->pointer_b);
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; } }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  ret=allocate_mapping(MAP_SLOTS(m->size)); doing.pointer_b=ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) 
f152401996-06-21Fredrik Hübinette (Hubbe)  check_stack(2);
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  LOOP(m) { copy_svalues_recursively_no_free(sp,&k->ind, 1, p); sp++; copy_svalues_recursively_no_free(sp,&k->val, 1, p); sp++; mapping_insert(ret, sp-2, sp-1); pop_n_elems(2); }
5267b71995-08-09Fredrik Hübinette (Hubbe)  return ret; }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) void mapping_search_no_free(struct svalue *to, struct mapping *m, struct svalue *look_for, struct svalue *start) {
515b6c1996-06-09Fredrik Hübinette (Hubbe)  unsigned INT32 h; struct keypair *k;
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(m->size)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  h=0; k=m->hash[h]; if(start)
5267b71995-08-09Fredrik Hübinette (Hubbe)  {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  h=hash_svalue(start) % m->hashsize; for(k=m->hash[h];k;k=k->next) if(is_eq(&k->ind, start)) break; if(!k)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  {
9076fa1997-02-17Fredrik Hübinette (Hubbe)  to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  return; } k=k->next; }
9076fa1997-02-17Fredrik Hübinette (Hubbe)  while(h < (unsigned INT32)m->hashsize) { while(k) { if(is_eq(look_for, &k->val)) { assign_svalue_no_free(to,&k->ind); return; } k=k->next; } k=m->hash[++h]; }
5267b71995-08-09Fredrik Hübinette (Hubbe)  }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  to->type=T_INT; to->subtype=NUMBER_UNDEFINED; to->u.integer=0;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef DEBUG
515b6c1996-06-09Fredrik Hübinette (Hubbe) void check_mapping(struct mapping *m)
5267b71995-08-09Fredrik Hübinette (Hubbe) { if(m->refs <=0) fatal("Mapping has zero refs.\n"); if(m->next && m->next->prev != m) fatal("Mapping ->next->prev != mapping.\n"); if(m->prev) { if(m->prev->next != m) fatal("Mapping ->prev->next != mapping.\n"); }else{ if(first_mapping != m) fatal("Mapping ->prev == 0 but first_mapping != mapping.\n"); }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(m->hashsize < 0) fatal("Assert: I don't think he's going to make it Jim.\n"); if(m->size < 0) fatal("Core breach, evacuate ship!\n"); if(m->size > (m->hashsize + 3) * AVG_LINK_LENGTH) fatal("Pretty mean hashtable there buster!.\n"); if(m->size > 0 && (!m->ind_types || !m->val_types)) fatal("Mapping type fields are... wrong.\n");
9076fa1997-02-17Fredrik Hübinette (Hubbe)  if(!m->hash && m->size)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  fatal("Hey! where did my hashtable go??\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) }
be478c1997-08-30Henrik Grubbström (Grubba) void check_all_mappings(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { struct mapping *m; for(m=first_mapping;m;m=m->next)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  check_mapping(m); } #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  void gc_mark_mapping_as_referenced(struct mapping *m) { INT32 e; struct keypair *k; if(gc_mark(m)) { if((m->ind_types | m->val_types) & BIT_COMPLEX) { LOOP(m) {
5d7d051996-09-25Fredrik Hübinette (Hubbe)  /* We do not want to count this key:index pair if * the index is a destructed object or function */ if(((1 << k->ind.type) & (BIT_OBJECT | BIT_FUNCTION)) && !(k->ind.u.object->prog)) continue;
515b6c1996-06-09Fredrik Hübinette (Hubbe)  gc_mark_svalues(&k->ind, 1); gc_mark_svalues(&k->val, 1); } } }
5267b71995-08-09Fredrik Hübinette (Hubbe) }
515b6c1996-06-09Fredrik Hübinette (Hubbe) 
be478c1997-08-30Henrik Grubbström (Grubba) void gc_check_all_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct mapping *m; for(m=first_mapping;m;m=m->next) { if((m->ind_types | m->val_types) & BIT_COMPLEX) { LOOP(m) {
5d7d051996-09-25Fredrik Hübinette (Hubbe)  /* We do not want to count this key:index pair if * the index is a destructed object or function */ if(((1 << k->ind.type) & (BIT_OBJECT | BIT_FUNCTION)) && !(k->ind.u.object->prog)) continue;
f6d0171997-10-15Fredrik Hübinette (Hubbe)  debug_gc_check_svalues(&k->ind, 1, T_MAPPING, m); m->val_types |= debug_gc_check_svalues(&k->val, 1, T_MAPPING, m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  }
06983f1996-09-22Fredrik Hübinette (Hubbe)  #ifdef DEBUG if(d_flag > 1) check_mapping_type_fields(m);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
06983f1996-09-22Fredrik Hübinette (Hubbe) 
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_mark_all_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { struct mapping *m; for(m=first_mapping;m;m=m->next) if(gc_is_referenced(m)) gc_mark_mapping_as_referenced(m); }
be478c1997-08-30Henrik Grubbström (Grubba) void gc_free_all_unreferenced_mappings(void)
515b6c1996-06-09Fredrik Hübinette (Hubbe) { INT32 e; struct keypair *k; struct mapping *m,*next; for(m=first_mapping;m;m=next) {
5d7d051996-09-25Fredrik Hübinette (Hubbe)  check_mapping_for_destruct(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  if(gc_do_free(m)) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(m);
515b6c1996-06-09Fredrik Hübinette (Hubbe)  for(e=0;e<m->hashsize;e++) {
06983f1996-09-22Fredrik Hübinette (Hubbe)  k=m->hash[e]; while(k)
515b6c1996-06-09Fredrik Hübinette (Hubbe)  { free_svalue(&k->ind); free_svalue(&k->val);
06983f1996-09-22Fredrik Hübinette (Hubbe)  if(k->next) { k = k->next; } else { k->next=m->free_list; m->free_list=m->hash[e]; m->hash[e]=0; break; }
515b6c1996-06-09Fredrik Hübinette (Hubbe)  } } m->size=0; next=m->next; free_mapping(m); }else{ next=m->next; } } }
61e9a01998-01-25Fredrik Hübinette (Hubbe) #ifdef DEBUG void simple_describe_mapping(struct mapping *m) { char *s; init_buf(); describe_mapping(m,0,2); s=simple_free_buf(); fprintf(stderr,"%s\n",s); free(s); } void debug_dump_mapping(struct mapping *m) { fprintf(stderr,"Refs=%d, next=%p, prev=%p, size=%d, hashsize=%d\n", m->refs, m->next, m->prev, m->size, m->hashsize); fprintf(stderr,"Indices type field = "); debug_dump_type_field(m->ind_types); fprintf(stderr,"\n"); fprintf(stderr,"Values type field = "); debug_dump_type_field(m->val_types); fprintf(stderr,"\n"); simple_describe_mapping(m); } #endif
be478c1997-08-30Henrik Grubbström (Grubba) void zap_all_mappings(void)
5267b71995-08-09Fredrik Hübinette (Hubbe) { INT32 e;
06983f1996-09-22Fredrik Hübinette (Hubbe)  struct keypair *k;
c94c371996-03-28Fredrik Hübinette (Hubbe)  struct mapping *m,*next; for(m=first_mapping;m;m=next) {
d6ac731998-04-20Henrik Grubbström (Grubba)  add_ref(m);
c94c371996-03-28Fredrik Hübinette (Hubbe) 
61e9a01998-01-25Fredrik Hübinette (Hubbe) #if defined(DEBUG) && defined(DEBUG_MALLOC) if(verbose_debug_exit) debug_dump_mapping(m); #endif
06983f1996-09-22Fredrik Hübinette (Hubbe)  for(e=0;e<m->hashsize;e++) {
9c6f7d1997-04-15Fredrik Hübinette (Hubbe)  while((k=m->hash[e]))
06983f1996-09-22Fredrik Hübinette (Hubbe)  {
66f7471997-02-06Fredrik Hübinette (Hubbe)  m->hash[e]=k->next; k->next=m->free_list; m->free_list=k;
06983f1996-09-22Fredrik Hübinette (Hubbe)  free_svalue(&k->ind); free_svalue(&k->val); }
c94c371996-03-28Fredrik Hübinette (Hubbe)  }
06983f1996-09-22Fredrik Hübinette (Hubbe)  m->size=0; next=m->next;
cbd60b1996-12-04Fredrik Hübinette (Hubbe)  /* free_mapping(m); */
c94c371996-03-28Fredrik Hübinette (Hubbe)  } }
c3c7031996-12-04Fredrik Hübinette (Hubbe)  void count_memory_in_mappings(INT32 *num_, INT32 *size_) { INT32 num=0, size=0; struct mapping *m; for(m=first_mapping;m;m=m->next) { struct keypair *k; num++; size+=sizeof(struct mapping)+ sizeof(struct keypair *) * m->hashsize+ sizeof(struct keypair) * m->size; for(k=m->free_list;k;k=k->next) size+=sizeof(struct keypair); } *num_=num; *size_=size; }