Exemple #1
0
/*
 * Swap an entry from a higher level dictionary into a base dictionary.
 * elt[0] is the key, elt[1] is the current value in the Level 2 dictionary
 * (*pdict2).
 */
static int
swap_entry(i_ctx_t *i_ctx_p, ref elt[2], ref * pdict, ref * pdict2)
{
    ref *pvalue;
#ifdef PACIFY_VALGRIND
    ref old_value = { 0 };		/* current value in *pdict */
#else
    ref old_value;		/* current value in *pdict */
#endif
    int found = dict_find(pdict, &elt[0], &pvalue);

    switch (found) {
        default:		/* <0, error */
            /*
             * The only possible error here is a dictfull error, which is
             * harmless.
             */
            /* fall through */
        case 0:		/* missing */
            make_null(&old_value);
            break;
        case 1:		/* present */
            old_value = *pvalue;
    }
    /*
     * Temporarily flag the dictionaries as local, so that we don't
     * get invalidaccess errors.  (We know that they are both
     * referenced from systemdict, so they are allowed to reference
     * local objects even if they are global.)
     */
    {
        uint space2 = r_space(pdict2);
        int code;

        r_set_space(pdict2, avm_local);
        idict_put(pdict2, &elt[0], &old_value);
        if (r_has_type(&elt[1], t_null)) {
            code = idict_undef(pdict, &elt[0]);
            if (code == gs_error_undefined &&
                r_has_type(&old_value, t_null)
                )
                code = 0;
        } else {
            uint space = r_space(pdict);

            r_set_space(pdict, avm_local);
            code = idict_put(pdict, &elt[0], &elt[1]);
            r_set_space(pdict, space);
        }
        r_set_space(pdict2, space2);
        return code;
    }
}
Exemple #2
0
/*
 * This forces a "put" even if the object is not writable, and (if the
 * object is systemdict or the save level is 0) even if the value is in
 * local VM.  It is meant to be used only for replacing the value of
 * FontDirectory in systemdict when switching between local and global VM,
 * and a few similar applications.  After initialization, this operator
 * should no longer be accessible by name.
 */
