Пример #1
0
/* <string> <index> <int> put - */
static int
zput(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr op1 = op - 1;
    os_ptr op2 = op1 - 1;
    byte *sdata;
    uint ssize;

    switch (r_type(op2)) {
	case t_dictionary:
	    if (i_ctx_p->in_superexec == 0)
		check_dict_write(*op2);
	    {
		int code = idict_put(op2, op1, op);

		if (code < 0)
		    return code;	/* error */
	    }
	    break;
	case t_array:
	    check_write(*op2);
	    check_int_ltu(*op1, r_size(op2));
	    store_check_dest(op2, op);
	    {
		ref *eltp = op2->value.refs + (uint) op1->value.intval;

		ref_assign_old(op2, eltp, op, "put");
	    }
	    break;
	case t_mixedarray:	/* packed arrays are read-only */
	case t_shortarray:
	    return_error(e_invalidaccess);
	case t_string:
	    sdata = op2->value.bytes;
	    ssize = r_size(op2);
str:	    check_write(*op2);
	    check_int_ltu(*op1, ssize);
	    check_int_leu(*op, 0xff);
	    sdata[(uint)op1->value.intval] = (byte)op->value.intval;
	    break;
	case t_astruct:
	    if (gs_object_type(imemory, op2->value.pstruct) != &st_bytes)
		return_error(e_typecheck);
	    sdata = r_ptr(op2, byte);
	    ssize = gs_object_size(imemory, op2->value.pstruct);
	    goto str;
	default:
	    return_op_typecheck(op2);
    }
    pop(3);
    return 0;
}
Пример #2
0
/* Note that this is now internal, since it only handles "new" arrays. */
static int
array_new_indexed_param_write(iparam_list * iplist, const ref * pkey,
			  const ref * pvalue)
{
    const ref *const arr = &((dict_param_list *)iplist)->dict;
    ref *eltp;

    if (!r_has_type(pkey, t_integer))
	return_error(e_typecheck);
    check_int_ltu(*pkey, r_size(arr));
    store_check_dest(arr, pvalue);
    eltp = arr->value.refs + pkey->value.intval;
    /* ref_assign_new(eltp, pvalue); */
    ref_assign(eltp, pvalue);
    r_set_attrs(eltp, imemory_new_mask(iplist->ref_memory));
    return 0;
}
Пример #3
0
static int
zbind(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    uint depth = 1;
    ref defn;
    register os_ptr bsp;

    switch (r_type(op)) {
        case t_array:
            if (!r_has_attr(op, a_write)) {
                return 0;	/* per PLRM3 */
            }
        case t_mixedarray:
        case t_shortarray:
            defn = *op;
            break;
        case t_oparray:
            defn = *op->value.const_refs;
            break;
        default:
            return_op_typecheck(op);
    }
    push(1);
    *op = defn;
    bsp = op;
    /*
     * We must not make the top-level procedure read-only,
     * but we must bind it even if it is read-only already.
     *
     * Here are the invariants for the following loop:
     *      `depth' elements have been pushed on the ostack;
     *      For i < depth, p = ref_stack_index(&o_stack, i):
     *        *p is an array (or packedarray) ref.
     */
    while (depth) {
        while (r_size(bsp)) {
            ref_packed *const tpp = (ref_packed *)bsp->value.packed; /* break const */

            r_dec_size(bsp, 1);
            if (r_is_packed(tpp)) {
                /* Check for a packed executable name */
                ushort elt = *tpp;

                if (r_packed_is_exec_name(&elt)) {
                    ref nref;
                    ref *pvalue;

                    name_index_ref(imemory, packed_name_index(&elt),
                                   &nref);
                    if ((pvalue = dict_find_name(&nref)) != 0 &&
                        r_is_ex_oper(pvalue)
                        ) {
                        store_check_dest(bsp, pvalue);
                        /*
                         * Always save the change, since this can only
                         * happen once.
                         */
                        ref_do_save(bsp, tpp, "bind");
                        *tpp = pt_tag(pt_executable_operator) +
                            op_index(pvalue);
                    }
                }
                bsp->value.packed = tpp + 1;
            } else {
                ref *const tp = bsp->value.refs++;

                switch (r_type(tp)) {
                    case t_name:	/* bind the name if an operator */
                        if (r_has_attr(tp, a_executable)) {
                            ref *pvalue;

                            if ((pvalue = dict_find_name(tp)) != 0 &&
                                r_is_ex_oper(pvalue)
                                ) {
                                store_check_dest(bsp, pvalue);
                                ref_assign_old(bsp, tp, pvalue, "bind");
                            }
                        }
                        break;
                    case t_array:	/* push into array if writable */
                        if (!r_has_attr(tp, a_write))
                            break;
                    case t_mixedarray:
                    case t_shortarray:
                        if (r_has_attr(tp, a_executable)) {
                            /* Make reference read-only */
                            r_clear_attrs(tp, a_write);
                            if (bsp >= ostop) {
                                /* Push a new stack block. */
                                ref temp;
                                int code;

                                temp = *tp;
                                osp = bsp;
                                code = ref_stack_push(&o_stack, 1);
                                if (code < 0) {
                                    ref_stack_pop(&o_stack, depth);
                                    return_error(code);
                                }
                                bsp = osp;
                                *bsp = temp;
                            } else
                                *++bsp = *tp;
                            depth++;
                        }
                }
            }
        }
        bsp--;
        depth--;
        if (bsp < osbot) {	/* Pop back to the previous stack block. */
            osp = bsp;
            ref_stack_pop_block(&o_stack);
            bsp = osp;
        }
    }
    osp = bsp;
    return 0;
}
Пример #4
0
/*
 * Enter a key-value pair in a dictionary.
 * See idict.h for the possible return values.
 */
