Пример #1
0
/*-------------------------------------------------------------------------*/
void
check_wizlist_for_destr (void)

/* Check the 'extra' info in all wizinfo and remove destructed objects
 * and closures.
 */

{
    wiz_list_t *wl;

    for (wl = &default_wizlist_entry; wl; )
    {
        size_t num;
        svalue_t *item;

        if (wl->extra.type == T_POINTER)
        {
            num = VEC_SIZE(wl->extra.u.vec);
            item = &(wl->extra.u.vec->item[0]);
        }
        else
        {
            num = 1;
            item = &(wl->extra);
        }

        for ( ; num != 0 ; item++, num--)
        {
            switch(item->type)
            {
            case T_POINTER:
                check_for_destr(item->u.vec);
                break;
            case T_MAPPING:
                check_map_for_destr(item->u.map);
                break;
            case T_OBJECT:
            case T_CLOSURE:
                if (destructed_object_ref(item))
                    assign_svalue(item, &const0);
                break;
            default:
                NOOP;
                break;
            }
        }

        if (wl == &default_wizlist_entry)
            wl = all_wiz;
        else
            wl = wl->next;
    }
} /* check_wizlist_for_destr() */
Пример #2
0
/*-------------------------------------------------------------------------*/
void
struct_check_for_destr ( struct_t * pStruct )

/* Remove all references to destructed objects from <pStruct>.
 */

{
    int member, num_members;
    svalue_t * svp;

    num_members = struct_size(pStruct);

    for (member = 0, svp = pStruct->member
        ; member < num_members
        ; member++, svp++
        )
    {
        if (destructed_object_ref(svp))
        {
            free_svalue(svp);
            put_number(svp, 0);
        }
    }
} /* struct_check_for_destr() */
Пример #3
0
/*-------------------------------------------------------------------------*/
vector_t *
order_alist (svalue_t *inlists, int listnum, Bool reuse)

/* Order the alist <inlists> and return a new vector with it. The sorting
 * order is the internal order defined by alist_cmp().
 *
 * <inlists> is a vector of <listnum> vectors:
 *   <inlists> = ({ ({ keys }), ({ data1 }), ..., ({ data<listnum-1> }) })
 *
 * If <reuse> is true, the vectors of <inlists> are reused for the
 * vectors of the result when possible, and their entries in <inlists> are
 * set to T_INVALID.
 *
 * As a side effect, strings in the key vector are made shared, and
 * destructed objects in key and data vectors are replaced by svalue 0s.
 *
 * This function is also called by the compiler for constant expressions.
 */

