/* <dict> begin - */ int zbegin(i_ctx_t *i_ctx_p) { os_ptr op = osp; check_type(*op, t_dictionary); check_dict_read(*op); if ( dsp == dstop ) { int code = ref_stack_extend(&d_stack, 1); if ( code < 0 ) { if (code == e_dictstackoverflow) { /* Adobe doesn't restore the operand that caused stack */ /* overflow. We do the same to match CET 20-02-02 */ pop(1); } return code; } } ++dsp; ref_assign(dsp, op); dict_set_top(); pop(1); return 0; }
/* - end - */ int zend(i_ctx_t *i_ctx_p) { if (ref_stack_count_inline(&d_stack) == min_dstack_size) { /* We would underflow the d-stack. */ return_error(e_dictstackunderflow); } while (dsp == dsbot) { /* We would underflow the current block. */ ref_stack_pop_block(&d_stack); } dsp--; dict_set_top(); return 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); }
int zrestore(i_ctx_t *i_ctx_p) { os_ptr op = osp; alloc_save_t *asave; bool last; vm_save_t *vmsave; int code = restore_check_operand(op, &asave, idmemory); if (code < 0) return code; if_debug2('u', "[u]vmrestore 0x%lx, id = %lu\n", (ulong) alloc_save_client_data(asave), (ulong) op->value.saveid); if (I_VALIDATE_BEFORE_RESTORE) ivalidate_clean_spaces(i_ctx_p); /* Check the contents of the stacks. */ osp--; { int code; if ((code = restore_check_stack(i_ctx_p, &o_stack, asave, false)) < 0 || (code = restore_check_stack(i_ctx_p, &e_stack, asave, true)) < 0 || (code = restore_check_stack(i_ctx_p, &d_stack, asave, false)) < 0 ) { osp++; return code; } } /* Reset l_new in all stack entries if the new save level is zero. */ /* Also do some special fixing on the e-stack. */ restore_fix_stack(&o_stack, asave, false); restore_fix_stack(&e_stack, asave, true); restore_fix_stack(&d_stack, asave, false); /* Iteratively restore the state of memory, */ /* also doing a grestoreall at each step. */ do { vmsave = alloc_save_client_data(alloc_save_current(idmemory)); /* Restore the graphics state. */ gs_grestoreall_for_restore(igs, vmsave->gsave); /* * If alloc_save_space decided to do a second save, the vmsave * object was allocated one save level less deep than the * current level, so ifree_object won't actually free it; * however, it points to a gsave object that definitely * *has* been freed. In order not to trip up the garbage * collector, we clear the gsave pointer now. */ vmsave->gsave = 0; /* Now it's safe to restore the state of memory. */ code = alloc_restore_step_in(idmemory, asave); if (code < 0) return code; last = code; } while (!last); { uint space = icurrent_space; ialloc_set_space(idmemory, avm_local); ifree_object(vmsave, "zrestore"); ialloc_set_space(idmemory, space); } dict_set_top(); /* reload dict stack cache */ if (I_VALIDATE_AFTER_RESTORE) ivalidate_clean_spaces(i_ctx_p); /* If the i_ctx_p LockFilePermissions is true, but the userparams */ /* we just restored is false, we need to make sure that we do not */ /* cause an 'invalidaccess' in setuserparams. Temporarily set */ /* LockFilePermissions false until the gs_lev2.ps can do a */ /* setuserparams from the restored userparam dictionary. */ i_ctx_p->LockFilePermissions = false; return 0; }
static int set_language_level(i_ctx_t *i_ctx_p, int new_level) { int old_level = LANGUAGE_LEVEL; ref *pgdict = /* globaldict, if present */ ref_stack_index(&d_stack, ref_stack_count(&d_stack) - 2); ref *level2dict; int code = 0; if (new_level < 1 || new_level > (dict_find_string(systemdict, "ll3dict", &level2dict) > 0 ? 3 : 2) ) return_error(e_rangecheck); if (dict_find_string(systemdict, "level2dict", &level2dict) <= 0) return_error(e_undefined); /* * As noted in dstack.h, we allocate the extra d-stack entry for * globaldict even in Level 1 mode; in Level 1 mode, this entry * holds an extra copy of systemdict, and [count]dictstack omit the * very bottommost entry. */ while (new_level != old_level) { switch (old_level) { case 1: { /* 1 => 2 or 3 */ /* Put globaldict in the dictionary stack. */ ref *pdict; /* * This might be called so early in initialization that * globaldict hasn't been defined yet. If so, just skip * this step. */ code = dict_find_string(level2dict, "globaldict", &pdict); if (code > 0) { if (!r_has_type(pdict, t_dictionary)) return_error(e_typecheck); *pgdict = *pdict; } /* Set other flags for Level 2 operation. */ imemory->gs_lib_ctx->dict_auto_expand = true; } code = swap_level_dict(i_ctx_p, "level2dict"); if (code < 0) return code; ++old_level; continue; case 3: /* 3 => 1 or 2 */ code = swap_level_dict(i_ctx_p, "ll3dict"); if (code < 0) return code; --old_level; continue; default: /* 2 => 1 or 3 */ break; } switch (new_level) { case 1: { /* 2 => 1 */ /* * Clear the cached definition pointers of all names defined * in globaldict. This will slow down future lookups, but * we don't care. */ int index = dict_first(pgdict); ref elt[2]; while ((index = dict_next(pgdict, index, &elt[0])) >= 0) if (r_has_type(&elt[0], t_name)) name_invalidate_value_cache(imemory, &elt[0]); /* Overwrite globaldict in the dictionary stack. */ *pgdict = *systemdict; /* Set other flags for Level 1 operation. */ imemory->gs_lib_ctx->dict_auto_expand = false; } code = swap_level_dict(i_ctx_p, "level2dict"); break; case 3: /* 2 => 3 */ code = swap_level_dict(i_ctx_p, "ll3dict"); break; default: /* not possible */ return_error(e_Fatal); } break; } dict_set_top(); /* reload dict stack cache */ return code; }