/* Only the type of *op has been checked. */ int zcopy_dict(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; int code; check_type(*op1, t_dictionary); check_dict_read(*op1); check_dict_write(*op); if (!imemory->gs_lib_ctx->dict_auto_expand && (dict_length(op) != 0 || dict_maxlength(op) < dict_length(op1)) ) return_error(e_rangecheck); code = idict_copy(op1, op); if (code < 0) return code; /* * In Level 1 systems, we must copy the access attributes too. * The only possible effect this can have is to make the * copy read-only if the original dictionary is read-only. */ if (!level2_enabled) r_copy_attrs(dict_access_ref(op), a_write, dict_access_ref(op1)); ref_assign(op1, op); pop(1); return 0; }
int dict_param_list_write(dict_param_list *plist, ref *pdict, const ref *pwanted, gs_ref_memory_t *imem) { check_dict_write(*pdict); plist->u.w.write = dict_param_write; plist->enumerate = dict_param_enumerate; ref_param_write_init((iparam_list *) plist, pwanted, imem); plist->dict = *pdict; return 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; }
/* * We make this into a separate procedure because * the interpreter will almost always call it directly. */ int zop_def(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; ref *pvslot; /* The following combines a check_op(2) with a type check. */ switch (r_type(op1)) { case t_name: { /* We can use the fast single-probe lookup here. */ uint nidx = name_index(imemory, op1); uint htemp; if_dict_find_name_by_index_top(nidx, htemp, pvslot) { if (dtop_can_store(op)) goto ra; } break; /* handle all slower cases */ } case t_null: return_error(e_typecheck); case t__invalid: return_error(e_stackunderflow); } /* * Combine the check for a writable top dictionary with * the global/local store check. See dstack.h for details. */ if (!dtop_can_store(op)) { check_dict_write(*dsp); /* * If the dictionary is writable, the problem must be * an invalid store. */ return_error(e_invalidaccess); } /* * Save a level of procedure call in the common (redefinition) * case. With the current interfaces, we pay a double lookup * in the uncommon case. */ if (dict_find(dsp, op1, &pvslot) <= 0) return idict_put(dsp, op1, op); ra: if ((pvslot->tas.type_attrs & (&i_ctx_p->memory)->test_mask) == 0) alloc_save_change(idmemory, &dsp->value.pdict->values, (ref_packed *)pvslot, "dict_put(value)"); ref_assign_new_inline(pvslot,op); return 0; }
/* <dict> <key> .knownundef <bool> */ static int zknownundef(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; int code; check_type(*op1, t_dictionary); check_dict_write(*op1); code = idict_undef(op1, op); make_bool(op1, code == 0); pop(1); return 0; }
/* Set actual frequency and angle in a dictionary. */ static int dict_real_result(i_ctx_t *i_ctx_p, ref * pdict, const char *kstr, floatp val) { int code = 0; ref *ignore; if (dict_find_string(pdict, kstr, &ignore) > 0) { ref rval; check_dict_write(*pdict); make_real(&rval, val); code = idict_put_string(pdict, kstr, &rval); } return code; }
/* <dict> <key> undef - */ static int zundef(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; int code; check_type(*op1, t_dictionary); if (i_ctx_p->in_superexec == 0) check_dict_write(*op1); code = idict_undef(op1, op); if (code < 0 && code != e_undefined) /* ignore undefined error */ return code; pop(2); return 0; }
/* <dict> <int> .setmaxlength - */ static int zsetmaxlength(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; uint new_size; int code; check_type(*op1, t_dictionary); if (i_ctx_p->in_superexec == 0) check_dict_write(*op1); check_type(*op, t_integer); if (op->value.intval < 0) return_error(e_rangecheck); new_size = (uint) op->value.intval; if (dict_length(op - 1) > new_size) return_error(e_dictfull); code = idict_resize(op - 1, new_size); if (code >= 0) pop(2); return code; }
/* <dict> <string> .parse_dsc_comments <dict> <dsc code> */ static int zparse_dsc_comments(i_ctx_t *i_ctx_p) { #define MAX_DSC_MSG_SIZE (DSC_LINE_LENGTH + 4) /* Allow for %% and CR/LF */ os_ptr const opString = osp; os_ptr const opDict = opString - 1; uint ssize; int comment_code, code; char dsc_buffer[MAX_DSC_MSG_SIZE + 2]; const cmdlist_t *pCmdList = DSCcmdlist; const char * const *pBadList = BadCmdlist; ref * pvalue; CDSC * dsc_data = NULL; dict_param_list list; /* * Verify operand types and length of DSC comment string. If a comment * is too long then we simply truncate it. Russell's parser gets to * handle any errors that may result. (Crude handling but the comment * is bad, so ...). */ check_type(*opString, t_string); check_dict_write(*opDict); ssize = r_size(opString); if (ssize > MAX_DSC_MSG_SIZE) /* need room for EOL + \0 */ ssize = MAX_DSC_MSG_SIZE; /* * Pick up the comment string to be parsed. */ memcpy(dsc_buffer, opString->value.bytes, ssize); dsc_buffer[ssize] = 0x0d; /* Russell wants a 'line end' */ dsc_buffer[ssize + 1] = 0; /* Terminate string */ /* * Skip data block comments (see comments in front of BadCmdList). */ while (*pBadList && strncmp(*pBadList, dsc_buffer, strlen(*pBadList))) pBadList++; if (*pBadList) { /* If found in list, then skip comment */ comment_code = 0; /* Force NOP */ } else { /* * Parse comments - use Russell Lang's DSC parser. We need to get * data area for Russell Lang's parser. Note: We have saved the * location of the data area for the parser in our DSC dict. */ code = dict_find_string(opDict, dsc_dict_name, &pvalue); dsc_data = r_ptr(pvalue, dsc_data_t)->dsc_data_ptr; if (code < 0) return code; comment_code = dsc_scan_data(dsc_data, dsc_buffer, ssize + 1); if_debug1('%', "[%%].parse_dsc_comments: code = %d\n", comment_code); /* * We ignore any errors from Russell's parser. The only value that * it will return for an error is -1 so there is very little information. * We also do not want bad DSC comments to abort processing of an * otherwise valid PS file. */ if (comment_code < 0) comment_code = 0; } /* * Transfer data from DSC structure to postscript variables. * Look up proper handler in the local cmd decode list. */ while (pCmdList->code && pCmdList->code != comment_code ) pCmdList++; if (pCmdList->dsc_proc) { code = dict_param_list_write(&list, opDict, NULL, iimemory); if (code < 0) return code; code = (pCmdList->dsc_proc)((gs_param_list *)&list, dsc_data); iparam_list_release(&list); if (code < 0) return code; } /* Put DSC comment name onto operand stack (replace string). */ return name_enter_string(imemory, pCmdList->comment_name, opString); }