/* Create a dictionary using the given allocator. */ int dict_alloc(gs_ref_memory_t * mem, uint size, ref * pdref) { ref arr; int code = gs_alloc_ref_array(mem, &arr, a_all, sizeof(dict) / sizeof(ref), "dict_alloc"); dict *pdict; ref dref; if (code < 0) return code; pdict = (dict *) arr.value.refs; make_tav(&dref, t_dictionary, r_space(&arr) | imemory_new_mask(mem) | a_all, pdict, pdict); make_struct(&pdict->memory, avm_foreign, mem); code = dict_create_contents(size, &dref, dict_default_pack); if (code < 0) { gs_free_ref_array(mem, &arr, "dict_alloc"); return code; } *pdref = dref; return 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; }
/* Return <0 on error, 0 if not wanted, 1 if wanted. */ static int ref_array_param_requested(const iparam_list *iplist, gs_param_name pkey, ref *pvalue, uint size, client_name_t cname) { int code; if (!ref_param_requested((const gs_param_list *)iplist, pkey)) return 0; code = gs_alloc_ref_array(iplist->ref_memory, pvalue, a_all, size, cname); return (code < 0 ? code : 1); }
/* 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; }
/* Initialize the graphics stack. */ gs_state * int_gstate_alloc(const gs_dual_memory_t * dmem) { int_gstate *iigs; ref proc0; int_remap_color_info_t *prci; gs_ref_memory_t *lmem = dmem->space_local; gs_ref_memory_t *gmem = dmem->space_global; gs_state *pgs = gs_state_alloc((gs_memory_t *)lmem); iigs = gs_alloc_struct((gs_memory_t *)lmem, int_gstate, &st_int_gstate, "int_gstate_alloc(int_gstate)"); int_gstate_map_refs(iigs, make_null); make_empty_array(&iigs->dash_pattern_array, a_all); gs_alloc_ref_array(lmem, &proc0, a_readonly + a_executable, 2, "int_gstate_alloc(proc0)"); make_oper(proc0.value.refs, 0, zpop); make_real(proc0.value.refs + 1, 0.0); iigs->black_generation = proc0; iigs->undercolor_removal = proc0; make_false(&iigs->use_cie_color); /* * Even though the gstate itself is allocated in local VM, the * container for the color remapping procedure must be allocated in * global VM so that the gstate can be copied into global VM. */ prci = gs_alloc_struct((gs_memory_t *)gmem, int_remap_color_info_t, &st_int_remap_color_info, "int_gstate_alloc(remap color info)"); make_struct(&iigs->remap_color_info, imemory_space(gmem), prci); clear_pagedevice(iigs); gs_state_set_client(pgs, iigs, &istate_procs, true); /* PostScript code wants limit clamping enabled. */ gs_setlimitclamp(pgs, true); /* * gsave and grestore only work properly * if there are always at least 2 entries on the stack. * We count on the PostScript initialization code to do a gsave. */ return pgs; }
/* Create and store [/key any] array in $error.errorinfo. * The key must be a permanently allocated C string. * This routine is here because it is often used with parameter dictionaries. */ int gs_errorinfo_put_pair(i_ctx_t *i_ctx_p, const char *key, int len, const ref *any) { int code; ref pair, *aptr, key_name, *pderror; code = name_ref(imemory_local, (const byte *)key, len, &key_name, 0); if (code < 0) return code; code = gs_alloc_ref_array(iimemory_local, &pair, a_readonly, 2, "gs_errorinfo_put_pair"); if (code < 0) return code; aptr = pair.value.refs; ref_assign_new(aptr, &key_name); ref_assign_new(aptr+1, any); if (dict_find_string(systemdict, "$error", &pderror) <= 0 || !r_has_type(pderror, t_dictionary) || idict_put_string(pderror, "errorinfo", &pair) < 0 ) return_error(e_Fatal); return 0; }
static int ref_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey, gs_param_dict * pvalue, gs_param_collection_type_t coll_type) { iparam_list *const iplist = (iparam_list *) plist; gs_ref_memory_t *imem = iplist->ref_memory; dict_param_list *dlist = (dict_param_list *) gs_alloc_bytes(plist->memory, size_of(dict_param_list), "ref_param_begin_write_collection"); int code; if (dlist == 0) return_error(e_VMerror); if (coll_type != gs_param_collection_array) { ref dref; code = dict_alloc(imem, pvalue->size, &dref); if (code >= 0) { code = dict_param_list_write(dlist, &dref, NULL, imem); dlist->int_keys = coll_type == gs_param_collection_dict_int_keys; } } else { ref aref; code = gs_alloc_ref_array(imem, &aref, a_all, pvalue->size, "ref_param_begin_write_collection"); if (code >= 0) code = array_new_indexed_plist_write(dlist, &aref, NULL, imem); } if (code < 0) gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection"); else pvalue->list = (gs_param_list *) dlist; return code; }
/* ensuring that refs in mixed arrays are properly aligned. */ #undef idmemory /****** NOTA BENE ******/ int make_packed_array(ref * parr, ref_stack_t * pstack, uint size, gs_dual_memory_t *idmemory, client_name_t cname) { uint i; const ref *pref; uint idest = 0, ishort = 0; ref_packed *pbody; ref_packed *pdest; ref_packed *pshort; /* points to start of */ /* last run of short elements */ gs_ref_memory_t *imem = idmemory->current; uint space = imemory_space(imem); int skip = 0, pad; ref rtemp; int code; /* Do a first pass to calculate the size of the array, */ /* and to detect local-into-global stores. */ for (i = size; i != 0; i--) { pref = ref_stack_index(pstack, i - 1); switch (r_btype(pref)) { /* not r_type, opers are special */ case t_name: if (name_index(imem, pref) >= packed_name_max_index) break; /* can't pack */ idest++; continue; case t_integer: if (pref->value.intval < packed_min_intval || pref->value.intval > packed_max_intval ) break; idest++; continue; case t_oparray: /* Check for local-into-global store. */ store_check_space(space, pref); /* falls through */ case t_operator: { uint oidx; if (!r_has_attr(pref, a_executable)) break; oidx = op_index(pref); if (oidx == 0 || oidx > packed_int_mask) break; } idest++; continue; default: /* Check for local-into-global store. */ store_check_space(space, pref); } /* Can't pack this element, use a full ref. */ /* We may have to unpack up to align_packed_per_ref - 1 */ /* preceding short elements. */ /* If we are at the beginning of the array, however, */ /* we can just move the elements up. */ { int i = (idest - ishort) & (align_packed_per_ref - 1); if (ishort == 0) /* first time */ idest += skip = -i & (align_packed_per_ref - 1); else idest += (packed_per_ref - 1) * i; } ishort = idest += packed_per_ref; } pad = -(int)idest & (packed_per_ref - 1); /* padding at end */ /* Now we can allocate the array. */ code = gs_alloc_ref_array(imem, &rtemp, 0, (idest + pad) / packed_per_ref, cname); if (code < 0) return code; pbody = (ref_packed *) rtemp.value.refs; /* Make sure any initial skipped elements contain legal packed */ /* refs, so that the garbage collector can scan storage. */ pshort = pbody; for (; skip; skip--) *pbody++ = pt_tag(pt_integer); pdest = pbody; for (i = size; i != 0; i--) { pref = ref_stack_index(pstack, i - 1); switch (r_btype(pref)) { /* not r_type, opers are special */ case t_name: { uint nidx = name_index(imem, pref); if (nidx >= packed_name_max_index) break; /* can't pack */ *pdest++ = nidx + (r_has_attr(pref, a_executable) ? pt_tag(pt_executable_name) : pt_tag(pt_literal_name)); } continue; case t_integer: if (pref->value.intval < packed_min_intval || pref->value.intval > packed_max_intval ) break; *pdest++ = pt_tag(pt_integer) + ((short)pref->value.intval - packed_min_intval); continue; case t_oparray: case t_operator: { uint oidx; if (!r_has_attr(pref, a_executable)) break; oidx = op_index(pref); if (oidx == 0 || oidx > packed_int_mask) break; *pdest++ = pt_tag(pt_executable_operator) + oidx; } continue; } /* Can't pack this element, use a full ref. */ /* We may have to unpack up to align_packed_per_ref - 1 */ /* preceding short elements. */ /* Note that if we are at the beginning of the array, */ /* 'skip' already ensures that we don't need to do this. */ { int i = (pdest - pshort) & (align_packed_per_ref - 1); const ref_packed *psrc = pdest; ref *pmove = (ref *) (pdest += (packed_per_ref - 1) * i); ref_assign_new(pmove, pref); while (--i >= 0) { --psrc; --pmove; packed_get(imem->non_gc_memory, psrc, pmove); } } pshort = pdest += packed_per_ref; } { int atype = (pdest == pbody + size ? t_shortarray : t_mixedarray); /* Pad with legal packed refs so that the garbage collector */ /* can scan storage. */ for (; pad; pad--) *pdest++ = pt_tag(pt_integer); /* Finally, make the array. */ ref_stack_pop(pstack, size); make_tasv_new(parr, atype, a_readonly | space, size, packed, pbody + skip); } return 0; }
int zdefault_make_font(gs_font_dir * pdir, const gs_font * oldfont, const gs_matrix * pmat, gs_font ** ppfont) { gs_font *newfont = *ppfont; gs_memory_t *mem = newfont->memory; /* HACK: we know this font was allocated by the interpreter. */ gs_ref_memory_t *imem = (gs_ref_memory_t *)mem; ref *fp = pfont_dict(oldfont); font_data *pdata; ref newdict, newmat, scalemat; uint dlen = dict_maxlength(fp); uint mlen = dict_length(fp) + 3; /* FontID, OrigFont, ScaleMatrix */ int code; if (dlen < mlen) dlen = mlen; if ((pdata = gs_alloc_struct(mem, font_data, &st_font_data, "make_font(font_data)")) == 0 ) return_error(e_VMerror); /* * This dictionary is newly created: it's safe to pass NULL as the * dstack pointer to dict_copy and dict_put_string. */ if ((code = dict_alloc(imem, dlen, &newdict)) < 0 || (code = dict_copy(fp, &newdict, NULL)) < 0 || (code = gs_alloc_ref_array(imem, &newmat, a_all, 12, "make_font(matrices)")) < 0 ) return code; refset_null_new(newmat.value.refs, 12, imemory_new_mask(imem)); ref_assign(&scalemat, &newmat); r_set_size(&scalemat, 6); scalemat.value.refs += 6; /* * Create the scaling matrix. We could do this several different * ways: by "dividing" the new FontMatrix by the base FontMatrix, by * multiplying the current scaling matrix by a ScaleMatrix kept in * the gs_font, or by multiplying the current scaling matrix by the * ScaleMatrix from the font dictionary. We opt for the last of * these. */ { gs_matrix scale, prev_scale; ref *ppsm; if (!(dict_find_string(fp, "ScaleMatrix", &ppsm) > 0 && read_matrix(mem, ppsm, &prev_scale) >= 0 && gs_matrix_multiply(pmat, &prev_scale, &scale) >= 0) ) scale = *pmat; write_matrix_new(&scalemat, &scale, imem); } r_clear_attrs(&scalemat, a_write); r_set_size(&newmat, 6); write_matrix_new(&newmat, &newfont->FontMatrix, imem); r_clear_attrs(&newmat, a_write); if ((code = dict_put_string(&newdict, "FontMatrix", &newmat, NULL)) < 0 || (code = dict_put_string(&newdict, "OrigFont", pfont_dict(oldfont->base), NULL)) < 0 || (code = dict_put_string(&newdict, "ScaleMatrix", &scalemat, NULL)) < 0 || (code = add_FID(NULL, &newdict, newfont, imem)) < 0 ) return code; newfont->client_data = pdata; *pdata = *pfont_data(oldfont); pdata->dict = newdict; r_clear_attrs(dict_access_ref(&newdict), a_write); return 0; }