pike.git / src / array.c

version» Context lines:

pike.git/src/array.c:12:   #include "stralloc.h"   #include "interpret.h"   #include "opcodes.h"   #include "pike_error.h"   #include "pike_types.h"   #include "fsort.h"   #include "builtin_functions.h"   #include "pike_memory.h"   #include "gc.h"   #include "main.h" - #include "pike_security.h" - #include "stuff.h" - #include "bignum.h" +    #include "cyclic.h"   #include "multiset.h"   #include "mapping.h" -  + #include "bignum.h" + #include "pike_search.h"      /** The empty array. */   PMOD_EXPORT struct array empty_array=   {    PIKE_CONSTANT_MEMOBJ_INIT(1, PIKE_T_ARRAY), /* Never free */ -  &weak_empty_array, /* Next */ -  0, /* previous */ +     0, /* Size = 0 */    0, /* malloced Size = 0 */    0, /* no types */    0, /* no flags */ -  +  &weak_empty_array, /* Next */ +  0, /* previous */    empty_array.real_item, /* Initialize the item pointer. */    {SVALUE_INIT_FREE},   };      /** The empty weak array. */   PMOD_EXPORT struct array weak_empty_array=   { -  PIKE_CONSTANT_MEMOBJ_INIT(1, PIKE_T_ARRAY), -  0, &empty_array, 0, 0, 0, ARRAY_WEAK_FLAG, -  weak_empty_array.real_item, +  PIKE_CONSTANT_MEMOBJ_INIT(1, PIKE_T_ARRAY), /* Never free */ +  0, /* Size = 0 */ +  0, /* malloced Size = 0 */ +  0, /* no types */ +  ARRAY_WEAK_FLAG, /* weak */ +  0, /* next */ +  &empty_array, /* previous */ +  weak_empty_array.real_item, /* Initialize the item pointer. */    {SVALUE_INIT_FREE},   };      struct array *first_array = &empty_array;   struct array *gc_internal_array = 0;   static struct array *gc_mark_array_pos;      #ifdef TRACE_UNFINISHED_TYPE_FIELDS   PMOD_EXPORT int accept_unfinished_type_fields = 0;   PMOD_EXPORT void dont_accept_unfinished_type_fields (void *orig)
pike.git/src/array.c:72:    *    * @param size The size of the new array, in elements.    * @param extra_space The number of extra elements space    * should be reserved for.    * @return A pointer to the allocated array struct.    */   PMOD_EXPORT struct array *real_allocate_array(ptrdiff_t size,    ptrdiff_t extra_space)   {    struct array *v; +  size_t length = size;    -  if(size+extra_space == 0) +  if (DO_SIZE_T_ADD_OVERFLOW(length, (size_t)extra_space, &length)) goto TOO_BIG; +  +  if(length == 0)    {    add_ref(&empty_array);    return &empty_array;    }    -  /* Limits size to (1<<29)-4 */ -  if( (size_t)(size+extra_space-1) > -  (LONG_MAX-sizeof(struct array))/sizeof(struct svalue) ) -  Pike_error("Too large array (size %ld exceeds %ld).\n", -  (long)(size+extra_space-1), -  (long)((LONG_MAX-sizeof(struct array))/sizeof(struct svalue)) ); -  v=(struct array *)malloc(sizeof(struct array)+ -  (size+extra_space-1)*sizeof(struct svalue)); -  if(!v) -  Pike_error(msg_out_of_mem_2, sizeof(struct array)+ -  (size+extra_space-1)*sizeof(struct svalue)); +  /* +  * Do we really need this limit? +  * - arne +  */ +  if (length > 1U<<29) goto TOO_BIG;    -  GC_ALLOC(v); +  /* struct array contains one svalue already */ +  length --;    -  +  if (DO_SIZE_T_MUL_OVERFLOW(length, sizeof(struct svalue), &length) || +  DO_SIZE_T_ADD_OVERFLOW(length, sizeof(struct array), &length)) goto TOO_BIG;    -  if (size+extra_space) +  v=xcalloc(length, 1); +  +  GC_ALLOC(v); +  gc_init_marker(v); +     /* for now, we don't know what will go in here */    v->type_field = BIT_MIXED | BIT_UNFINISHED; -  else -  v->type_field = 0; -  v->flags=0; +     -  v->malloced_size = DO_NOT_WARN((INT32)(size + extra_space)); +  v->malloced_size = (INT32)(size + extra_space);    v->item=v->real_item; -  v->size = DO_NOT_WARN((INT32)size); +  v->size = (INT32)size;    INIT_PIKE_MEMOBJ(v, T_ARRAY);    DOUBLELINK (first_array, v);    -  { -  struct svalue *item = ITEM(v); -  struct svalue *item_end = item + v->size; -  while (item < item_end) -  *item++ = svalue_int_zero; -  } -  +     return v; -  + TOO_BIG: +  Pike_error("Too large array (size %ld is too big).\n", length);   }      /**    * Free an array without freeing the values inside it.    * Any values inside of the array will be kept.    * @param v The array to be freed.    */   static void array_free_no_free(struct array *v)   {    DOUBLEUNLINK (first_array, v);    -  free((char *)v); +  free(v);       GC_FREE(v);   }      /**    * Free an array. Call this when the array has zero references.    * @param v The array to free.    */   PMOD_EXPORT void really_free_array(struct array *v)   {
pike.git/src/array.c:169:   /**    * Decrement the references (and free if unused) an array if it is not null.    */   PMOD_EXPORT void do_free_array(struct array *a)   {    if (a)    free_array(a);   }      /** +  * Free all elements in an array and set them to zero. +  */ + PMOD_EXPORT void clear_array(struct array *a) + { +  if (!a->size) return; +  free_svalues(ITEM(a), a->size, a->type_field); +  /* NB: We know that INT_T == 0. */ +  memset(ITEM(a), 0, a->size * sizeof(struct svalue)); +  a->type_field = BIT_INT; + } +  + /**    * Set the flags on an array. If the array is empty then only the    * weak flag is significant.    */   PMOD_EXPORT struct array *array_set_flags(struct array *a, int flags)   {    if (a->size)    a->flags = flags;    else {    free_array(a);    if (flags & ARRAY_WEAK_FLAG)
pike.git/src/array.c:277:   {    switch(TYPEOF(*ind))    {    case T_INT: {    INT_TYPE p = ind->u.integer;    INT_TYPE i = p < 0 ? p + a->size : p;    if(i<0 || i>=a->size) {    struct svalue tmp;    SET_SVAL(tmp, T_ARRAY, 0, array, a);    if (a->size) { -  index_error(0,0,0,&tmp,ind, +  index_error(0,0,&tmp,ind,    "Index %"PRINTPIKEINT"d is out of array range "    "%d..%d.\n", p, -a->size, a->size-1);    } else { -  index_error(0,0,0,&tmp,ind, +  index_error(0,0,&tmp,ind,    "Attempt to index the empty array with %"PRINTPIKEINT"d.\n", p);    }    }    array_index_no_free(s,a,i);    break;    }       case T_STRING:    {    SET_SVAL(*s, T_ARRAY, 0, array, array_column(a, ind, 0));    break;    }       default:    {    struct svalue tmp;    SET_SVAL(tmp, T_ARRAY, 0, array, a); -  index_error(0,0,0,&tmp,ind,"Array index is neither int nor string.\n"); +  index_error(0,0,&tmp,ind,"Array index is neither int nor string.\n");    }    }   }      /**    * Extract an svalue from an array.    */   PMOD_EXPORT void array_free_index(struct array *v,INT32 index)   {   #ifdef PIKE_DEBUG
pike.git/src/array.c:359:    assign_lvalue(Pike_sp-2, s);    }    pop_n_elems(2);    break;    }       default:    {    struct svalue tmp;    SET_SVAL(tmp, T_ARRAY, 0, array, a); -  index_error(0,0,0,&tmp,ind,"Array index is neither int nor string.\n"); +  index_error(0,0,&tmp,ind,"Array index is neither int nor string.\n");    }    }   }      /**    * Insert an svalue into an array and grow the array if necessary.    */   PMOD_EXPORT struct array *array_insert(struct array *v,struct svalue *s,INT32 index)   {   #ifdef PIKE_DEBUG    if(index<0 || index>v->size)    Pike_fatal("Illegal index in low level insert routine.\n");   #endif       /* Can we fit it into the existing block? */    if(v->refs<=1 && (v->malloced_size > v->size))    {    if ((v->item != v->real_item) &&    (((index<<1) < v->size) ||    ((v->item + v->size) == (v->real_item + v->malloced_size)))) { -  MEMMOVE((char *)(ITEM(v)-1), -  (char *)(ITEM(v)), -  index * sizeof(struct svalue)); +  memmove(ITEM(v)-1, ITEM(v), index * sizeof(struct svalue));    v->item--;    } else { -  MEMMOVE((char *)(ITEM(v)+index+1), -  (char *)(ITEM(v)+index), +  memmove(ITEM(v)+index+1, ITEM(v)+index,    (v->size-index) * sizeof(struct svalue));    }    assert_free_svalue (ITEM(v) + index);    v->size++;    }else{    struct array *ret;       ret = array_set_flags(allocate_array_no_init(v->size+1, v->size + 1),    v->flags);    ret->type_field = v->type_field;    -  MEMCPY(ITEM(ret), ITEM(v), sizeof(struct svalue) * index); -  MEMCPY(ITEM(ret)+index+1, ITEM(v)+index, +  memcpy(ITEM(ret), ITEM(v), sizeof(struct svalue) * index); +  memcpy(ITEM(ret)+index+1, ITEM(v)+index,    sizeof(struct svalue) * (v->size-index));    assert_free_svalue (ITEM(ret) + index);    if (v->refs == 1) {    /* Optimization: Steal the references. */    v->size = 0;    } else if (v->type_field & BIT_REF_TYPES) {    /* Adjust the references. */    int e = v->size;    struct svalue *s = ITEM(ret);    while (e--) {
pike.git/src/array.c:426:    }       array_set_index_no_free (v,index,s);       return v;   }      /*    * lval += ({ @args });    * -  * Stack is lvalue followed by arguments. +  * Stack is lvalue followed by a zero placeholder followed by arguments.    */   void o_append_array(INT32 args)   {    struct svalue *lval = Pike_sp - args;    struct svalue *val = lval + 2; -  +  int lval_type;   #ifdef PIKE_DEBUG    if (args < 3) {    Pike_fatal("Too few arguments to o_append_array(): %d\n", args);    }   #endif    args -= 3;    /* Note: val should always be a zero here! */ -  lvalue_to_svalue_no_free(val, lval); +  lval_type = lvalue_to_svalue_no_free(val, lval);       if (TYPEOF(*val) == T_ARRAY) {    struct svalue tmp;    struct array *v = val->u.array; -  +  /* simple case: if refs == 2 and there is space, just add the +  element and do not do the assign. This can be done because the +  lvalue already has the array as it's value. +  */ +  if( (v->refs == 2) && (lval_type != PIKE_T_GET_SET) ) { +  if ((TYPEOF(*lval) == T_OBJECT) && +  lval->u.object->prog && +  ((FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_INDEX) >= 0) || +  (FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_ARROW) >= 0))) { +  /* There's a function controlling assignments in this object, +  * so we can't alter the array in place. +  */ +  } else if( v->real_item+v->malloced_size >= v->item+v->size+args ) { +  struct svalue *from = val+1; +  int i; +  for( i = 0; i<args; i++,from++ ) +  { +  v->item[v->size++] = *from; +  v->type_field |= 1<<TYPEOF(*from); +  } +  Pike_sp -= args; +  stack_pop_2_elems_keep_top(); +  return; +  } +  }    /* This is so that we can minimize the number of references    * to the array, and be able to use destructive operations.    * It's done by freeing the old reference to foo after it has been    * pushed on the stack. That way foo can have only 1 reference if we    * are lucky, and then the low array manipulation routines can    * be destructive if they like.    */    SET_SVAL(tmp, PIKE_T_INT, NUMBER_NUMBER, integer, 0);    assign_lvalue(lval, &tmp);   
pike.git/src/array.c:537:    free_svalues(ITEM(v) + size, v->size - size, v->type_field);    v->size=size;       if(size*4 < v->malloced_size + 4) /* Should we realloc it? */    {    a = array_set_flags(allocate_array_no_init(size, 0), v->flags);    if (a->size) {    a->type_field = v->type_field;    }    -  MEMCPY(ITEM(a), ITEM(v), size*sizeof(struct svalue)); +  memcpy(ITEM(a), ITEM(v), size*sizeof(struct svalue));    v->size=0;    free_array(v);    return a;    }else{    return v;    }   }      /**    * Resize an array destructively, with the exception that a may be one
pike.git/src/array.c:576:    {    for(;a->size < size; a->size++)    {    SET_SVAL(ITEM(a)[a->size], T_INT, NUMBER_NUMBER, integer, 0);    }    a->type_field |= BIT_INT;    return a;    } else {    struct array *ret;    ret = array_set_flags(low_allocate_array(size, size + 1), a->flags); -  MEMCPY(ITEM(ret), ITEM(a), sizeof(struct svalue)*a->size); -  ret->type_field = DO_NOT_WARN((TYPE_FIELD)(a->type_field | BIT_INT)); +  memcpy(ITEM(ret), ITEM(a), sizeof(struct svalue)*a->size); +  ret->type_field = (TYPE_FIELD)(a->type_field | BIT_INT);    a->size=0;    free_array(a);    return ret;    }    } else {    return array_shrink(a, size);    }   }      /**
pike.git/src/array.c:619:    /* NOTE: The following uses the fact that array_set_flags()    * will reallocate the array if it has zero size!    */    return array_set_flags(v, v->flags);    } else if(v->size*4 + 4 < v->malloced_size ) /* Should we realloc it? */    {    a = array_set_flags(allocate_array_no_init(v->size-1, 0), v->flags);    a->type_field = v->type_field;       if(index>0) -  MEMCPY(ITEM(a), ITEM(v), index*sizeof(struct svalue)); +  memcpy(ITEM(a), ITEM(v), index*sizeof(struct svalue));    if(v->size-index>1) -  MEMCPY(ITEM(a)+index, +  memcpy(ITEM(a)+index,    ITEM(v)+index+1,    (v->size-index-1)*sizeof(struct svalue));    v->size=0;    free_array(v);    return a;    } else {    if(v->size-index>1)    { -  MEMMOVE((char *)(ITEM(v)+index), -  (char *)(ITEM(v)+index+1), +  memmove(ITEM(v)+index, ITEM(v)+index+1,    (v->size-index-1)*sizeof(struct svalue));    }    v->size--;    return v;    }   }      static ptrdiff_t fast_array_search( struct array *v, struct svalue *s, ptrdiff_t start )   {    ptrdiff_t e;
pike.git/src/array.c:870:      /* The sort is stable. */   INT32 *get_order(struct array *v, cmpfun fun)   {    INT32 e, *current_order;    ONERROR tmp;       if(!v->size) return 0;       /* Overlow safe: ((1<<29)-4)*4 < ULONG_MAX */ -  current_order=(INT32 *)xalloc(v->size * sizeof(INT32)); +  current_order=xalloc(v->size * sizeof(INT32));    SET_ONERROR(tmp, free, current_order);    for(e=0; e<v->size; e++) current_order[e]=e;       get_order_fsort(current_order,    current_order+v->size-1,    fun,    ITEM(v));       UNSET_ONERROR(tmp);    return current_order;
pike.git/src/array.c:1087:       case T_OBJECT:    case T_FUNCTION:    return obj_or_func_cmp (a, b);       default:    if(a->u.refs < b->u.refs) return -1;    if(a->u.refs > b->u.refs) return 1;    return 0;    } -  /* NOT REACHED */ +    }      static int switch_svalue_cmpfun(const struct svalue *a, const struct svalue *b)   {    int typediff = TYPEOF(*a) - TYPEOF(*b);    if (typediff)    return typediff;       switch(TYPEOF(*a))    {
pike.git/src/array.c:1109:    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)); +  return (int)my_quick_strcmp(a->u.string, b->u.string);       case T_OBJECT:    case T_FUNCTION:    return obj_or_func_cmp (a, b);       default:    if(a->u.refs < b->u.refs) return -1;    if(a->u.refs > b->u.refs) return 1;    return 0;    } -  /* NOT REACHED */ +    }      int alpha_svalue_cmpfun(const struct svalue *a, const struct svalue *b)   {    int typediff = TYPEOF(*a) - TYPEOF(*b);    if (typediff) {    if (TYPEOF(*a) == T_OBJECT || TYPEOF(*b) == T_OBJECT) {    int res = lfun_cmp (a, b);    if (res != -CMPFUN_UNORDERED) return res;    }
pike.git/src/array.c:1147:    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)); +  return (int)my_quick_strcmp(a->u.string, b->u.string);       case T_ARRAY:    if(a==b) return 0;    if (!a->u.array->size)    if (!b->u.array->size) /* There are several different empty arrays. */    return 0;    else    return -1;    else    if (!b->u.array->size)
pike.git/src/array.c:1193:       case T_OBJECT:    case T_FUNCTION:    return obj_or_func_cmp (a, b);       default:    if(a->u.ptr < b->u.ptr) return -1;    if(a->u.ptr > b->u.ptr) return 1;    return 0;    } -  /* NOT REACHED */ +    }      #define CMP(X,Y) alpha_svalue_cmpfun(X,Y)   #define TYPE struct svalue   #define ID low_sort_svalues   #include "fsort_template.h"   #undef CMP   #undef TYPE   #undef ID   
pike.git/src/array.c:1271:    * get_alpha_order. */   PMOD_EXPORT INT32 *stable_sort_array_destructively(struct array *v)   {    INT32 *current_order;    ONERROR tmp;    int e;       if(!v->size) return NULL;       /* Overflow safe: ((1<<29)-4)*4 < ULONG_MAX */ -  current_order=(INT32 *)xalloc(v->size * sizeof(INT32)); +  current_order=xalloc(v->size * sizeof(INT32));    SET_ONERROR(tmp, free, current_order);    for(e=0; e<v->size; e++) current_order[e]=e;       low_stable_sort_svalues (0, v->size - 1, ITEM (v), current_order, v->size);       UNSET_ONERROR (tmp);    return current_order;   }      
pike.git/src/array.c:1382:    return ~a->size;    }       return low_lookup(a,s,switch_svalue_cmpfun);   }         /**    * Reorganize an array in the order specified by 'order'.    */ - PMOD_EXPORT struct array *order_array(struct array *v, INT32 *order) + PMOD_EXPORT struct array *order_array(struct array *v, const INT32 *order)   {    reorder((char *)ITEM(v),v->size,sizeof(struct svalue),order);    return v;   }         /**    * Copy and reorganize an array.    */ - PMOD_EXPORT struct array *reorder_and_copy_array(struct array *v, INT32 *order) + PMOD_EXPORT struct array *reorder_and_copy_array(const struct array *v, const INT32 *order)   {    INT32 e;    struct array *ret;    ret=allocate_array_no_init(v->size, 0);    ret->type_field = v->type_field;       for(e=0;e<v->size;e++)    assign_svalue_no_free(ITEM(ret)+e, ITEM(v)+order[e]);       return ret;
pike.git/src/array.c:1421:    if(v->flags & ARRAY_LVALUE)    {    v->type_field=BIT_MIXED|BIT_UNFINISHED;    return BIT_MIXED|BIT_UNFINISHED;    }       t=0;       for(e=0; e<v->size; e++) {    check_svalue (ITEM(v) + e); -  t |= 1 << TYPEOF(ITEM(v)[e]); +  t |= BITOF(ITEM(v)[e]);    }      #ifdef PIKE_DEBUG    if(t & ~(v->type_field))    {    describe(v);    Pike_fatal("Type field out of order (old:0x%04x new:0x%04x)!\n",    v->type_field, t);    }   #endif
pike.git/src/array.c:1538:    }   #endif    if(!(a->type_field & b->type_field) &&    !((a->type_field | b->type_field) & BIT_OBJECT))    {    /* do smart optimizations */    switch(opcode)    {    case PIKE_ARRAY_OP_AND:    /* Trivially overflow safe */ -  ret=(INT32 *)xalloc(sizeof(INT32)); +  ret=xalloc(sizeof(INT32));    *ret=0;    return ret;       case PIKE_ARRAY_OP_SUB:    /* Overlow safe: ((1<<29)-4+1)*4 < ULONG_MAX */ -  ptr=ret=(INT32 *)xalloc(sizeof(INT32)*(a->size+1)); +  ptr=ret=xalloc(sizeof(INT32)*(a->size+1));    *(ptr++)=a->size;    for(i=0;i<a->size;i++) *(ptr++)=i;    return ret;    }    }       /* Note: The following is integer overflow safe as long as    * sizeof(struct svalue) >= 2*sizeof(INT32).    */ -  ptr=ret=(INT32 *)xalloc(sizeof(INT32)*(a->size + b->size + 1)); +  ptr=ret=xalloc(sizeof(INT32)*(a->size + b->size + 1));    SET_ONERROR(r, free,ret);    ptr++;       while(ap < a->size && bp < b->size)    {    i=set_svalue_cmpfun(ITEM(a)+ap,ITEM(b)+bp);    if(i < 0)    i=opcode >> 8;    else if(i > 0)    i=opcode;
pike.git/src/array.c:1577:       if(i & PIKE_ARRAY_OP_A) *(ptr++)=ap;    if(i & PIKE_ARRAY_OP_B) *(ptr++)=~bp;    if(i & PIKE_ARRAY_OP_SKIP_A) ap++;    if(i & PIKE_ARRAY_OP_SKIP_B) bp++;    }       if((opcode >> 8) & PIKE_ARRAY_OP_A) while(ap<a->size) *(ptr++)=ap++;    if(opcode & PIKE_ARRAY_OP_B) while(bp<b->size) *(ptr++)=~(bp++);    -  *ret = DO_NOT_WARN((INT32)(ptr-ret-1)); +  *ret = (INT32)(ptr-ret-1);       UNSET_ONERROR(r);       return ret;   }      /**    * This routine merges two arrays in the order specified by 'zipper'    * zipper normally produced by merge() above.    */
pike.git/src/array.c:1668: Inside #if 1 and #if defined(PIKE_DEBUG)
   }   #ifdef PIKE_DEBUG    if(d_flag>1)    check_array(v);   #endif    return v;    }    if (!v2 || (v->size > v2->size)) {    /* Got a potential candidate.    * -  * Optimize for maximum MEMMOVE() +  * Optimize for maximum memmove()    * (ie minimum assign_svalues_no_free()).    */    tmp2 = tmp;    v2 = v;    e2 = e;    }    }    tmp+=v->size;    }    if (v2) {    debug_malloc_touch(v2);    mark_free_svalue(argp + e2); -  MEMMOVE((char *)(v2->real_item + tmp2), (char *)ITEM(v2), +  memmove(v2->real_item + tmp2, ITEM(v2),    v2->size * sizeof(struct svalue));    v2->item = v2->real_item + tmp2;    for(tmp=e2-1;tmp>=0;tmp--)    {    v = argp[tmp].u.array;    debug_malloc_touch(v);    v2->type_field |= v->type_field;    assign_svalues_no_free(ITEM(v2) - v->size, ITEM(v),    v->size, v->type_field);    v2->item -= v->size;