{
    vector_t *outlist;   /* The result vector of vectors */
    vector_t *v;         /* Aux vector pointer */
    svalue_t *outlists;  /* Next element in outlist to fill in */
    ptrdiff_t * sorted;  /* The vector elements in sorted order */
    svalue_t *inpnt;     /* Pointer to the value to copy into the result */
    mp_int keynum;       /* Number of keys */
    int i, j;

    keynum = (mp_int)VEC_SIZE(inlists[0].u.vec);

    /* Get the sorting order */

    sorted = get_array_order(inlists[0].u.vec);

    /* Generate the result vectors from the sorting order.
     */

    outlist = allocate_array(listnum);
    outlists = outlist->item;

    /* Copy the elements from all inlist vectors into the outlist
     * vectors.
     *
     * At the beginning of every loop v points to the vector to
     * use as the next 'out' vector. It may be a re-used 'in' vector
     * from the previous run.
     */
    v = allocate_array(keynum);
    for (i = listnum; --i >= 0; ) {

        svalue_t *outpnt; /* Next result value element to fill in */

        /* Set the new array v as the next 'out' vector, and init outpnt
         * and offs.
         */
        put_array(outlists + i, v);
        outpnt = v->item;

        v = inlists[i].u.vec; /* Next vector to fill if reusable */

        /* Copy the elements.
         * For a reusable 'in' vector, a simple memory copy is sufficient.
         * For a new vector, a full assignment is due to keep the refcounters
         * happy.
         */
        if (reuse && inlists[i].u.vec->ref == 1) {

            if (i) /* not the last iteration */
                inlists[i].type = T_INVALID;

            for (j = keynum; --j >= 0; ) {
                inpnt = inlists[i].u.vec->item + sorted[j];
                if (destructed_object_ref(inpnt))
                {
                    free_svalue(inpnt);
                    put_number(outpnt, 0);
                    outpnt++;
                } else {
                    *outpnt++ = *inpnt;
                }
                inpnt->type = T_INVALID;
            }

        } else {

            if (i) /* Not the last iteration: get new out-vector */
                v = allocate_array(keynum);

            for (j = keynum; --j >= 0; ) {
                inpnt = inlists[i].u.vec->item + sorted[j];
                if (destructed_object_ref(inpnt))
                {
                    put_number(outpnt, 0);
                    outpnt++;
                } else {
                    assign_svalue_no_free(outpnt++, inpnt);
                }
            }
        } /* if (reuse) */
    } /* for (listnum) */

    xfree(sorted);

    return outlist;
} /* order_alist() */
Пример #4
0
/*-------------------------------------------------------------------------*/
svalue_t *
v_assoc (svalue_t *sp, int num_arg)

/* EFUN assoc()
 *
 *     int   assoc (mixed key, mixed *keys)
 *     mixed assoc (mixed key, mixed *alist [, mixed fail] )
 *     mixed assoc (mixed key, mixed *keys, mixed *data [, mixed fail])
 *
 * Search for <key> in the <alist> resp. in the <keys>.
 *
 * When the key list of an alist contains destructed objects
 * it is better not to free them till the next reordering by
 * order_alist to retain the alist property.
 */

{
    svalue_t *args;
    vector_t *keys,*data;
    svalue_t *fail_val;
    int ix;

    args = sp -num_arg +1;

    /* Analyse the arguments */
    if ( !VEC_SIZE(args[1].u.vec)
     ||  args[1].u.vec->item[0].type != T_POINTER )
    {
        keys = args[1].u.vec;
        if (num_arg == 2)
        {
            data = NULL;
        }
        else
        {
            if (args[2].type != T_POINTER
             || VEC_SIZE(args[2].u.vec) != VEC_SIZE(keys))
            {
                errorf("Number of values in key and data arrays differ.\n");
                /* NOTREACHED */
                return sp;
            }
            data = args[2].u.vec;
        }
        if (num_arg == 4)
        {
            fail_val = &args[3];
        }
        else
        {
            fail_val = &const0;
        }
    }
    else
    {
        keys = args[1].u.vec->item[0].u.vec;
        if (VEC_SIZE(args[1].u.vec) > 1)
        {
            if (args[1].u.vec->item[1].type != T_POINTER
             || VEC_SIZE(args[1].u.vec->item[1].u.vec) != VEC_SIZE(keys))
            {
                errorf("Number of values in key and data arrays differ.\n");
                /* NOTREACHED */
                return sp;
            }
            data = args[1].u.vec->item[1].u.vec;
        }
        else
        {
            data = NULL;
        }

        if (num_arg == 3) fail_val = &args[2];
        else if (num_arg == 2) fail_val = &const0;
        else
        {
            errorf("too many args to efun assoc\n");
            /* NOTREACHED */
            return sp;
        }
    }

    /* Call lookup_key() and push the result */
    ix = lookup_key(&args[0],keys);
    if (data == NULL)
    {
        sp = pop_n_elems(num_arg, sp);
        push_number(sp, ix < 0 ? -1 : ix);
    }
    else
    {
        assign_svalue(args
                     , ix < 0
                       ? fail_val
                       : (destructed_object_ref(&data->item[ix])
                         ? &const0
                         : &data->item[ix])
                     );
        sp = pop_n_elems(num_arg-1, sp);
    }

    return sp;
} /* v_assoc() */
Пример #5
0
/*-------------------------------------------------------------------------*/
svalue_t *
x_map_struct (svalue_t *sp, int num_arg)

