pike.git / src / array.c

version» Context lines:

pike.git/src/array.c:16:   #include "pike_types.h"   #include "fsort.h"   #include "builtin_functions.h"   #include "pike_memory.h"   #include "gc.h"   #include "main.h"   #include "security.h"   #include "stuff.h"   #include "bignum.h"    - RCSID("$Id: array.c,v 1.78 2000/07/18 05:48:20 mast Exp $"); + RCSID("$Id: array.c,v 1.79 2000/07/28 17:16:54 hubbe Exp $");    - struct array empty_array= + PMOD_EXPORT struct array empty_array=   {    1, /* Never free */   #ifdef PIKE_SECURITY    0,   #endif    &empty_array, /* Next */    &empty_array, /* previous (circular) */    0, /* Size = 0 */    0, /* malloced Size = 0 */    0, /* no types */
pike.git/src/array.c:41:      struct array *gc_internal_array = &empty_array;   static struct array *gc_mark_array_pos = 0;         /* Allocate an array, this might be changed in the future to    * allocate linked lists or something    * NOTE: the new array have zero references    */    - struct array *low_allocate_array(INT32 size,INT32 extra_space) + PMOD_EXPORT struct array *low_allocate_array(INT32 size,INT32 extra_space)   {    struct array *v;    INT32 e;       if(size == 0)    {    add_ref(&empty_array);    return &empty_array;    }   
pike.git/src/array.c:102:    UNLINK_ARRAY(v);       free((char *)v);       GC_FREE();   }      /*    * Free an array, call this when the array has zero references    */ - void really_free_array(struct array *v) + PMOD_EXPORT void really_free_array(struct array *v)   {   #ifdef PIKE_DEBUG    if(v == & empty_array)    fatal("Tried to free the empty_array.\n");   #endif      #ifdef PIKE_DEBUG    if(d_flag > 1) array_check_type_field(v);   #endif       add_ref(v);    FREE_PROT(v);    free_svalues(ITEM(v), v->size, v->type_field);    v->refs--;    array_free_no_free(v);   }    - void do_free_array(struct array *a) + PMOD_EXPORT void do_free_array(struct array *a)   {    if (a)    free_array(a);   }      /*    * Extract an svalue from an array    */ - void array_index_no_free(struct svalue *s,struct array *v,INT32 index) + PMOD_EXPORT void array_index_no_free(struct svalue *s,struct array *v,INT32 index)   {   #ifdef PIKE_DEBUG    if(index<0 || index>=v->size)    fatal("Illegal index in low level index routine.\n");   #endif       assign_svalue_no_free(s, ITEM(v) + index);   }      /*    * Extract an svalue from an array    */ - void array_index(struct svalue *s,struct array *v,INT32 index) + PMOD_EXPORT void array_index(struct svalue *s,struct array *v,INT32 index)   {   #ifdef PIKE_DEBUG    if(index<0 || index>=v->size)    fatal("Illegal index in low level index routine.\n");   #endif       add_ref(v);    assign_svalue(s, ITEM(v) + index);    free_array(v);   }    - void simple_array_index_no_free(struct svalue *s, + PMOD_EXPORT void simple_array_index_no_free(struct svalue *s,    struct array *a,struct svalue *ind)   {    INT32 i;    switch(ind->type)    {    case T_INT:    i=ind->u.integer;    if(i<0) i+=a->size;    if(i<0 || i>=a->size) {    struct svalue tmp;
pike.git/src/array.c:201:    tmp.type=T_ARRAY;    tmp.u.array=a;    index_error(0,0,0,&tmp,ind,"Array index is neither int nor string.\n");    }    }   }      /*    * Extract an svalue from an array    */ - void array_free_index(struct array *v,INT32 index) + PMOD_EXPORT void array_free_index(struct array *v,INT32 index)   {   #ifdef PIKE_DEBUG    if(index<0 || index>=v->size)    fatal("Illegal index in low level free index routine.\n");   #endif       free_svalue(ITEM(v) + index);   }      /*    * Set an index in an array    */ - void array_set_index(struct array *v,INT32 index, struct svalue *s) + PMOD_EXPORT void array_set_index(struct array *v,INT32 index, struct svalue *s)   {   #ifdef PIKE_DEBUG    if(index<0 || index>v->size)    fatal("Illegal index in low level array set routine.\n");   #endif       add_ref(v);    check_destructed(s);       v->type_field = (v->type_field & ~BIT_UNFINISHED) | (1 << s->type);    assign_svalue( ITEM(v) + index, s);    free_array(v);   }       - void simple_set_index(struct array *a,struct svalue *ind,struct svalue *s) + PMOD_EXPORT void simple_set_index(struct array *a,struct svalue *ind,struct svalue *s)   {    INT32 i;    switch (ind->type) {    case T_INT:    i=ind->u.integer;    if(i<0) i+=a->size;    if(i<0 || i>=a->size) {    if (a->size) {    error("Index %d is out of array range 0 - %d.\n", i, a->size-1);    } else {
pike.git/src/array.c:274:    tmp.type=T_ARRAY;    tmp.u.array=a;    index_error(0,0,0,&tmp,ind,"Array index is neither int nor string.\n");    }    }   }      /*    * Insert an svalue into an array, grow the array if nessesary    */ - struct array *array_insert(struct array *v,struct svalue *s,INT32 index) + PMOD_EXPORT struct array *array_insert(struct array *v,struct svalue *s,INT32 index)   {   #ifdef PIKE_DEBUG    if(index<0 || index>v->size)    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)    {    MEMMOVE((char *)(ITEM(v)+index+1),
pike.git/src/array.c:319:    }       array_set_index(v,index,s);       return v;   }      /*    * resize array, resize an array destructively    */ - struct array *resize_array(struct array *a, INT32 size) + PMOD_EXPORT struct array *resize_array(struct array *a, INT32 size)   {   #ifdef PIKE_DEBUG    if(d_flag > 1) array_check_type_field(a);   #endif       if(a->size == size) return a;    if(size > a->size)    {    /* We should grow the array */   
pike.git/src/array.c:360:    /* We should shrink the array */    free_svalues(ITEM(a)+size, a->size - size, a->type_field);    a->size = size;    return a;    }   }      /*    * Shrink an array destructively    */ - struct array *array_shrink(struct array *v,INT32 size) + PMOD_EXPORT struct array *array_shrink(struct array *v,INT32 size)   {    struct array *a;      #ifdef PIKE_DEBUG    if(v->refs>2) /* Odd, but has to be two */    fatal("Array shrink on array with many references.\n");       if(size > v->size)    fatal("Illegal argument to array_shrink.\n");   #endif
pike.git/src/array.c:392:    }else{    free_svalues(ITEM(v) + size, v->size - size, v->type_field);    v->size=size;    return v;    }   }      /*    * Remove an index from an array and shrink the array    */ - struct array *array_remove(struct array *v,INT32 index) + 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
pike.git/src/array.c:436:    }    v->size--;    return v;    }   }      /*    * Search for in svalue in an array.    * return the index if found, -1 otherwise    */ - INT32 array_search(struct array *v, struct svalue *s,INT32 start) + PMOD_EXPORT INT32 array_search(struct array *v, struct svalue *s,INT32 start)   {    INT32 e;   #ifdef PIKE_DEBUG    if(start<0)    fatal("Start of find_index is less than zero.\n");   #endif       check_destructed(s);      #ifdef PIKE_DEBUG
pike.git/src/array.c:478:    v->type_field=t;    }    }    return -1;   }      /*    * Slice a pice of an array (nondestructively)    * return an array consisting of v[start..end-1]    */ - struct array *slice_array(struct array *v,INT32 start,INT32 end) + PMOD_EXPORT struct array *slice_array(struct array *v,INT32 start,INT32 end)   {    struct array *a;      #ifdef PIKE_DEBUG    if(start > end || end>v->size || start<0)    fatal("Illegal arguments to slice_array()\n");       if(d_flag > 1) array_check_type_field(v);   #endif   
pike.git/src/array.c:507:       assign_svalues_no_free(ITEM(a), ITEM(v)+start, end-start, v->type_field);       return a;   }      /*    * Slice a pice of an array (nondestructively)    * return an array consisting of v[start..end-1]    */ - struct array *friendly_slice_array(struct array *v,INT32 start,INT32 end) + PMOD_EXPORT struct array *friendly_slice_array(struct array *v,INT32 start,INT32 end)   {    struct array *a;      #ifdef PIKE_DEBUG    if(start > end || end>v->size || start<0)    fatal("Illegal arguments to slice_array()\n");       if(d_flag > 1) array_check_type_field(v);   #endif   
pike.git/src/array.c:529:    a->type_field = v->type_field;       assign_svalues_no_free(ITEM(a), ITEM(v)+start, end-start, v->type_field);       return a;   }      /*    * Copy an array    */ - struct array *copy_array(struct array *v) + PMOD_EXPORT struct array *copy_array(struct array *v)   {    struct array *a;       a=allocate_array_no_init(v->size, 0);    a->type_field = v->type_field;       assign_svalues_no_free(ITEM(a), ITEM(v), v->size, v->type_field);       return a;   }      /*    * Clean an array from destructed objects    */ - void check_array_for_destruct(struct array *v) + PMOD_EXPORT void check_array_for_destruct(struct array *v)   {    int e;    INT16 types;       types = 0;   #ifdef PIKE_DEBUG    if(d_flag > 1) array_check_type_field(v);   #endif    if(v->type_field & (BIT_OBJECT | BIT_FUNCTION))    {
pike.git/src/array.c:581:    }    v->type_field = types;    }   }      /*    * This function finds the index of any destructed object in a set    * it could be optimized to search out the object part with a binary    * search lookup if the array is mixed    */ - INT32 array_find_destructed_object(struct array *v) + PMOD_EXPORT INT32 array_find_destructed_object(struct array *v)   {    INT32 e;    TYPE_FIELD types;   #ifdef PIKE_DEBUG    if(d_flag > 1) array_check_type_field(v);   #endif    if(v->type_field & (BIT_OBJECT | BIT_FUNCTION))    {    types=0;    for(e=0; e<v->size; e++)
pike.git/src/array.c:746:      #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       - void sort_array_destructively(struct array *v) + PMOD_EXPORT void sort_array_destructively(struct array *v)   {    if(!v->size) return;    low_sort_svalues(ITEM(v), ITEM(v)+v->size-1);   }            /*    * return an 'order' suitable for making mappings and multisets    */ - INT32 *get_set_order(struct array *a) + PMOD_EXPORT INT32 *get_set_order(struct array *a)   {    return get_order(a, set_svalue_cmpfun);   }      /*    * return an 'order' suitable for switches.    *    * Note: This is used by encode_value_canonic(). It must keep the    * sorting rules for all the types that function allows in multiset    * and mapping indices.    */ - INT32 *get_switch_order(struct array *a) + PMOD_EXPORT INT32 *get_switch_order(struct array *a)   {    return get_order(a, switch_svalue_cmpfun);   }         /*    * return an 'order' suitable for sorting.    */ - INT32 *get_alpha_order(struct array *a) + PMOD_EXPORT INT32 *get_alpha_order(struct array *a)   {    return get_order(a, alpha_svalue_cmpfun);   }         static INT32 low_lookup(struct array *v,    struct svalue *s,    cmpfun fun)   {    INT32 a,b,c;
pike.git/src/array.c:845:    if( ((BIT_MIXED << s->type) & BIT_MIXED & a->type_field) == 0)    return ~a->size;       return low_lookup(a,s,switch_svalue_cmpfun);   }         /*    * reorganize an array in the order specifyed by 'order'    */ - struct array *order_array(struct array *v, INT32 *order) + PMOD_EXPORT struct array *order_array(struct array *v, INT32 *order)   {    reorder((char *)ITEM(v),v->size,sizeof(struct svalue),order);    return v;   }         /*    * copy and reorganize an array    */ - struct array *reorder_and_copy_array(struct array *v, INT32 *order) + PMOD_EXPORT struct array *reorder_and_copy_array(struct array *v, 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;   }      /* Maybe I should have a 'clean' flag for this computation */ - void array_fix_type_field(struct array *v) + PMOD_EXPORT void array_fix_type_field(struct array *v)   {    int e;    TYPE_FIELD t;       t=0;       if(v->flags & ARRAY_LVALUE)    {    v->type_field=BIT_MIXED;    return;
pike.git/src/array.c:922: Inside #if defined(PIKE_DEBUG)
   }       if(t & ~(v->type_field))    {    describe(v);    fatal("Type field out of order!\n");    }   }   #endif    - struct array *compact_array(struct array *v) { return v; } + PMOD_EXPORT struct array *compact_array(struct array *v) { return v; }      /*    * Get a pointer to the 'union anything' specified IF it is of the specified    * type. The 'union anything' may be changed, but not the type.    */   union anything *low_array_get_item_ptr(struct array *a,    INT32 ind,    TYPE_T t)   {    if(ITEM(a)[ind].type == t) return & (ITEM(a)[ind].u);
