/* <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; }
/* <obj1> ... <objn> <int> copy <obj1> ... <objn> <obj1> ... <objn> */ static int zcopy_integer(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; int count, i; int code; if ((uint) op->value.intval > (uint)(op - osbot)) { /* There might be enough elements in other blocks. */ check_type(*op, t_integer); if (op->value.intval >= (int)ref_stack_count(&o_stack)) return_error(e_stackunderflow); if (op->value.intval < 0) return_error(e_rangecheck); check_int_ltu(*op, ref_stack_count(&o_stack)); count = op->value.intval; } else if (op1 + (count = op->value.intval) <= ostop) { /* Fast case. */ memcpy((char *)op, (char *)(op - count), count * sizeof(ref)); push(count - 1); return 0; } /* Do it the slow, general way. */ code = ref_stack_push(&o_stack, count - 1); if (code < 0) return code; for (i = 0; i < count; i++) *ref_stack_index(&o_stack, i) = *ref_stack_index(&o_stack, i + count); return 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; }
/* * 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; }
/* <dict> <key> get <obj> */ static int zget(i_ctx_t *i_ctx_p) { int code; os_ptr op = osp; os_ptr op1 = op - 1; ref *pvalue; switch (r_type(op1)) { case t_dictionary: check_dict_read(*op1); if (dict_find(op1, op, &pvalue) <= 0) return_error(e_undefined); op[-1] = *pvalue; break; case t_string: check_read(*op1); check_int_ltu(*op, r_size(op1)); make_int(op1, op1->value.bytes[(uint) op->value.intval]); break; case t_array: case t_mixedarray: case t_shortarray: check_type(*op, t_integer); check_read(*op1); code = array_get(imemory, op1, op->value.intval, op1); if (code < 0) return code; break; case t__invalid: return_error(e_stackunderflow); default: return_error(e_typecheck); } pop(1); return 0; }