pike.git/src/array.c:1758: Inside #if defined(PIKE_DEBUG)
   array_check_type_field(a);    array_check_type_field(b);    }   #endif       /* This could be done much better if I KNEW that    * the type fields didn't contain types that    * really aren't in the array    */    if(!(a->type_field & b->type_field) && -  !( (a->type_field | b->type_field) & BIT_OBJECT )) +  !( (a->type_field | b->type_field) & (BIT_OBJECT|BIT_FUNCTION) ))    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;   
pike.git/src/array.c:1875: Inside #if 0
   for (i = 1; i < *zipper + 1; i++)    fprintf (stderr, "%d ", zipper[i]);    fprintf (stderr, "\n");    }   #endif       fsort_with_order( (zipper+1), zipper+*zipper, array_merge_fun,    ordera, orderb );       ret=array_zip(tmpa,tmpb,zipper); -  UNSET_ONERROR(r3); free((char *)zipper); +  UNSET_ONERROR(r3); free(zipper);    UNSET_ONERROR(r2); free_array(tmpb);    UNSET_ONERROR(r1); free_array(tmpa); -  UNSET_ONERROR(r5); free((char *)orderb); -  UNSET_ONERROR(r4); free((char *)ordera); +  UNSET_ONERROR(r5); free(orderb); +  UNSET_ONERROR(r4); free(ordera);    return ret;   }         #define CMP(X,Y) set_svalue_cmpfun(X,Y)   #define TYPE struct svalue   #define ID set_sort_svalues   #include "fsort_template.h"   #undef CMP   #undef TYPE   #undef ID    -  - 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; -  - #ifdef PIKE_DEBUG -  if(d_flag > 1) -  { -  array_check_type_field(a); -  array_check_type_field(b); -  } - #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{ -  /* Overlow safe: ((1<<29)-4)*8 < ULONG_MAX */ -  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) -  { -  arrb=ITEM(b); -  }else{ -  /* Overlow safe: ((1<<29)-4)*8 < ULONG_MAX */ -  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) -  { -  i=set_svalue_cmpfun(arra+ap,arrb+bp); -  if(i < 0) -  i=op >> 8; -  else if(i > 0) -  i=op; -  else -  i=op >> 4; -  -  if(i & PIKE_ARRAY_OP_A) ret=append_array(ret,arra+ap); -  if(i & PIKE_ARRAY_OP_B) ret=append_array(ret,arrb+bp); -  if(i & PIKE_ARRAY_OP_SKIP_A) ap++; -  if(i & PIKE_ARRAY_OP_SKIP_B) bp++; -  } -  -  if((op >> 8) & PIKE_ARRAY_OP_A) -  while(ap<a->size) -  ret=append_array(ret,arra + ap++); -  -  if(op & PIKE_ARRAY_OP_B) -  while(bp<b->size) -  ret=append_array(ret,arrb + bp++); -  -  UNSET_ONERROR(r5); -  -  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; - } -  -  - /** merge two arrays without paying attention to the order -  * the elements has presently -  */ - PMOD_EXPORT struct array *merge_array_without_order(struct array *a, -  struct array *b, -  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; -  -  if(ordera) { free((char *)ordera); ordera=0; } -  if(orderb) { free((char *)orderb); orderb=0; } -  -  ordera=get_set_order(a); -  tmpa=reorder_and_copy_array(a,ordera); -  free((char *)ordera); -  ordera=0; -  -  orderb=get_set_order(b); -  tmpb=reorder_and_copy_array(b,orderb); -  free((char *)orderb); -  orderb=0; -  -  zipper=merge(tmpa,tmpb,op); -  ret=array_zip(tmpa,tmpb,zipper); -  free_array(tmpa); -  free_array(tmpb); -  free((char *)zipper); -  return ret; -  - #else -  add_ref(a); -  add_ref(b); -  return merge_array_without_order2(a,b,op); - #endif - } -  +    /** Remove all instances of an svalue from an array   */   static struct array *subtract_array_svalue(struct array *a, struct svalue *b)   {    size_t size = a->size;    size_t from=0, to=0;    TYPE_FIELD to_type = 1<<TYPEOF(*b);    TYPE_FIELD type_field = 0;    ONERROR ouch;    struct svalue *ip=ITEM(a), *dp=ip;