pike.git/src/array.c:1029:       *ret=(ptr-ret-1);       return ret;   }      /*    * This routine merges two arrays in the order specified by 'zipper'    * zipper normally produced by merge() above    */ - struct array *array_zip(struct array *a, struct array *b,INT32 *zipper) + PMOD_EXPORT struct array *array_zip(struct array *a, struct array *b,INT32 *zipper)   {    INT32 size,e;    struct array *ret;    size=zipper[0];    zipper++;       ret=allocate_array_no_init(size,0);    for(e=0; e<size; e++)    {    if(*zipper >= 0)    assign_svalue_no_free(ITEM(ret)+e, ITEM(a)+*zipper);    else    assign_svalue_no_free(ITEM(ret)+e, ITEM(b)+~*zipper);    zipper++;    }    ret->type_field = a->type_field | b->type_field;    return ret;   }    - struct array *add_arrays(struct svalue *argp, INT32 args) + PMOD_EXPORT struct array *add_arrays(struct svalue *argp, INT32 args)   {    INT32 e, size;    struct array *v;       for(size=e=0;e<args;e++)    size+=argp[e].u.array->size;       if(args && argp[0].u.array->refs==1)    {    e=argp[0].u.array->size;
pike.git/src/array.c:1083:    assign_svalues_no_free(ITEM(v)+size,    ITEM(argp[e].u.array),    argp[e].u.array->size,    argp[e].u.array->type_field);    size+=argp[e].u.array->size;    }       return v;   }    - int array_equal_p(struct array *a, struct array *b, struct processing *p) + PMOD_EXPORT int array_equal_p(struct array *a, struct array *b, struct processing *p)   {    struct processing curr;    INT32 e;       if(a == b) return 1;    if(a->size != b->size) return 0;    if(!a->size) return 1;      #ifdef PIKE_DEBUG    if(d_flag > 1)
pike.git/src/array.c:1155:    }   }            /*    * merge two arrays and retain their order, this is done by arranging them    * into ordered sets, merging them as sets and then rearranging the zipper    * before zipping the sets together.    */ - struct array *merge_array_with_order(struct array *a, struct array *b,INT32 op) + PMOD_EXPORT struct array *merge_array_with_order(struct array *a, struct array *b,INT32 op)   {    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);   
pike.git/src/array.c:1197:   #undef CMP   #undef TYPE   #undef ID         /*    * merge two arrays and retain their order, this is done by arranging them    * into ordered sets, merging them as sets and then rearranging the zipper    * before zipping the sets together.    */ - struct array *merge_array_without_order2(struct array *a, struct array *b,INT32 op) + PMOD_EXPORT struct array *merge_array_without_order2(struct array *a, struct array *b,INT32 op)   {    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);
pike.git/src/array.c:1270:    free_array(a);    free_array(b);       return ret;   }         /* merge two arrays without paying attention to the order    * the elements has presently    */ - struct array *merge_array_without_order(struct array *a, + PMOD_EXPORT struct array *merge_array_without_order(struct array *a,    struct array *b,    INT32 op)   {   #if 0    INT32 *zipper;    struct array *tmpa,*tmpb,*ret;       if(ordera) { free((char *)ordera); ordera=0; }    if(orderb) { free((char *)orderb); orderb=0; }   
pike.git/src/array.c:1306: Inside #if 0
   return ret;      #else    add_ref(a);    add_ref(b);    return merge_array_without_order2(a,b,op);   #endif   }      /* subtract an array from another */ - struct array *subtract_arrays(struct array *a, struct array *b) + PMOD_EXPORT struct array *subtract_arrays(struct array *a, struct array *b)   {   #ifdef PIKE_DEBUG    if(d_flag > 1)    {    array_check_type_field(b);    }   #endif    check_array_for_destruct(a);       if(a->type_field & b->type_field)
pike.git/src/array.c:1330:    if(a->refs == 1)    {    add_ref(a);    return a;    }    return slice_array(a,0,a->size);    }   }      /* and two arrays */ - struct array *and_arrays(struct array *a, struct array *b) + PMOD_EXPORT struct array *and_arrays(struct array *a, struct array *b)   {   #ifdef PIKE_DEBUG    if(d_flag > 1)    {    array_check_type_field(b);    }   #endif    check_array_for_destruct(a);       if(a->type_field & b->type_field)
pike.git/src/array.c:1442:    s.u.array=a;    return mkconstantsvaluenode(&s);    }else{    node *ret=0;    for(e=0; e<a->size; e++)    ret=mknode(F_ARG_LIST,ret,mksvaluenode(ITEM(a)+e));    return mkefuncallnode("aggregate",ret);    }   }    - void push_array_items(struct array *a) + 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);    Pike_sp += a->size;    a->size=0;    free_array(a);    }else{
pike.git/src/array.c:1472:    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);    }   }    - void simple_describe_array(struct array *a) + PMOD_EXPORT void simple_describe_array(struct array *a)   {    char *s;    init_buf();    describe_array_low(a,0,0);    s=simple_free_buf();    fprintf(stderr,"({\n%s\n})\n",s);    free(s);   }      void describe_index(struct array *a,
pike.git/src/array.c:1524:    sprintf(buf, a->size == 1 ? "({ /* %ld element */\n" :    "({ /* %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("})");   }    - struct array *aggregate_array(INT32 args) + PMOD_EXPORT struct array *aggregate_array(INT32 args)   {    struct array *a;       a=allocate_array_no_init(args,0);    MEMCPY((char *)ITEM(a),(char *)(Pike_sp-args),args*sizeof(struct svalue));    a->type_field=BIT_MIXED;    Pike_sp-=args;    DO_IF_DMALLOC(while(args--) dmalloc_touch_svalue(Pike_sp + args));    return a;   }    - struct array *append_array(struct array *a, struct svalue *s) + PMOD_EXPORT struct array *append_array(struct array *a, struct svalue *s)   {    a=resize_array(a,a->size+1);    array_set_index(a, a->size-1, s);    return a;   }    - struct array *explode(struct pike_string *str, + PMOD_EXPORT struct array *explode(struct pike_string *str,    struct pike_string *del)   {    INT32 e;    struct array *ret;    char *s, *end, *tmp;      #if 0    if(!str->len)    {    return allocate_array_no_init(0,0);
pike.git/src/array.c:1619:    (s-str->str)>>str->size_shift,    (end-s)>>str->size_shift);       ITEM(ret)[ret->size].type=T_STRING;    ret->size++;    }    ret->type_field=BIT_STRING;    return ret;   }    - struct pike_string *implode(struct array *a,struct pike_string *del) + PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del)   {    INT32 len,e, inited;    PCHARP r;    struct pike_string *ret,*tmp;    int max_shift=0;       len=0;       for(e=0;e<a->size;e++)    {
pike.git/src/array.c:1662:    inited=1;    tmp=ITEM(a)[e].u.string;    pike_string_cpy(r,tmp);    INC_PCHARP(r,tmp->len);    len++;    }    }    return low_end_shared_string(ret);   }    - struct array *copy_array_recursively(struct array *a,struct processing *p) + PMOD_EXPORT struct array *copy_array_recursively(struct array *a,struct processing *p)   {    struct processing doing;    struct array *ret;      #ifdef PIKE_DEBUG    if(d_flag > 1) array_check_type_field(a);   #endif       doing.next=p;    doing.pointer_a=(void *)a;
pike.git/src/array.c:1692:       ret=allocate_array_no_init(a->size,0);    doing.pointer_b=(void *)ret;       copy_svalues_recursively_no_free(ITEM(ret),ITEM(a),a->size,&doing);       ret->type_field=a->type_field;    return ret;   }    - void apply_array(struct array *a, INT32 args) + PMOD_EXPORT void apply_array(struct array *a, INT32 args)   {    INT32 e;    struct array *ret;    INT32 argp;       argp=Pike_sp-args - Pike_interpreter.evaluator_stack;       check_stack(a->size + args + 1);    check_array_for_destruct(a);    for(e=0;e<a->size;e++)    {    assign_svalues_no_free(Pike_sp,Pike_interpreter.evaluator_stack+argp,args,BIT_MIXED);    Pike_sp+=args;    apply_svalue(ITEM(a)+e,args);    }    ret=aggregate_array(a->size);    pop_n_elems(args);    push_array(ret);   }    - struct array *reverse_array(struct array *a) + PMOD_EXPORT struct array *reverse_array(struct array *a)   {    INT32 e;    struct array *ret;       /* FIXME: Check refs so we might optimize */    ret=allocate_array_no_init(a->size,0);    for(e=0;e<a->size;e++)    assign_svalue_no_free(ITEM(ret)+e,ITEM(a)+a->size+~e);    return ret;   }    - void array_replace(struct array *a, + PMOD_EXPORT void array_replace(struct array *a,    struct svalue *from,    struct svalue *to)   {    INT32 i = -1;       while((i=array_search(a,from,i+1)) >= 0) array_set_index(a,i,to);   }      #ifdef PIKE_DEBUG - void check_array(struct array *a) + PMOD_EXPORT void check_array(struct array *a)   {    INT32 e;       if(a->next->prev != a)    fatal("Array check: a->next->prev != a\n");       if(a->size > a->malloced_size)    fatal("Array is larger than malloced block!\n");       if(a->refs <=0 )
pike.git/src/array.c:2042:    for(m=empty_array.next;m!=&empty_array;m=m->next)    {    num++;    size+=sizeof(struct array)+    sizeof(struct svalue) * (m->malloced_size - 1);    }    *num_=num;    *size_=size;   }    - struct array *explode_array(struct array *a, struct array *b) + PMOD_EXPORT struct array *explode_array(struct array *a, struct array *b)   {    INT32 e,d,q,start;    struct array *tmp;       q=start=0;   #if 0    if(!a->size)    {    return allocate_array_no_init(0,0);    }
pike.git/src/array.c:2085:    }else{    check_stack(a->size);    for(e=0;e<a->size;e++) push_array(friendly_slice_array(a, e, e+1));    q=a->size;    }    tmp=aggregate_array(q);    if(tmp->size) tmp->type_field=BIT_ARRAY;    return tmp;   }    - struct array *implode_array(struct array *a, struct array *b) + PMOD_EXPORT struct array *implode_array(struct array *a, struct array *b)   {    INT32 e,size;    struct array *ret;    size=0;    for(e=0;e<a->size;e++)    {    if(ITEM(a)[e].type!=T_ARRAY)    error("Implode array contains non-arrays.\n");    size+=ITEM(a)[e].u.array->size;    }