int
dict_put(ref * pdref /* t_dictionary */ , const ref * pkey, const ref * pvalue,
         dict_stack_t *pds)
{
    dict *pdict = pdref->value.pdict;
    gs_ref_memory_t *mem = dict_memory(pdict);
    gs_memory_t *pmem = dict_mem(pdict);
    int rcode = 0;
    int code;
    ref *pvslot, kname;

    /* Check the value. */
    store_check_dest(pdref, pvalue);
  top:if ((code = dict_find(pdref, pkey, &pvslot)) <= 0) {	/* not found *//* Check for overflow */
        uint index;

        switch (code) {
            case 0:
                break;
            case gs_error_dictfull:
                if (!pmem->gs_lib_ctx->dict_auto_expand)
                    return_error(gs_error_dictfull);
                code = dict_grow(pdref, pds);
                if (code < 0)
                    return code;
                goto top;	/* keep things simple */
            default:		/* gs_error_typecheck */
                return code;
        }
        index = pvslot - pdict->values.value.refs;
        /* If the key is a string, convert it to a name. */
        if (r_has_type(pkey, t_string)) {
            int code;

            if (!r_has_attr(pkey, a_read))
                return_error(gs_error_invalidaccess);
            code = name_from_string(pmem, pkey, &kname);
            if (code < 0)
                return code;
            pkey = &kname;
        }
        if (dict_is_packed(pdict)) {
            ref_packed *kp;

            if (!r_has_type(pkey, t_name) ||
                name_index(pmem, pkey) > packed_name_max_index
                ) {		/* Change to unpacked representation. */
                int code = dict_unpack(pdref, pds);

                if (code < 0)
                    return code;
                goto top;
            }
            kp = pdict->keys.value.writable_packed + index;
            if (ref_must_save_in(mem, &pdict->keys)) {	/* See initial comment for why it is safe */
                /* not to save the change if the keys */
                /* array itself is new. */
                ref_do_save_in(mem, &pdict->keys, kp, "dict_put(key)");
            }
            *kp = pt_tag(pt_literal_name) + name_index(pmem, pkey);
        } else {
            ref *kp = pdict->keys.value.refs + index;

            if_debug2m('d', (const gs_memory_t *)mem, "[d]0x%lx: fill key at 0x%lx\n",
                       (ulong) pdict, (ulong) kp);
            store_check_dest(pdref, pkey);
            ref_assign_old_in(mem, &pdict->keys, kp, pkey,
                              "dict_put(key)");	/* set key of pair */
        }
        ref_save_in(mem, pdref, &pdict->count, "dict_put(count)");
        pdict->count.value.intval++;
        /* If the key is a name, update its 1-element cache. */
        if (r_has_type(pkey, t_name)) {
            name *pname = pkey->value.pname;

            if (pname->pvalue == pv_no_defn &&
                CAN_SET_PVALUE_CACHE(pds, pdref, mem)
                ) {		/* Set the cache. */
                if_debug0m('d', (const gs_memory_t *)mem, "[d]set cache\n");
                pname->pvalue = pvslot;
            } else {		/* The cache can't be used. */
                if_debug0m('d', (const gs_memory_t *)mem, "[d]no cache\n");
                pname->pvalue = pv_other;
            }
        }
        rcode = 1;
    }
    if_debug8m('d', (const gs_memory_t *)mem,
               "[d]0x%lx: put key 0x%lx 0x%lx\n  value at 0x%lx: old 0x%lx 0x%lx, new 0x%lx 0x%lx\n",
               (ulong) pdref->value.pdict,
               ((const ulong *)pkey)[0], ((const ulong *)pkey)[1],
               (ulong) pvslot,
               ((const ulong *)pvslot)[0], ((const ulong *)pvslot)[1],
               ((const ulong *)pvalue)[0], ((const ulong *)pvalue)[1]);
    ref_assign_old_in(mem, &pdref->value.pdict->values, pvslot, pvalue,
                      "dict_put(value)");
    return rcode;
}