static int
zforceput(i_ctx_t *i_ctx_p)
{
    os_ptr op = osp;
    os_ptr op1 = op - 1;
    os_ptr op2 = op - 2;
    int code;

    switch (r_type(op2)) {
    case t_array:
	check_int_ltu(*op1, r_size(op2));
	if (r_space(op2) > r_space(op)) {
	    if (imemory_save_level(iimemory))
		return_error(e_invalidaccess);
	}
	{
	    ref *eltp = op2->value.refs + (uint) op1->value.intval;

	    ref_assign_old(op2, eltp, op, "put");
	}
	break;
    case t_dictionary:
	if (op2->value.pdict == systemdict->value.pdict ||
	    !imemory_save_level(iimemory)
	    ) {
	    uint space = r_space(op2);

	    r_set_space(op2, avm_local);
	    code = idict_put(op2, op1, op);
	    r_set_space(op2, space);
	} else
	    code = idict_put(op2, op1, op);
	if (code < 0)
	    return code;
	break;
    default:
	return_error(e_typecheck);
    }
    pop(3);
    return 0;
}
Exemple #3
0
/* initialize the dictionaries that hold operator definitions. */
int
obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
{
    int level = gs_op_language_level();
    ref system_dict;
    i_ctx_t *i_ctx_p;
    int code;

    /*
     * Create systemdict.  The context machinery requires that
     * we do this before initializing the interpreter.
     */
    code = dict_alloc(idmem->space_global,
		      (level >= 3 ? SYSTEMDICT_LL3_SIZE :
		       level >= 2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE),
		      &system_dict);
    if (code < 0)
	return code;

    /* Initialize the interpreter. */
    code = gs_interp_init(pi_ctx_p, &system_dict, idmem);
    if (code < 0)
	return code;
    i_ctx_p = *pi_ctx_p;

    {
#define icount countof(initial_dictionaries)
	ref idicts[icount];
	int i;
	const op_def *const *tptr;

	min_dstack_size = MIN_DSTACK_SIZE;

	refset_null(idicts, icount);

	/* Put systemdict on the dictionary stack. */
	if (level >= 2) {
	    dsp += 2;
	    /*
	     * For the moment, let globaldict be an alias for systemdict.
	     */
	    dsp[-1] = system_dict;
	    min_dstack_size++;
	} else {
	    ++dsp;
	}
	*dsp = system_dict;

	/* Create dictionaries which are to be homes for operators. */
	for (tptr = op_defs_all; *tptr != 0; tptr++) {
	    const op_def *def;

	    for (def = *tptr; def->oname != 0; def++)
		if (op_def_is_begin_dict(def)) {
		    if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0)
			return_error(e_VMerror);
		}
	}

	/* Set up the initial dstack. */
	for (i = 0; i < countof(initial_dstack); i++) {
	    const char *dname = initial_dstack[i];

	    ++dsp;
	    if (!strcmp(dname, "userdict"))
		dstack_userdict_index = dsp - dsbot;
	    ref_assign(dsp, make_initial_dict(i_ctx_p, dname, idicts));
	}

	/* Enter names of referenced initial dictionaries into systemdict. */
	initial_enter_name("systemdict", systemdict);
	for (i = 0; i < icount; i++) {
	    ref *idict = &idicts[i];

	    if (!r_has_type(idict, t_null)) {
		/*
		 * Note that we enter the dictionary in systemdict
		 * even if it is in local VM.  There is a special
		 * provision in the garbage collector for this:
		 * see ivmspace.h for more information.
		 * In order to do this, we must temporarily
		 * identify systemdict as local, so that the
		 * store check in dict_put won't fail.
		 */
		uint save_space = r_space(systemdict);

		r_set_space(systemdict, avm_local);
		code = initial_enter_name(initial_dictionaries[i].name,
					  idict);
		r_set_space(systemdict, save_space);
		if (code < 0)
		    return code;
	    }
	}
#undef icount
    }

    gs_interp_reset(i_ctx_p);

    {
	ref vnull, vtrue, vfalse;

	make_null(&vnull);
	make_true(&vtrue);
	make_false(&vfalse);
	if ((code = initial_enter_name("null", &vnull)) < 0 ||
	    (code = initial_enter_name("true", &vtrue)) < 0 ||
	    (code = initial_enter_name("false", &vfalse)) < 0
	    )
	    return code;
    }

    /* Create the error name table */
    {
	int n = countof(gs_error_names) - 1;
	int i;
	ref era;

	code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames");
	if (code < 0)
	    return code;
	for (i = 0; i < n; i++)
	  if ((code = name_enter_string(imemory, (const char *)gs_error_names[i],
					  era.value.refs + i)) < 0)
		return code;
	return initial_enter_name("ErrorNames", &era);
    }
}
Exemple #4
0
/* Resize a dictionary. */
int
dict_resize(ref * pdref, uint new_size, dict_stack_t *pds)
{
    dict *pdict = pdref->value.pdict;
    gs_ref_memory_t *mem = dict_memory(pdict);
    uint new_mask = imemory_new_mask(mem);
    ushort orig_attrs = r_type_attrs(&pdict->values) & (a_all | a_executable);
    dict dnew;
    ref drto;
    int code;

    if (new_size < d_length(pdict)) {
        if (!mem->gs_lib_ctx->dict_auto_expand)
            return_error(gs_error_dictfull);
        new_size = d_length(pdict);
    }
    make_tav(&drto, t_dictionary, r_space(pdref) | a_all | new_mask,
             pdict, &dnew);
    dnew.memory = pdict->memory;
    if ((code = dict_create_contents(new_size, &drto, dict_is_packed(pdict))) < 0)
        return code;
    /*
     * We must suppress the store check, in case we are expanding
     * systemdict or another global dictionary that is allowed
     * to reference local objects.
     */
    r_set_space(&drto, avm_local);
    /*
     * If we are expanding a permanent dictionary, we must make sure that
     * dict_put doesn't think this is a second definition for any
     * single-definition names.  This in turn requires that
     * dstack_dict_is_permanent must be true for the second ("to")
     * argument of dict_copy_elements, which requires temporarily
     * setting *pdref = drto.
     */
    if (CAN_SET_PVALUE_CACHE(pds, pdref, mem)) {
        ref drfrom;

        drfrom = *pdref;
        *pdref = drto;
        dict_copy_elements(&drfrom, pdref, COPY_FOR_RESIZE, pds);
        *pdref = drfrom;
    } else {
        dict_copy_elements(pdref, &drto, 0, pds);
    }
    /* Save or free the old dictionary. */
    if (ref_must_save_in(mem, &pdict->values))
        ref_do_save_in(mem, pdref, &pdict->values, "dict_resize(values)");
    else
        gs_free_ref_array(mem, &pdict->values, "dict_resize(old values)");
    if (ref_must_save_in(mem, &pdict->keys))
        ref_do_save_in(mem, pdref, &pdict->keys, "dict_resize(keys)");
    else
        gs_free_ref_array(mem, &pdict->keys, "dict_resize(old keys)");
    ref_assign(&pdict->keys, &dnew.keys);
    ref_assign(&pdict->values, &dnew.values);
    r_store_attrs(&pdict->values, a_all | a_executable, orig_attrs);
    ref_save_in(dict_memory(pdict), pdref, &pdict->maxlength,
                "dict_resize(maxlength)");
    d_set_maxlength(pdict, new_size);
    if (pds)
        dstack_set_top(pds);	/* just in case this is the top dict */
    return 0;
}