pike.git/src/array.c:2274:   }      /** Push elements of an array onto the stack. The array will be freed.    */   PMOD_EXPORT void push_array_items(struct array *a)   {    check_stack(a->size);    check_array_for_destruct(a);    if(a->refs == 1)    { -  MEMCPY(Pike_sp,ITEM(a),sizeof(struct svalue)*a->size); +  memcpy(Pike_sp,ITEM(a),sizeof(struct svalue)*a->size);    Pike_sp += a->size;    a->size=0;    free_array(a);    }else{    assign_svalues_no_free(Pike_sp, ITEM(a), a->size, a->type_field);    Pike_sp += a->size;    free_array(a);    }   }    - void describe_array_low(struct array *a, struct processing *p, int indent) + void describe_array_low(struct byte_buffer *buf, struct array *a, struct processing *p, int indent)   {    INT32 e,d;    indent += 2;       for(e=0; e<a->size; e++)    { -  if(e) my_strcat(",\n"); -  for(d=0; d<indent; d++) my_putchar(' '); -  describe_svalue(ITEM(a)+e,indent,p); +  buffer_ensure_space(buf, indent + 2); +  if(e) buffer_add_str_unsafe(buf, ",\n"); +  for(d=0; d<indent; d++) buffer_add_char_unsafe(buf, ' '); +  describe_svalue(buf, ITEM(a)+e,indent,p);    }   }         #ifdef PIKE_DEBUG   void simple_describe_array(struct array *a)   { -  dynamic_buffer save_buf; +     char *s;    if (a->size) { -  init_buf(&save_buf); -  describe_array_low(a,0,0); -  s=simple_free_buf(&save_buf); -  fprintf(stderr,"({\n%s\n})\n",s); -  free(s); +  struct byte_buffer buf = BUFFER_INIT(); +  describe_array_low(&buf,a,0,0); +  fprintf(stderr,"({\n%s\n})\n",buffer_get_string(&buf)); +  buffer_free(&buf);    }    else    fputs ("({ })\n", stderr);   } -  - void describe_index(struct array *a, -  int e, -  struct processing *p, -  int indent) - { -  describe_svalue(ITEM(a)+e, indent, p); - } +    #endif       - void describe_array(struct array *a,struct processing *p,int indent) + void describe_array(struct byte_buffer *buffer,struct array *a,struct processing *p,int indent)   {    struct processing doing;    INT32 e;    char buf[60];    if(! a->size)    { -  my_strcat("({ })"); +  buffer_add_str(buffer, "({ })");    return;    }       doing.next=p;    doing.pointer_a=(void *)a;    for(e=0;p;e++,p=p->next)    {    if(p->pointer_a == (void *)a)    {    sprintf(buf,"@%ld",(long)e); -  my_strcat(buf); +  buffer_add_str(buffer, buf);    return;    }    }       if (a->size == 1) {    sprintf(buf, "({ /* 1 element */\n");    } else {    sprintf(buf, "({ /* %ld elements */\n", (long)a->size);    } -  my_strcat(buf); -  describe_array_low(a,&doing,indent); -  my_putchar('\n'); -  for(e=2; e<indent; e++) my_putchar(' '); -  my_strcat("})"); +  buffer_add_str(buffer, buf); +  describe_array_low(buffer,a,&doing,indent); +  buffer_add_char(buffer, '\n'); +  for(e=2; e<indent; e++) buffer_add_char(buffer, ' '); +  buffer_add_str(buffer, "})");   }      /**    * Pops a number of arguments off of the stack an puts them in an array.    * The 'top' of the stack will be the last element in the array.    * @param args The number of arguments to aggregate.    */   PMOD_EXPORT struct array *aggregate_array(INT32 args)   {    struct array *a;       a=allocate_array_no_init(args,0);    if (args) { -  MEMCPY((char *)ITEM(a),(char *)(Pike_sp-args),args*sizeof(struct svalue)); +  memcpy(ITEM(a),Pike_sp-args,args*sizeof(struct svalue));    array_fix_type_field (a);    Pike_sp-=args;    DO_IF_DMALLOC(while(args--) dmalloc_touch_svalue(Pike_sp + args));    }    return a;   }      /** Add an element to the end of an array by resizing the array.    *    * @param a the array to be appended    * @param s the value to be added to the new element in the array    */   PMOD_EXPORT struct array *append_array(struct array *a, struct svalue *s)   {    INT32 size = a->size;    a=resize_array(a, size+1);    array_set_index(a, size, s);    return a;   }    -  + /** Automap assignments +  * This implements X[*] = ...[*].. +  * Assign elements in a at @level to elements from b at the same @level. +  * This will not actually modify any of the arrays, only change the +  * values in them. +  */ + void assign_array_level( struct array *a, struct array *b, int level ) + { +  if( a->size != b->size ) +  /* this should not really happen. */ +  Pike_error("Source and destination differs in size in automap?!\n"); +  +  if( level > 1 ) +  { +  /* recurse. */ +  INT32 i; +  for( i=0; i<a->size; i++ ) +  { +  if( TYPEOF(a->item[i]) != PIKE_T_ARRAY ) +  Pike_error("Too many automap levels.\n"); +  if( TYPEOF(b->item[i]) != PIKE_T_ARRAY ) /* obscure messages much? */ +  Pike_error("Not enough levels of mapping in RHS\n"); +  assign_array_level( a->item[i].u.array, b->item[i].u.array, level-1 ); +  } +  } +  else { +  assign_svalues( a->item, b->item, a->size, +  a->type_field|b->type_field ); +  a->type_field = b->type_field; +  } + } +  + /* Assign all elemnts in a at level to b. +  * This implements X[*] = expression without automap. +  */ + void assign_array_level_value( struct array *a, struct svalue *b, int level ) + { +  INT32 i; +  if( level > 1 ) +  { +  /* recurse. */ +  for( i=0; i<a->size; i++ ) +  { +  if( TYPEOF(a->item[i]) != PIKE_T_ARRAY ) +  Pike_error("Too many automap levels.\n"); +  assign_array_level_value( a->item[i].u.array, b, level-1 ); +  } +  } +  else +  { +  if( a->type_field & BIT_REF_TYPES ) free_mixed_svalues( a->item, a->size ); +  if( REFCOUNTED_TYPE(TYPEOF(*b)) ) *b->u.refs+=a->size; +  for( i=0; i<a->size; i++) +  a->item[i] = *b; +  a->type_field = 1 << TYPEOF(*b); +  } + } +    typedef char *(* explode_searchfunc)(void *,void *,size_t);      /** Explode a string into an array by a delimiter.    *    * @param str the string to be split    * @param del the string to split str by    * @returns an array containing the elements of the split string    */   PMOD_EXPORT struct array *explode(struct pike_string *str,    struct pike_string *del)
pike.git/src/array.c:2439:    ret->size=0;       mojt=compile_memsearcher(MKPCHARP_STR(del),    del->len,    str->len,    del);    SET_ONERROR (uwp, do_free_object, mojt.container);       switch(str->size_shift)    { -  case 0: f=(explode_searchfunc)mojt.vtab->func0; break; -  case 1: f=(explode_searchfunc)mojt.vtab->func1; break; -  case 2: f=(explode_searchfunc)mojt.vtab->func2; break; - #ifdef PIKE_DEBUG -  default: Pike_fatal("Illegal shift.\n"); - #endif +  case eightbit: f=(explode_searchfunc)mojt.vtab->func0; break; +  case sixteenbit: f=(explode_searchfunc)mojt.vtab->func1; break; +  case thirtytwobit: f=(explode_searchfunc)mojt.vtab->func2; break; +  default: Pike_fatal("Invalid size_shift: %d.\n", str->size_shift);    }       while((tmp = f(mojt.data, s, (end-s)>> str->size_shift)))    {    if(ret->size == ret->malloced_size)    {    e=ret->size;    ACCEPT_UNFINISHED_TYPE_FIELDS {    ret=resize_array(ret, e * 2);    } END_ACCEPT_UNFINISHED_TYPE_FIELDS;
pike.git/src/array.c:2519:       for(e=a->size, ae=a->item; e--; ae++)    switch(TYPEOF(*ae))    {    case T_INT:    if(!ae->u.integer)    continue; /* skip zero (strings) */    /* FALLTHROUGH */    default:    Pike_error("Array element %d is not a string\n", ae-a->item); +  break;    case T_STRING:    delims++;    len+=ae->u.string->len + del->len;    if(ae->u.string->size_shift > max_shift)    max_shift=ae->u.string->size_shift;    break;    }       if(delims)    {
pike.git/src/array.c:2614:   PMOD_EXPORT void apply_array(struct array *a, INT32 args, int flags)   {    INT32 e, hash = 0;    struct svalue *argp = Pike_sp-args;    struct array *cycl;    DECLARE_CYCLIC();       check_stack(args);    check_array_for_destruct(a);    for (e=0; e<args; e++) -  hash = hash * 33 + DO_NOT_WARN ((INT32) PTR_TO_INT (Pike_sp[-e-1].u.ptr)); +  hash = hash * 33 + (INT32) PTR_TO_INT (Pike_sp[-e-1].u.ptr);       if (!(cycl = (struct array *)BEGIN_CYCLIC(a, (ptrdiff_t)hash))) {    TYPE_FIELD new_types = 0;    struct array *aa;    if ((flags & 1) && (a->refs == 1)) {    /* Destructive operation possible. */    add_ref(aa = a);    aa->type_field |= BIT_UNFINISHED;    } else {    aa = allocate_array(a->size);
pike.git/src/array.c:2690:    *(tmp0++) = *(--tmp1);    *tmp1 = swap;    }       /* FIXME: What about the flags field? */       add_ref(a);    return a;    }    -  /* fprintf(stderr, "R"); */ -  +     ret=allocate_array_no_init(a->size,0);    for(e=0;e<start;e++)    assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+e);    for(;e<end;e++)    assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+end+~e-start);    for(;e<a->size;e++)    assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+e);    ret->type_field = a->type_field;    return ret;   }
pike.git/src/array.c:2716:    */   void array_replace(struct array *a,    struct svalue *from,    struct svalue *to)   {    ptrdiff_t i = -1;    check_array_for_destruct(a);    while((i=fast_array_search(a,from,i+1)) >= 0) array_set_index(a,i,to);   }    + /** +  * Perform a quick gc of the specified weak array. +  * +  * @param a The weak array to be garbage collected. +  * @return The number of freed elements. +  * +  * @see do_gc +  */ + ptrdiff_t do_gc_weak_array(struct array *a) + { +  INT32 e; +  ptrdiff_t res = 0; +  +  if (!(a->flags & ARRAY_WEAK_FLAG)) { +  return 0; +  } +  +  for (e = 0; e < a->size; e++) { +  struct svalue *s = ITEM(a) + e; +  if (!REFCOUNTED_TYPE(TYPEOF(*s)) || (*s->u.refs > 1)) { +  continue; +  } +  /* NB: cf svalue.c:ZAP_SVALUE(). */ +  free_svalue(s); +  SET_SVAL(*s, T_INT, NUMBER_DESTRUCTED, integer, 0); +  res++; +  } +  return res; + } +    #ifdef PIKE_DEBUG   PMOD_EXPORT void check_array(struct array *a)   {    INT32 e;       if(a->next && a->next->prev != a)    Pike_fatal("array->next->prev != array.\n");       if(a->prev)    {
pike.git/src/array.c:2756: Inside #if defined(PIKE_DEBUG) and #if defined(DEBUG_MALLOC)
   {   #ifdef DEBUG_MALLOC    describe(a);   #endif    Pike_fatal("Array item pointer is too small!\n");    }       if(a->refs <=0 )    Pike_fatal("Array has zero refs.\n");    -  +     for(e=0;e<a->size;e++)    {    if(! ( (1 << TYPEOF(ITEM(a)[e])) & (a->type_field) ) &&    TYPEOF(ITEM(a)[e])<16)    Pike_fatal("Type field lies.\n");       check_svalue(ITEM(a)+e);    }   }      void check_all_arrays(void)   {    struct array *a;    for (a = first_array; a; a = a->next)    check_array(a);   }   #endif /* PIKE_DEBUG */       - PMOD_EXPORT void visit_array (struct array *a, int action) + PMOD_EXPORT void visit_array (struct array *a, int action, void *extra)   { -  switch (action) { +  visit_enter(a, T_ARRAY, extra); +  switch (action & VISIT_MODE_MASK) {   #ifdef PIKE_DEBUG    default:    Pike_fatal ("Unknown visit action %d.\n", action);    case VISIT_NORMAL:    case VISIT_COMPLEX_ONLY:    break;   #endif    case VISIT_COUNT_BYTES:    mc_counted_bytes += sizeof (struct array) +    (a->malloced_size - 1) * sizeof (struct svalue);    break;    }    -  if (a->type_field & +  if (!(action & VISIT_NO_REFS) && +  a->type_field &    (action & VISIT_COMPLEX_ONLY ? BIT_COMPLEX : BIT_REF_TYPES)) {    size_t e, s = a->size;    int ref_type = a->flags & ARRAY_WEAK_FLAG ? REF_TYPE_WEAK : REF_TYPE_NORMAL;    for (e = 0; e < s; e++) -  visit_svalue (ITEM (a) + e, ref_type); +  visit_svalue (ITEM (a) + e, ref_type, extra);    } -  +  visit_leave(a, T_ARRAY, extra);   }      static void gc_check_array(struct array *a)   {    GC_ENTER (a, T_ARRAY) {    if(a->type_field & BIT_COMPLEX)    {    if (a->flags & ARRAY_WEAK_FLAG) {    gc_check_weak_svalues(ITEM(a), a->size);    gc_checked_as_weak(a);    }    else    gc_check_svalues(ITEM(a), a->size);    }    } GC_LEAVE;   }    - void gc_mark_array_as_referenced(struct array *a) + PMOD_EXPORT void gc_mark_array_as_referenced(struct array *a)   {    if(gc_mark(a, T_ARRAY))    GC_ENTER (a, T_ARRAY) {    if (a == gc_mark_array_pos)    gc_mark_array_pos = a->next;    if (a == gc_internal_array)    gc_internal_array = a->next;    else {    DOUBLEUNLINK (first_array, a);    DOUBLELINK (first_array, a); /* Linked in first. */
pike.git/src/array.c:2861:    a->type_field = t;    else    a->type_field |= t;    }    gc_assert_checked_as_nonweak(a);    }    }    } GC_LEAVE;   }    - void real_gc_cycle_check_array(struct array *a, int weak) + PMOD_EXPORT void real_gc_cycle_check_array(struct array *a, int weak)   {    GC_CYCLE_ENTER(a, T_ARRAY, weak) {   #ifdef PIKE_DEBUG    if (!gc_destruct_everything &&    (a == &empty_array || a == &weak_empty_array))    Pike_fatal("Trying to gc cycle check some *_empty_array.\n");   #endif       if (a->type_field & BIT_COMPLEX)    {