/src/ghostpdl/psi/zarray.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2021 Artifex Software, Inc. |
2 | | All Rights Reserved. |
3 | | |
4 | | This software is provided AS-IS with no warranty, either express or |
5 | | implied. |
6 | | |
7 | | This software is distributed under license and may not be copied, |
8 | | modified or distributed except as expressly authorized under the terms |
9 | | of the license contained in the file LICENSE in this distribution. |
10 | | |
11 | | Refer to licensing information at http://www.artifex.com or contact |
12 | | Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, |
13 | | CA 94945, U.S.A., +1(415)492-9861, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Array operators */ |
18 | | #include "memory_.h" |
19 | | #include "ghost.h" |
20 | | #include "ialloc.h" |
21 | | #include "ipacked.h" |
22 | | #include "oper.h" |
23 | | #include "store.h" |
24 | | |
25 | | /* The generic operators (copy, get, put, getinterval, putinterval, */ |
26 | | /* length, and forall) are implemented in zgeneric.c. */ |
27 | | |
28 | | /* <int> array <array> */ |
29 | | int |
30 | | zarray(i_ctx_t *i_ctx_p) |
31 | 399M | { |
32 | 399M | os_ptr op = osp; |
33 | 399M | uint size; |
34 | 399M | int code; |
35 | | |
36 | 399M | check_type(*op, t_integer); |
37 | 399M | if (op->value.intval < 0) |
38 | 30 | return_error(gs_error_rangecheck); |
39 | 399M | if (op->value.intval > max_array_size) |
40 | 9 | return_error(gs_error_limitcheck); |
41 | 399M | size = op->value.intval; |
42 | 399M | code = ialloc_ref_array((ref *)op, a_all, size, "array"); |
43 | 399M | if (code < 0) |
44 | 0 | return code; |
45 | 399M | refset_null(op->value.refs, size); |
46 | 399M | return 0; |
47 | 399M | } |
48 | | |
49 | | /* <array> aload <obj_0> ... <obj_n-1> <array> */ |
50 | | static int |
51 | | zaload(i_ctx_t *i_ctx_p) |
52 | 109M | { |
53 | 109M | os_ptr op = osp; |
54 | 109M | ref aref; |
55 | 109M | uint asize; |
56 | | |
57 | 109M | ref_assign(&aref, op); |
58 | 109M | if (!r_is_array(&aref)) |
59 | 109M | return_op_typecheck(op); |
60 | 109M | check_read(aref); |
61 | 109M | asize = r_size(&aref); |
62 | 109M | if (asize > ostop - op) { /* Use the slow, general algorithm. */ |
63 | 1.76k | int code = ref_stack_push(&o_stack, asize); |
64 | 1.76k | uint i; |
65 | 1.76k | const ref_packed *packed = aref.value.packed; |
66 | | |
67 | 1.76k | if (code < 0) |
68 | 0 | return code; |
69 | 34.1M | for (i = asize; i > 0; i--, packed = packed_next(packed)) |
70 | 34.1M | packed_get(imemory, packed, ref_stack_index(&o_stack, i)); |
71 | 1.76k | *osp = aref; |
72 | 1.76k | return 0; |
73 | 1.76k | } |
74 | 109M | if (r_has_type(&aref, t_array)) |
75 | 108M | memcpy(op, aref.value.refs, asize * sizeof(ref)); |
76 | 981k | else { |
77 | 981k | uint i; |
78 | 981k | const ref_packed *packed = aref.value.packed; |
79 | 981k | os_ptr pdest = op; |
80 | | |
81 | 20.2M | for (i = 0; i < asize; i++, pdest++, packed = packed_next(packed)) |
82 | 19.2M | packed_get(imemory, packed, pdest); |
83 | 981k | } |
84 | 109M | push(asize); |
85 | 109M | ref_assign(op, &aref); |
86 | 109M | return 0; |
87 | 109M | } |
88 | | |
89 | | /* <obj_0> ... <obj_n-1> <array> astore <array> */ |
90 | | static int |
91 | | zastore(i_ctx_t *i_ctx_p) |
92 | 385M | { |
93 | 385M | os_ptr op = osp; |
94 | 385M | uint size; |
95 | 385M | int code; |
96 | | |
97 | 385M | if (!r_is_array(op)) |
98 | 385M | return_op_typecheck(op); |
99 | 385M | size = r_size(op); |
100 | | /* Amazingly, the following is valid: 0 array noaccess astore */ |
101 | 385M | if (size == 0) |
102 | 1.92M | return 0; |
103 | 383M | if (!r_has_type_attrs(op, t_array, a_write)) |
104 | 0 | return_error(gs_error_invalidaccess); |
105 | 383M | if (size > op - osbot) { |
106 | | /* The store operation might involve other stack segments. */ |
107 | 91.1k | ref arr; |
108 | | |
109 | 91.1k | if (size >= ref_stack_count(&o_stack)) |
110 | 3 | return_error(gs_error_stackunderflow); |
111 | 91.1k | arr = *op; |
112 | 91.1k | code = ref_stack_store(&o_stack, &arr, size, 1, 0, true, idmemory, |
113 | 91.1k | "astore"); |
114 | 91.1k | if (code < 0) |
115 | 0 | return code; |
116 | 91.1k | ref_stack_pop(&o_stack, size); |
117 | 91.1k | *ref_stack_index(&o_stack, 0) = arr; |
118 | 383M | } else { |
119 | 383M | code = refcpy_to_old(op, 0, op - size, size, idmemory, "astore"); |
120 | 383M | if (code < 0) |
121 | 0 | return code; |
122 | 383M | op[-(int)size] = *op; |
123 | 383M | pop(size); |
124 | 383M | } |
125 | 383M | return 0; |
126 | 383M | } |
127 | | |
128 | | /* ------ Initialization procedure ------ */ |
129 | | |
130 | | const op_def zarray_op_defs[] = |
131 | | { |
132 | | {"1aload", zaload}, |
133 | | {"1array", zarray}, |
134 | | {"1astore", zastore}, |
135 | | op_def_end(0) |
136 | | }; |