Esempio n. 1
0
/*
 * Ensure that a dictionary uses the unpacked representation for keys.
 * We can't just use dict_resize, because the values slots mustn't move.
 */
int
dict_unpack(ref * pdref, dict_stack_t *pds)
{
    dict *pdict = pdref->value.pdict;

    if (!dict_is_packed(pdict))
        return 0;		/* nothing to do */
    {
        gs_ref_memory_t *mem = dict_memory(pdict);
        uint count = nslots(pdict);
        const ref_packed *okp = pdict->keys.value.packed;
        ref old_keys;
        int code;
        ref *nkp;

        old_keys = pdict->keys;
        if (ref_must_save_in(mem, &old_keys))
            ref_do_save_in(mem, pdref, &pdict->keys, "dict_unpack(keys)");
        code = dict_create_unpacked_keys(count, pdref);
        if (code < 0)
            return code;
        for (nkp = pdict->keys.value.refs; count--; okp++, nkp++)
            if (r_packed_is_name(okp)) {
                packed_get((const gs_memory_t *)mem, okp, nkp);
                ref_mark_new_in(mem, nkp);
            } else if (*okp == packed_key_deleted)
                r_set_attrs(nkp, a_executable);
        if (!ref_must_save_in(mem, &old_keys))
            gs_free_ref_array(mem, &old_keys, "dict_unpack(old keys)");
        if (pds)
            dstack_set_top(pds);	/* just in case */
    }
    return 0;
}
Esempio n. 2
0
/* <obj> <typenames> .type <name> */
static int
ztype(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    ref tnref;
    int code = array_get(imemory, op, (long)r_btype(op - 1), &tnref);

    if (code < 0)
	return code;
    if (!r_has_type(&tnref, t_name)) {
	/* Must be either a stack underflow or a t_[a]struct. */
	check_op(2);
	{			/* Get the type name from the structure. */
	    const char *sname =
		gs_struct_type_name_string(gs_object_type(imemory,
							  op[-1].value.pstruct));
	    int code = name_ref(imemory, (const byte *)sname, strlen(sname),
				(ref *) (op - 1), 0);

	    if (code < 0)
		return code;
	}
	r_set_attrs(op - 1, a_executable);
    } else {
	ref_assign(op - 1, &tnref);
    }
    pop(1);
    return 0;
}
Esempio n. 3
0
/* or if they are identical. */
void
packed_get(const gs_memory_t *mem, const ref_packed * packed, ref * pref)
{
    const ref_packed elt = *packed;
    uint value = elt & packed_value_mask;

    switch (elt >> r_packed_type_shift) {
	default:		/* (shouldn't happen) */
	    make_null(pref);
	    break;
	case pt_executable_operator:
	    op_index_ref(value, pref);
	    break;
	case pt_integer:
	    make_int(pref, (int)value + packed_min_intval);
	    break;
	case pt_literal_name:
	    name_index_ref(mem, value, pref);
	    break;
	case pt_executable_name:
	    name_index_ref(mem, value, pref);
	    r_set_attrs(pref, a_executable);
	    break;
	case pt_full_ref:
	case pt_full_ref + 1:
	    ref_assign(pref, (const ref *)packed);
    }
}
Esempio n. 4
0
/* The keys are allocated using the same allocator as the dictionary. */
static int
dict_create_unpacked_keys(uint asize, const ref * pdref)
{
    dict *pdict = pdref->value.pdict;
    gs_ref_memory_t *mem = dict_memory(pdict);
    int code;

    code = gs_alloc_ref_array(mem, &pdict->keys, a_all, asize,
                              "dict_create_unpacked_keys");
    if (code >= 0) {
        uint new_mask = imemory_new_mask(mem);
        ref *kp = pdict->keys.value.refs;

        r_set_attrs(&pdict->keys, new_mask);
        refset_null_new(kp, asize, new_mask);
        r_set_attrs(kp, a_executable);	/* wraparound entry */
    }
    return code;
}
Esempio n. 5
0
/* or if the object did not have the access already when modify=1. */
static int
access_check(i_ctx_t *i_ctx_p,
	     int access,	/* mask for attrs */
	     bool modify)	/* if true, reduce access */
{
    os_ptr op = osp;
    ref *aop;

    switch (r_type(op)) {
	case t_dictionary:
	    aop = dict_access_ref(op);
	    if (modify) {
		if (!r_has_attrs(aop, access))
		    return_error(e_invalidaccess);
		ref_save(op, aop, "access_check(modify)");
		r_clear_attrs(aop, a_all);
		r_set_attrs(aop, access);
		dict_set_top();
		return 0;
	    }
	    break;
	case t_array:
	case t_file:
	case t_string:
	case t_mixedarray:
	case t_shortarray:
	case t_astruct:
	case t_device:;
	    if (modify) {
		if (!r_has_attrs(op, access))
		    return_error(e_invalidaccess);
		r_clear_attrs(op, a_all);
		r_set_attrs(op, access);
		return 0;
	    }
	    aop = op;
	    break;
	default:
	    return_op_typecheck(op);
    }
    return (r_has_attrs(aop, access) ? 1 : 0);
}
Esempio n. 6
0
static int
runandhide_restore_hidden(i_ctx_t *i_ctx_p, ref *obj, ref *attrs)
{
    os_ptr op = osp;

    push(1);
    /* restore the hidden_object and its type_attrs */
    ref_assign(op, obj);
    r_clear_attrs(op, a_all);
    r_set_attrs(op, attrs->value.intval);
    return 0;
}
Esempio n. 7
0
/* Call out to a PostScript procedure. */
static int
push_callout(i_ctx_t *i_ctx_p, const char *callout_name)
{
    int code;

    check_estack(1);
    code = name_enter_string(imemory, callout_name, esp + 1);
    if (code < 0)
        return code;
    ++esp;
    r_set_attrs(esp, a_executable);
    return o_push_estack;
}
Esempio n. 8
0
/* Convert strings to executable names for build_proc_refs. */
int
build_proc_name_refs(const gs_memory_t *mem, build_proc_refs * pbuild,
                     const char *bcstr, const char *bgstr)
{
    int code;

    if (!bcstr)
        make_null(&pbuild->BuildChar);
    else {
        if ((code = name_ref(mem, (const byte *)bcstr,
                             strlen(bcstr), &pbuild->BuildChar, 0)) < 0)
            return code;
        r_set_attrs(&pbuild->BuildChar, a_executable);
    }
    if (!bgstr)
        make_null(&pbuild->BuildGlyph);
    else {
        if ((code = name_ref(mem, (const byte *)bgstr,
                             strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0)
            return code;
        r_set_attrs(&pbuild->BuildGlyph, a_executable);
    }
    return 0;
}
Esempio n. 9
0
/* - .wrapfont - */
static int
zwrapfont(i_ctx_t *i_ctx_p)
{
    gs_font *font = gs_currentfont(igs);
    gs_font_type0 *font0;
    int wmode = 0;
    int code;

    switch (font->FontType) {
    case ft_TrueType:
	code = gs_font_type0_from_type42(&font0, (gs_font_type42 *)font, wmode,
					 true, font->memory);
	if (code < 0)
	    return code;
	/*
	 * Patch up BuildChar and CIDMap.  This isn't necessary for
	 * TrueType fonts in general, only for Type 42 fonts whose
	 * BuildChar is implemented in PostScript code.
	 */
	{
	    font_data *pdata = pfont_data(font);
	    const char *bgstr = "%Type11BuildGlyph";
	    ref temp;

	    make_int(&temp, 0);
	    ref_assign(&pdata->u.type42.CIDMap, &temp);
	    code = name_ref((const byte *)bgstr, strlen(bgstr), &temp, 1);
	    if (code < 0)
		return code;
	    r_set_attrs(&temp, a_executable);
	    ref_assign(&pdata->BuildGlyph, &temp);
	}
	break;
    case ft_CID_encrypted:
    case ft_CID_user_defined:
    case ft_CID_TrueType:
	code = gs_font_type0_from_cidfont(&font0, font, wmode, NULL,
					  font->memory);
	break;
    default:
	return_error(e_rangecheck);
    }
    if (code < 0)
	return code;
    gs_setfont(igs, (gs_font *)font0);
    return 0;
}
Esempio n. 10
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;
}
Esempio n. 11
0
/* the VM space where the dictionary is allocated. */
static int
dict_create_contents(uint size, const ref * pdref, bool pack)
{
    dict *pdict = pdref->value.pdict;
    gs_ref_memory_t *mem = dict_memory(pdict);
    uint new_mask = imemory_new_mask(mem);
    uint asize = dict_round_size((size == 0 ? 1 : size));
    int code;
    register uint i;

    if (asize == 0 || asize > max_array_size - 1)	/* too large */
        return_error(gs_error_limitcheck);
    asize++;			/* allow room for wraparound entry */
    code = gs_alloc_ref_array(mem, &pdict->values, a_all, asize,
                              "dict_create_contents(values)");
    if (code < 0)
        return code;
    r_set_attrs(&pdict->values, new_mask);
    refset_null_new(pdict->values.value.refs, asize, new_mask);
    if (pack) {
        uint ksize = (asize + packed_per_ref - 1) / packed_per_ref;
        ref arr;
        ref_packed *pkp;
        ref_packed *pzp;

        code = gs_alloc_ref_array(mem, &arr, a_all, ksize,
                                  "dict_create_contents(packed keys)");
        if (code < 0)
            return code;
        pkp = (ref_packed *) arr.value.refs;
        make_tasv(&pdict->keys, t_shortarray,
                  r_space(&arr) | a_all | new_mask,
                  asize, packed, pkp);
        for (pzp = pkp, i = 0; i < asize || i % packed_per_ref; pzp++, i++)
            *pzp = packed_key_empty;
        *pkp = packed_key_deleted;	/* wraparound entry */
    } else {			/* not packed */
        int code = dict_create_unpacked_keys(asize, pdref);

        if (code < 0)
            return code;
    }
    make_tav(&pdict->count, t_integer, new_mask, intval, 0);
    make_tav(&pdict->maxlength, t_integer, new_mask, intval, size);
    return 0;
}
Esempio n. 12
0
/* Mark a ref.  Return true if new mark. */
bool
ptr_ref_mark(enum_ptr_t *pep, gc_state_t * ignored)
{
    ref_packed *rpp = (void *)pep->ptr;

    if (r_is_packed(rpp)) {
	if (r_has_pmark(rpp))
	    return false;
	r_set_pmark(rpp);
    } else {
	ref *const pref = (ref *)rpp;

	if (r_has_attr(pref, l_mark))
	    return false;
	r_set_attrs(pref, l_mark);
    }
    return true;
}
Esempio n. 13
0
/* <obj> cvx <obj> */
int
zcvx(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    ref *aop;
    uint opidx;

    check_op(1);
    /*
     * If the object is an internal operator, we can't allow it to
     * exist in executable form anywhere outside the e-stack.
     */
    if (r_has_type(op, t_operator) &&
	((opidx = op_index(op)) == 0 ||
	 op_def_is_internal(op_index_def(opidx)))
	)
	return_error(e_rangecheck);
    aop = ACCESS_REF(op);
    r_set_attrs(aop, a_executable);
    return 0;
}
Esempio n. 14
0
/* - .typenames <name1|null> ... <nameN|null> */
static int
ztypenames(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    static const char *const tnames[] = { REF_TYPE_NAME_STRINGS };
    int i;

    check_ostack(t_next_index);
    for (i = 0; i < t_next_index; i++) {
	ref *const rtnp = op + 1 + i;

	if (i >= countof(tnames) || tnames[i] == 0)
	    make_null(rtnp);
	else {
	    int code = name_enter_string(imemory, tnames[i], rtnp);

	    if (code < 0)
		return code;
	    r_set_attrs(rtnp, a_executable);
	}
    }
    osp += t_next_index;
    return 0;
}
Esempio n. 15
0
int
make_upath(i_ctx_t *i_ctx_p, ref *rupath, gs_state *pgs, gx_path *ppath,
           bool with_ucache)
{
    int size = (with_ucache ? 6 : 5);
    gs_path_enum penum;
    gs_rect bbox;
    int op;
    ref *next;
    int code;

    /* Compute the bounding box. */
    if ((code = gs_upathbbox(pgs, &bbox, true)) < 0) {
        /*
         * Note: Adobe throws 'nocurrentpoint' error, but the PLRM does
         * not list this as a possible error from 'upath', so if we are
         * not in CPSI compatibility mode, we set a reasonable default
         * bbox instead.
         */
        if (code != e_nocurrentpoint || gs_currentcpsimode(imemory))
            return code;
        bbox.p.x = bbox.p.y = bbox.q.x = bbox.q.y = 0;
    }

    code = path_length_for_upath(ppath);
    if (code < 0)
        return code;
    size += code;
    if (size >= 65536)
        return_error(e_limitcheck);

    code = ialloc_ref_array(rupath, a_all | a_executable, size,
                            "make_upath");
    if (code < 0)
        return code;
    /* Construct the path. */
    next = rupath->value.refs;
    if (with_ucache) {
        if ((code = name_enter_string(pgs->memory, "ucache", next)) < 0)
            return code;
        r_set_attrs(next, a_executable | l_new);
        ++next;
    }
    make_real_new(next, bbox.p.x);
    make_real_new(next + 1, bbox.p.y);
    make_real_new(next + 2, bbox.q.x);
    make_real_new(next + 3, bbox.q.y);
    next += 4;
    if ((code = name_enter_string(pgs->memory, "setbbox", next)) < 0)
        return code;
    r_set_attrs(next, a_executable | l_new);
    ++next;
    {
        gs_point pts[3];

        /* Patch the path in the gstate to set up the enumerator. */
        gx_path *save_path = pgs->path;

        pgs->path = ppath;
        gs_path_enum_copy_init(&penum, pgs, false);
        pgs->path = save_path;
        while ((op = gs_path_enum_next(&penum, pts)) != 0) {
            const char *opstr;

            switch (op) {
                case gs_pe_moveto:
                    opstr = "moveto";
                    goto ml;
                case gs_pe_lineto:
                    opstr = "lineto";
                  ml:make_real_new(next, pts[0].x);
                    make_real_new(next + 1, pts[0].y);
                    next += 2;
                    break;
                case gs_pe_curveto:
                    opstr = "curveto";
                    make_real_new(next, pts[0].x);
                    make_real_new(next + 1, pts[0].y);
                    make_real_new(next + 2, pts[1].x);
                    make_real_new(next + 3, pts[1].y);
                    make_real_new(next + 4, pts[2].x);
                    make_real_new(next + 5, pts[2].y);
                    next += 6;
                    break;
                case gs_pe_closepath:
                    opstr = "closepath";
                    break;
                default:
                    return_error(e_unregistered);
            }
            if ((code = name_enter_string(pgs->memory, opstr, next)) < 0)
                return code;
            r_set_attrs(next, a_executable);
            ++next;
        }
    }
    return 0;
}
Esempio n. 16
0
/* Remove an element from a dictionary. */
int
dict_undef(ref * pdref, const ref * pkey, dict_stack_t *pds)
{
    gs_ref_memory_t *mem;
    ref *pvslot;
    dict *pdict;
    uint index;
    int code = dict_find(pdref, pkey, &pvslot);

    switch (code) {
    case 0:
    case gs_error_dictfull:
        return_error(gs_error_undefined);
    case 1:
        break;
    default:			/* other error */
        return code;
    }
    /* Remove the entry from the dictionary. */
    pdict = pdref->value.pdict;
    index = pvslot - pdict->values.value.refs;
    mem = dict_memory(pdict);
    if (dict_is_packed(pdict)) {
        ref_packed *pkp = pdict->keys.value.writable_packed + index;
        bool must_save = ref_must_save_in(mem, &pdict->keys);

        if_debug3m('d', (const gs_memory_t *)mem,
                   "[d]0x%lx: removing key at 0%lx: 0x%x\n",
                   (ulong)pdict, (ulong)pkp, (uint)*pkp);
        /* See the initial comment for why it is safe not to save */
        /* the change if the keys array itself is new. */
        if (must_save)
            ref_do_save_in(mem, &pdict->keys, pkp, "dict_undef(key)");
        /*
         * Accumulating deleted entries slows down lookup.
         * Detect the easy case where we can use an empty entry
         * rather than a deleted one, namely, when the next entry
         * in the probe order is empty.
         */
        if (pkp[-1] == packed_key_empty) {
            /*
             * In this case we can replace any preceding deleted keys with
             * empty ones as well.
             */
            uint end = nslots(pdict);

            *pkp = packed_key_empty;
            if (must_save) {
                while (++index < end && *++pkp == packed_key_deleted) {
                    ref_do_save_in(mem, &pdict->keys, pkp, "dict_undef(key)");
                    *pkp = packed_key_empty;
                }
            } else {
                while (++index < end && *++pkp == packed_key_deleted)
                    *pkp = packed_key_empty;
            }
        } else
            *pkp = packed_key_deleted;
    } else {			/* not packed */
        ref *kp = pdict->keys.value.refs + index;

        if_debug4m('d', (const gs_memory_t *)mem,
                   "[d]0x%lx: removing key at 0%lx: 0x%lx 0x%lx\n",
                   (ulong)pdict, (ulong)kp, ((ulong *)kp)[0], ((ulong *)kp)[1]);
        make_null_old_in(mem, &pdict->keys, kp, "dict_undef(key)");
        /*
         * Accumulating deleted entries slows down lookup.
         * Detect the easy case where we can use an empty entry
         * rather than a deleted one, namely, when the next entry
         * in the probe order is empty.
         */
        if (!r_has_type(kp - 1, t_null) ||	/* full entry */
            r_has_attr(kp - 1, a_executable)	/* deleted or wraparound */
            )
            r_set_attrs(kp, a_executable);	/* mark as deleted */
    }
    ref_save_in(mem, pdref, &pdict->count, "dict_undef(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 (pv_valid(pname->pvalue)) {
#ifdef DEBUG
            /* Check the the cache is correct. */
            if (!(pds && dstack_dict_is_permanent(pds, pdref)))
                lprintf1("dict_undef: cached name value pointer 0x%lx is incorrect!\n",
                         (ulong) pname->pvalue);
#endif
            /* Clear the cache */
            pname->pvalue = pv_no_defn;
        }
    }
    make_null_old_in(mem, &pdict->values, pvslot, "dict_undef(value)");
    return 0;
}