/* the error name vector, etc. */ int array_get(const gs_memory_t *mem, const ref * aref, long index_long, ref * pref) { if ((ulong)index_long >= r_size(aref)) return_error(e_rangecheck); switch (r_type(aref)) { case t_array: { const ref *pvalue = aref->value.refs + index_long; ref_assign(pref, pvalue); } break; case t_mixedarray: { const ref_packed *packed = aref->value.packed; uint index = (uint)index_long; for (; index--;) packed = packed_next(packed); packed_get(mem, packed, pref); } break; case t_shortarray: { const ref_packed *packed = aref->value.packed + index_long; packed_get(mem, packed, pref); } break; default: return_error(e_typecheck); } return 0; }
/* <array> aload <obj_0> ... <obj_n-1> <array> */ static int zaload(i_ctx_t *i_ctx_p) { os_ptr op = osp; ref aref; uint asize; ref_assign(&aref, op); if (!r_is_array(&aref)) return_op_typecheck(op); check_read(aref); asize = r_size(&aref); if (asize > ostop - op) { /* Use the slow, general algorithm. */ int code = ref_stack_push(&o_stack, asize); uint i; const ref_packed *packed = aref.value.packed; if (code < 0) return code; for (i = asize; i > 0; i--, packed = packed_next(packed)) packed_get(imemory, packed, ref_stack_index(&o_stack, i)); *osp = aref; return 0; } if (r_has_type(&aref, t_array)) memcpy(op, aref.value.refs, asize * sizeof(ref)); else { uint i; const ref_packed *packed = aref.value.packed; os_ptr pdest = op; for (i = 0; i < asize; i++, pdest++, packed = packed_next(packed)) packed_get(imemory, packed, pdest); } push(asize); ref_assign(op, &aref); return 0; }
/* its length; nothing else has been checked. */ static int copy_interval(i_ctx_t *i_ctx_p /* for ref_assign_old */, os_ptr prto, uint index, os_ptr prfrom, client_name_t cname) { int fromtype = r_type(prfrom); uint fromsize = r_size(prfrom); if (!(fromtype == r_type(prto) || ((fromtype == t_shortarray || fromtype == t_mixedarray) && r_type(prto) == t_array)) ) return_op_typecheck(prfrom); check_read(*prfrom); check_write(*prto); if (fromsize > r_size(prto) - index) return_error(e_rangecheck); switch (fromtype) { case t_array: { /* We have to worry about aliasing, */ /* but refcpy_to_old takes care of it for us. */ return refcpy_to_old(prto, index, prfrom->value.refs, fromsize, idmemory, cname); } case t_string: { /* memmove takes care of aliasing. */ memmove(prto->value.bytes + index, prfrom->value.bytes, fromsize); } break; case t_mixedarray: case t_shortarray: { /* We don't have to worry about aliasing, because */ /* packed arrays are read-only and hence the destination */ /* can't be a packed array. */ uint i; const ref_packed *packed = prfrom->value.packed; ref *pdest = prto->value.refs + index; ref elt; for (i = 0; i < fromsize; i++, pdest++) { packed_get(imemory, packed, &elt); ref_assign_old(prto, pdest, &elt, cname); packed = packed_next(packed); } } break; } return 0; }
static int cond_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; es_ptr ep = esp; int code; /* The top element of the e-stack is the remaining tail of */ /* the cond body. The top element of the o-stack should be */ /* the (boolean) result of the test that is the first element */ /* of the tail. */ check_type(*op, t_boolean); if (op->value.boolval) { /* true */ array_get(imemory, ep, 1L, ep); esfile_check_cache(); code = o_pop_estack; } else if (r_size(ep) > 2) { /* false */ const ref_packed *elts = ep->value.packed; check_estack(2); r_dec_size(ep, 2); elts = packed_next(elts); elts = packed_next(elts); ep->value.packed = elts; array_get(imemory, ep, 0L, ep + 2); make_op_estack(ep + 1, cond_continue); esp = ep + 2; esfile_check_cache(); code = o_push_estack; } else { /* fall off end of cond */ esp = ep - 1; code = o_pop_estack; } pop(1); /* get rid of the boolean */ return code; }
/* <seq:array|packedarray|string> <index> <count> getinterval <subseq> */ static int zgetinterval(i_ctx_t *i_ctx_p) { os_ptr op = osp; os_ptr op1 = op - 1; os_ptr op2 = op1 - 1; uint index; uint count; switch (r_type(op2)) { default: return_op_typecheck(op2); case t_array: case t_string: case t_mixedarray: case t_shortarray:; } check_read(*op2); check_int_leu(*op1, r_size(op2)); index = op1->value.intval; check_int_leu(*op, r_size(op2) - index); count = op->value.intval; switch (r_type(op2)) { case t_array: op2->value.refs += index; break; case t_string: op2->value.bytes += index; break; case t_mixedarray: { const ref_packed *packed = op2->value.packed; for (; index--;) packed = packed_next(packed); op2->value.packed = packed; break; } case t_shortarray: op2->value.packed += index; break; } r_set_size(op2, count); pop(2); return 0; }
/* Get a FontBBox parameter from a font dictionary. */ int font_bbox_param(const gs_memory_t *mem, const ref * pfdict, double bbox[4]) { ref *pbbox; /* * Pre-clear the bbox in case it's invalid. The Red Books say that * FontBBox is required, but old Adobe interpreters don't require * it, and a few user-written fonts don't supply it, or supply one * of the wrong size (!); also, PageMaker 5.0 (an Adobe product!) * sometimes emits an absurd bbox for Type 1 fonts converted from * TrueType. */ bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0; if (dict_find_string(pfdict, "FontBBox", &pbbox) > 0) { if (!r_is_array(pbbox)) return_error(e_typecheck); if (r_size(pbbox) == 4) { const ref_packed *pbe = pbbox->value.packed; ref rbe[4]; int i; int code; float dx, dy, ratio; const float max_ratio = 12; /* From the bug 687594. */ for (i = 0; i < 4; i++) { packed_get(mem, pbe, rbe + i); pbe = packed_next(pbe); } if ((code = num_params(rbe + 3, 4, bbox)) < 0) return code; /* Require "reasonable" values. */ dx = bbox[2] - bbox[0]; dy = bbox[3] - bbox[1]; if (dx <= 0 || dy <= 0 || (ratio = dy / dx) < 1 / max_ratio || ratio > max_ratio ) bbox[0] = bbox[1] = bbox[2] = bbox[3] = 0.0; } } else if (gs_currentcpsimode(mem)) { return_error(e_invalidfont); /* CPSI requires FontBBox */ } return 0; }
/* Continuation operator for packed arrays */ static int packedarray_continue(i_ctx_t *i_ctx_p) { os_ptr op = osp; es_ptr obj = esp - 1; if (r_size(obj)) { /* continue */ const ref_packed *packed = obj->value.packed; r_dec_size(obj, 1); push(1); packed_get(imemory, packed, op); obj->value.packed = packed_next(packed); esp += 2; *esp = obj[1]; return o_push_estack; } else { /* done */ esp -= 3; /* pop mark, object, proc */ return o_pop_estack; } }
/* Dump an array. */ void debug_dump_array(const ref *array) { const ref_packed *pp; unsigned int type = r_type(array); uint len; switch (type) { default: dprintf2 ("%s at 0x%lx isn't an array.\n", (type < countof(type_strings) ? type_strings[type] : "????"), (ulong)array); return; case t_oparray: /* This isn't really an array, but we'd like to see */ /* its contents anyway. */ debug_dump_array(op_array_table.value.refs + op_index(array) - op_def_count); return; case t_array: case t_mixedarray: case t_shortarray: ; } /* This "packed" loop works for all array-types. */ for ( len = r_size (array), pp = array->value.packed; len > 0; len--, pp = packed_next(pp)) { ref temp; packed_get(pp, &temp); dprintf3("..%04x%c 0x%02x ", (uint)pp & 0xffff, ((r_is_packed(pp)) ? '*' : ':'), r_type(&temp)); debug_dump_one_ref(&temp); dputc ('\n'); } }