/* EFUN map() on structs
 *
 *   mixed * map(struct arg, string func, string|object ob, mixed extra...)
 *   mixed * map(struct arg, closure cl, mixed extra...)
 *   mixed * map(struct arr, mapping map [, int col])
 *
 * Map the elements of <arr> through a filter defined by the other
 * arguments, and return an array of the elements returned by the filter.
 *
 * The filter can be a function call:
 *
 *    <obj>-><fun>(elem, <extra>...)
 *
 * or a mapping query:
 *
 *    <map>[elem[,idx]]
 *
 * In the mapping case, if <map>[elem[,idx]] does not exist, the original
 * value is returned in the result.
 * [Note: argument type and range checking for idx is done in v_map()]
 *
 * <obj> can both be an object reference or a filename. If <ob> is
 * omitted, or neither an object nor a string, then this_object() is used.
 *
 * As a bonus, all references to destructed objects in <arr> are replaced
 * by proper 0es.
 */

{
    struct_t   *st;
    struct_t   *res;
    svalue_t   *arg;
    svalue_t   *v, *w, *x;
    mp_int      cnt;

    inter_sp = sp;
    arg = sp - num_arg + 1;

    st = arg->u.strct;
    cnt = (mp_int)struct_size(st);

    if (arg[1].type == T_MAPPING)
    {
        /* --- Map through mapping --- */

        mapping_t *m;
        p_int column = 0; /* mapping column to use */

        m = arg[1].u.map;

        if (num_arg > 2)
            column = arg[2].u.number;

        res = struct_new(st->type);
        if (!res)
            errorf("(map_struct) Out of memory: struct[%"PRIdMPINT"] for result\n", cnt);
        push_struct(inter_sp, res); /* In case of errors */

        for (w = st->member, x = res->member; --cnt >= 0; w++, x++)
        {
            if (destructed_object_ref(w))
                assign_svalue(w, &const0);

            v = get_map_value(m, w);
            if (v == &const0)
                assign_svalue_no_free(x, w);
            else
                assign_svalue_no_free(x, v + column);
        }

        if (num_arg > 2)
            free_svalue(arg+2);
        free_svalue(arg+1); /* the mapping */
        sp = arg;
    }
    else
    {
        /* --- Map through function call --- */

        callback_t  cb;
        int         error_index;

        error_index = setup_efun_callback(&cb, arg+1, num_arg-1);
        if (error_index >= 0)
        {
            vefun_bad_arg(error_index+2, arg);
            /* NOTREACHED */
            return arg;
        }
        inter_sp = sp = arg+1;
        put_callback(sp, &cb);
        num_arg = 2;

        res = struct_new(st->type);
        if (!res)
            errorf("(map_struct) Out of memory: struct[%"PRIdMPINT"] for result\n", cnt);
        push_struct(inter_sp, res); /* In case of errors */

        /* Loop through arr and res, mapping the values from arr */
        for (w = st->member, x = res->member; --cnt >= 0; w++, x++)
        {
            if (current_object->flags & O_DESTRUCTED)
                continue;

            if (destructed_object_ref(w))
                assign_svalue(w, &const0);

            if (!callback_object(&cb))
                errorf("object used by map_array destructed");

            push_svalue(w);

            v = apply_callback(&cb, 1);
            if (v)
            {
                transfer_svalue_no_free(x, v);
                v->type = T_INVALID;
            }
        }

        free_callback(&cb);
    }
    
    /* The arguments have been removed already, now just replace
     * the struct on the stack with the result.
     */
    free_struct(st);
    arg->u.strct = res; /* Keep svalue type T_STRUCT */

    return arg;
} /* x_map_struct () */