/src/ghostpdl/psi/zrelbit.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2023 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., 39 Mesa Street, Suite 108A, San Francisco, |
13 | | CA 94129, USA, for further information. |
14 | | */ |
15 | | |
16 | | |
17 | | /* Relational, boolean, and bit operators */ |
18 | | #include "ghost.h" |
19 | | #include "oper.h" |
20 | | #include "gsutil.h" |
21 | | #include "idict.h" |
22 | | #include "store.h" |
23 | | #include "gsstate.h" |
24 | | |
25 | | /* |
26 | | * Many of the procedures in this file are public only so they can be |
27 | | * called from the FunctionType 4 interpreter (zfunc4.c). |
28 | | */ |
29 | | |
30 | | /* ------ Standard operators ------ */ |
31 | | |
32 | | /* Define the type test for eq and its relatives. */ |
33 | | #define EQ_CHECK_READ(opp, dflt)\ |
34 | 8.91G | switch ( r_type(opp) ) {\ |
35 | 232M | case t_string:\ |
36 | 232M | check_read(*(opp));\ |
37 | 232M | break;\ |
38 | 8.68G | default:\ |
39 | 13.0G | dflt;\ |
40 | 8.91G | } |
41 | | |
42 | | /* Forward references */ |
43 | | static int obj_le(os_ptr, os_ptr); |
44 | | |
45 | | /* <obj1> <obj2> eq <bool> */ |
46 | | int |
47 | | zeq(i_ctx_t *i_ctx_p) |
48 | 4.45G | { |
49 | 4.45G | os_ptr op = osp; |
50 | 4.45G | check_op(2); |
51 | 4.45G | EQ_CHECK_READ(op - 1, check_op(2)); |
52 | 4.45G | EQ_CHECK_READ(op, DO_NOTHING); |
53 | 4.45G | make_bool(op - 1, (obj_eq(imemory, op - 1, op) ? 1 : 0)); |
54 | 4.45G | pop(1); |
55 | 4.45G | return 0; |
56 | 4.45G | } |
57 | | |
58 | | /* <obj1> <obj2> ne <bool> */ |
59 | | int |
60 | | zne(i_ctx_t *i_ctx_p) |
61 | 974M | { /* We'll just be lazy and use eq. */ |
62 | 974M | int code = zeq(i_ctx_p); |
63 | | |
64 | 974M | if (!code) |
65 | 974M | osp->value.boolval ^= 1; |
66 | 974M | return code; |
67 | 974M | } |
68 | | |
69 | | /* <num1> <num2> ge <bool> */ |
70 | | /* <str1> <str2> ge <bool> */ |
71 | | int |
72 | | zge(i_ctx_t *i_ctx_p) |
73 | 9.20M | { |
74 | 9.20M | os_ptr op = osp; |
75 | 9.20M | int code; |
76 | | |
77 | 9.20M | check_op(2); |
78 | 9.20M | code = obj_le(op, op - 1); |
79 | 9.20M | if (code < 0) |
80 | 11 | return code; |
81 | 9.20M | make_bool(op - 1, code); |
82 | 9.20M | pop(1); |
83 | 9.20M | return 0; |
84 | 9.20M | } |
85 | | |
86 | | /* <num1> <num2> gt <bool> */ |
87 | | /* <str1> <str2> gt <bool> */ |
88 | | int |
89 | | zgt(i_ctx_t *i_ctx_p) |
90 | 337M | { |
91 | 337M | os_ptr op = osp; |
92 | 337M | int code; |
93 | | |
94 | 337M | check_op(2); |
95 | 337M | code = obj_le(op - 1, op); |
96 | 337M | if (code < 0) |
97 | 24 | return code; |
98 | 337M | make_bool(op - 1, code ^ 1); |
99 | 337M | pop(1); |
100 | 337M | return 0; |
101 | 337M | } |
102 | | |
103 | | /* <num1> <num2> le <bool> */ |
104 | | /* <str1> <str2> le <bool> */ |
105 | | int |
106 | | zle(i_ctx_t *i_ctx_p) |
107 | 35.7M | { |
108 | 35.7M | os_ptr op = osp; |
109 | 35.7M | int code; |
110 | | |
111 | 35.7M | check_op(2); |
112 | 35.7M | code = obj_le(op - 1, op); |
113 | 35.7M | if (code < 0) |
114 | 22 | return code; |
115 | 35.7M | make_bool(op - 1, code); |
116 | 35.7M | pop(1); |
117 | 35.7M | return 0; |
118 | 35.7M | } |
119 | | |
120 | | /* <num1> <num2> lt <bool> */ |
121 | | /* <str1> <str2> lt <bool> */ |
122 | | int |
123 | | zlt(i_ctx_t *i_ctx_p) |
124 | 22.1M | { |
125 | 22.1M | os_ptr op = osp; |
126 | 22.1M | int code; |
127 | | |
128 | 22.1M | check_op(2); |
129 | 22.1M | code = obj_le(op, op - 1); |
130 | 22.1M | if (code < 0) |
131 | 19 | return code; |
132 | 22.1M | make_bool(op - 1, code ^ 1); |
133 | 22.1M | pop(1); |
134 | 22.1M | return 0; |
135 | 22.1M | } |
136 | | |
137 | | /* <num1> <num2> .max <num> */ |
138 | | /* <str1> <str2> .max <str> */ |
139 | | static int |
140 | | zmax(i_ctx_t *i_ctx_p) |
141 | 3.99M | { |
142 | 3.99M | os_ptr op = osp; |
143 | 3.99M | int code; |
144 | | |
145 | 3.99M | check_op(2); |
146 | 3.99M | code = obj_le(op - 1, op); |
147 | 3.99M | if (code < 0) |
148 | 2 | return code; |
149 | 3.99M | if (code) { |
150 | 682k | ref_assign(op - 1, op); |
151 | 682k | } |
152 | 3.99M | pop(1); |
153 | 3.99M | return 0; |
154 | 3.99M | } |
155 | | |
156 | | /* <num1> <num2> .min <num> */ |
157 | | /* <str1> <str2> .min <str> */ |
158 | | static int |
159 | | zmin(i_ctx_t *i_ctx_p) |
160 | 2.61M | { |
161 | 2.61M | os_ptr op = osp; |
162 | 2.61M | int code; |
163 | | |
164 | 2.61M | check_op(2); |
165 | 2.61M | code = obj_le(op - 1, op); |
166 | 2.61M | if (code < 0) |
167 | 2 | return code; |
168 | 2.61M | if (!code) { |
169 | 5 | ref_assign(op - 1, op); |
170 | 5 | } |
171 | 2.61M | pop(1); |
172 | 2.61M | return 0; |
173 | 2.61M | } |
174 | | |
175 | | /* <bool1> <bool2> and <bool> */ |
176 | | /* <int1> <int2> and <int> */ |
177 | | int |
178 | | zand(i_ctx_t *i_ctx_p) |
179 | 582M | { |
180 | 582M | os_ptr op = osp; |
181 | | |
182 | 582M | check_op(2); |
183 | 582M | switch (r_type(op)) { |
184 | 582M | case t_boolean: |
185 | 582M | check_type(op[-1], t_boolean); |
186 | 582M | op[-1].value.boolval &= op->value.boolval; |
187 | 582M | break; |
188 | 827 | case t_integer: |
189 | 827 | check_type(op[-1], t_integer); |
190 | 822 | op[-1].value.intval &= op->value.intval; |
191 | 822 | break; |
192 | 13 | default: |
193 | 13 | return_op_typecheck(op); |
194 | 582M | } |
195 | 582M | pop(1); |
196 | 582M | return 0; |
197 | 582M | } |
198 | | |
199 | | /* <bool> not <bool> */ |
200 | | /* <int> not <int> */ |
201 | | int |
202 | | znot(i_ctx_t *i_ctx_p) |
203 | 506M | { |
204 | 506M | os_ptr op = osp; |
205 | | |
206 | 506M | check_op(1); |
207 | 506M | switch (r_type(op)) { |
208 | 506M | case t_boolean: |
209 | 506M | op->value.boolval = !op->value.boolval; |
210 | 506M | break; |
211 | 86 | case t_integer: |
212 | 86 | op->value.intval = ~op->value.intval; |
213 | 86 | break; |
214 | 16 | default: |
215 | 16 | return_op_typecheck(op); |
216 | 506M | } |
217 | 506M | return 0; |
218 | 506M | } |
219 | | |
220 | | /* <bool1> <bool2> or <bool> */ |
221 | | /* <int1> <int2> or <int> */ |
222 | | int |
223 | | zor(i_ctx_t *i_ctx_p) |
224 | 167M | { |
225 | 167M | os_ptr op = osp; |
226 | | |
227 | 167M | check_op(2); |
228 | 167M | switch (r_type(op)) { |
229 | 167M | case t_boolean: |
230 | 167M | check_type(op[-1], t_boolean); |
231 | 167M | op[-1].value.boolval |= op->value.boolval; |
232 | 167M | break; |
233 | 3.85k | case t_integer: |
234 | 3.85k | check_type(op[-1], t_integer); |
235 | 3.83k | op[-1].value.intval |= op->value.intval; |
236 | 3.83k | break; |
237 | 24 | default: |
238 | 24 | return_op_typecheck(op); |
239 | 167M | } |
240 | 167M | pop(1); |
241 | 167M | return 0; |
242 | 167M | } |
243 | | |
244 | | /* <bool1> <bool2> xor <bool> */ |
245 | | /* <int1> <int2> xor <int> */ |
246 | | int |
247 | | zxor(i_ctx_t *i_ctx_p) |
248 | 39 | { |
249 | 39 | os_ptr op = osp; |
250 | | |
251 | 39 | check_op(2); |
252 | 25 | switch (r_type(op)) { |
253 | 2 | case t_boolean: |
254 | 2 | check_type(op[-1], t_boolean); |
255 | 2 | op[-1].value.boolval ^= op->value.boolval; |
256 | 2 | break; |
257 | 14 | case t_integer: |
258 | 14 | check_type(op[-1], t_integer); |
259 | 12 | op[-1].value.intval ^= op->value.intval; |
260 | 12 | break; |
261 | 9 | default: |
262 | 9 | return_op_typecheck(op); |
263 | 25 | } |
264 | 14 | pop(1); |
265 | 14 | return 0; |
266 | 25 | } |
267 | | |
268 | | /* <int> <shift> bitshift <int> */ |
269 | | int |
270 | | zbitshift(i_ctx_t *i_ctx_p) |
271 | 208 | { |
272 | 208 | os_ptr op = osp; |
273 | 208 | int shift; |
274 | 208 | short max_shift = (sizeof(ps_int) * 8) - 1; |
275 | 208 | short max_shift32 = (sizeof(ps_int32) * 8) - 1; |
276 | | |
277 | 208 | check_op(2); |
278 | 192 | check_type(*op, t_integer); |
279 | 182 | check_type(op[-1], t_integer); |
280 | 174 | if ((op->value.intval < -max_shift) || (op->value.intval > max_shift)) |
281 | 23 | op[-1].value.intval = 0; |
282 | 151 | else if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory) && (op->value.intval < -max_shift32 || op->value.intval > max_shift32)) |
283 | 0 | op[-1].value.intval = 0; |
284 | 151 | else if ((shift = op->value.intval) < 0) { |
285 | 36 | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
286 | 0 | ps_int32 val = (ps_int32)(op[-1].value.intval); |
287 | 0 | op[-1].value.intval = (ps_int)((uint)(val)) >> -shift; |
288 | 0 | } |
289 | 36 | else { |
290 | 36 | op[-1].value.intval = ((ps_int)(op[-1].value.intval)) >> -shift; |
291 | 36 | } |
292 | 36 | } |
293 | 115 | else { |
294 | 115 | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
295 | 0 | ps_int32 val = (ps_int32)(op[-1].value.intval); |
296 | |
|
297 | 0 | op[-1].value.intval = (ps_int)(val << shift); |
298 | 0 | } |
299 | 115 | else |
300 | 115 | op[-1].value.intval <<= shift; |
301 | 115 | } |
302 | 174 | pop(1); |
303 | 174 | return 0; |
304 | 182 | } |
305 | | |
306 | | /* ------ Extensions ------ */ |
307 | | |
308 | | /* <obj1> <obj2> .identeq <bool> */ |
309 | | static int |
310 | | zidenteq(i_ctx_t *i_ctx_p) |
311 | 0 | { |
312 | 0 | os_ptr op = osp; |
313 | |
|
314 | 0 | check_op(2); |
315 | 0 | EQ_CHECK_READ(op - 1, check_op(2)); |
316 | 0 | EQ_CHECK_READ(op, DO_NOTHING); |
317 | 0 | make_bool(op - 1, (obj_ident_eq(imemory, op - 1, op) ? 1 : 0)); |
318 | 0 | pop(1); |
319 | 0 | return 0; |
320 | |
|
321 | 0 | } |
322 | | |
323 | | /* <obj1> <obj2> .identne <bool> */ |
324 | | static int |
325 | | zidentne(i_ctx_t *i_ctx_p) |
326 | 0 | { |
327 | | /* We'll just be lazy and use .identeq. */ |
328 | 0 | os_ptr op = osp; |
329 | 0 | int code; |
330 | |
|
331 | 0 | check_op(1); |
332 | 0 | code = zidenteq(i_ctx_p); |
333 | 0 | if (!code) |
334 | 0 | osp->value.boolval ^= 1; |
335 | 0 | return code; |
336 | 0 | } |
337 | | |
338 | | /* ------ Initialization procedure ------ */ |
339 | | |
340 | | const op_def zrelbit_op_defs[] = |
341 | | { |
342 | | {"2and", zand}, |
343 | | {"2bitshift", zbitshift}, |
344 | | {"2eq", zeq}, |
345 | | {"2ge", zge}, |
346 | | {"2gt", zgt}, |
347 | | {"2le", zle}, |
348 | | {"2lt", zlt}, |
349 | | {"2.max", zmax}, |
350 | | {"2.min", zmin}, |
351 | | {"2ne", zne}, |
352 | | {"1not", znot}, |
353 | | {"2or", zor}, |
354 | | {"2xor", zxor}, |
355 | | /* Extensions */ |
356 | | {"2.identeq", zidenteq}, |
357 | | {"2.identne", zidentne}, |
358 | | op_def_end(0) |
359 | | }; |
360 | | |
361 | | /* ------ Internal routines ------ */ |
362 | | |
363 | | /* Compare two operands (both numeric, or both strings). */ |
364 | | /* Return 1 if op[-1] <= op[0], 0 if op[-1] > op[0], */ |
365 | | /* or a (negative) error code. */ |
366 | | static int |
367 | | obj_le(register os_ptr op1, register os_ptr op) |
368 | 410M | { |
369 | 410M | switch (r_type(op1)) { |
370 | 269M | case t_integer: |
371 | 269M | switch (r_type(op)) { |
372 | 267M | case t_integer: |
373 | 267M | return (op1->value.intval <= op->value.intval); |
374 | 2.28M | case t_real: |
375 | 2.28M | return ((double)op1->value.intval <= op->value.realval); |
376 | 12 | default: |
377 | 12 | return_op_typecheck(op); |
378 | 269M | } |
379 | 30.3M | case t_real: |
380 | 30.3M | switch (r_type(op)) { |
381 | 30.3M | case t_real: |
382 | 30.3M | return (op1->value.realval <= op->value.realval); |
383 | 20.3k | case t_integer: |
384 | 20.3k | return (op1->value.realval <= (double)op->value.intval); |
385 | 7 | default: |
386 | 7 | return_op_typecheck(op); |
387 | 30.3M | } |
388 | 110M | case t_string: |
389 | 110M | check_read(*op1); |
390 | 110M | check_read_type(*op, t_string); |
391 | 110M | return (bytes_compare(op1->value.bytes, r_size(op1), |
392 | 110M | op->value.bytes, r_size(op)) <= 0); |
393 | 54 | default: |
394 | 54 | return_op_typecheck(op1); |
395 | 410M | } |
396 | 410M | } |