/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.77G | switch ( r_type(opp) ) {\ |
35 | 235M | case t_string:\ |
36 | 235M | check_read(*(opp));\ |
37 | 235M | break;\ |
38 | 8.53G | default:\ |
39 | 12.8G | dflt;\ |
40 | 8.77G | } |
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.38G | { |
49 | 4.38G | os_ptr op = osp; |
50 | 4.38G | check_op(2); |
51 | 4.38G | EQ_CHECK_READ(op - 1, check_op(2)); |
52 | 4.38G | EQ_CHECK_READ(op, DO_NOTHING); |
53 | 4.38G | make_bool(op - 1, (obj_eq(imemory, op - 1, op) ? 1 : 0)); |
54 | 4.38G | pop(1); |
55 | 4.38G | return 0; |
56 | 4.38G | } |
57 | | |
58 | | /* <obj1> <obj2> ne <bool> */ |
59 | | int |
60 | | zne(i_ctx_t *i_ctx_p) |
61 | 980M | { /* We'll just be lazy and use eq. */ |
62 | 980M | int code = zeq(i_ctx_p); |
63 | | |
64 | 980M | if (!code) |
65 | 980M | osp->value.boolval ^= 1; |
66 | 980M | return code; |
67 | 980M | } |
68 | | |
69 | | /* <num1> <num2> ge <bool> */ |
70 | | /* <str1> <str2> ge <bool> */ |
71 | | int |
72 | | zge(i_ctx_t *i_ctx_p) |
73 | 9.40M | { |
74 | 9.40M | os_ptr op = osp; |
75 | 9.40M | int code; |
76 | | |
77 | 9.40M | check_op(2); |
78 | 9.40M | code = obj_le(op, op - 1); |
79 | 9.40M | if (code < 0) |
80 | 12 | return code; |
81 | 9.40M | make_bool(op - 1, code); |
82 | 9.40M | pop(1); |
83 | 9.40M | return 0; |
84 | 9.40M | } |
85 | | |
86 | | /* <num1> <num2> gt <bool> */ |
87 | | /* <str1> <str2> gt <bool> */ |
88 | | int |
89 | | zgt(i_ctx_t *i_ctx_p) |
90 | 342M | { |
91 | 342M | os_ptr op = osp; |
92 | 342M | int code; |
93 | | |
94 | 342M | check_op(2); |
95 | 342M | code = obj_le(op - 1, op); |
96 | 342M | if (code < 0) |
97 | 23 | return code; |
98 | 342M | make_bool(op - 1, code ^ 1); |
99 | 342M | pop(1); |
100 | 342M | return 0; |
101 | 342M | } |
102 | | |
103 | | /* <num1> <num2> le <bool> */ |
104 | | /* <str1> <str2> le <bool> */ |
105 | | int |
106 | | zle(i_ctx_t *i_ctx_p) |
107 | 37.5M | { |
108 | 37.5M | os_ptr op = osp; |
109 | 37.5M | int code; |
110 | | |
111 | 37.5M | check_op(2); |
112 | 37.5M | code = obj_le(op - 1, op); |
113 | 37.5M | if (code < 0) |
114 | 22 | return code; |
115 | 37.5M | make_bool(op - 1, code); |
116 | 37.5M | pop(1); |
117 | 37.5M | return 0; |
118 | 37.5M | } |
119 | | |
120 | | /* <num1> <num2> lt <bool> */ |
121 | | /* <str1> <str2> lt <bool> */ |
122 | | int |
123 | | zlt(i_ctx_t *i_ctx_p) |
124 | 22.5M | { |
125 | 22.5M | os_ptr op = osp; |
126 | 22.5M | int code; |
127 | | |
128 | 22.5M | check_op(2); |
129 | 22.5M | code = obj_le(op, op - 1); |
130 | 22.5M | if (code < 0) |
131 | 20 | return code; |
132 | 22.5M | make_bool(op - 1, code ^ 1); |
133 | 22.5M | pop(1); |
134 | 22.5M | return 0; |
135 | 22.5M | } |
136 | | |
137 | | /* <num1> <num2> .max <num> */ |
138 | | /* <str1> <str2> .max <str> */ |
139 | | static int |
140 | | zmax(i_ctx_t *i_ctx_p) |
141 | 4.00M | { |
142 | 4.00M | os_ptr op = osp; |
143 | 4.00M | int code; |
144 | | |
145 | 4.00M | check_op(2); |
146 | 4.00M | code = obj_le(op - 1, op); |
147 | 4.00M | if (code < 0) |
148 | 2 | return code; |
149 | 4.00M | if (code) { |
150 | 692k | ref_assign(op - 1, op); |
151 | 692k | } |
152 | 4.00M | pop(1); |
153 | 4.00M | return 0; |
154 | 4.00M | } |
155 | | |
156 | | /* <num1> <num2> .min <num> */ |
157 | | /* <str1> <str2> .min <str> */ |
158 | | static int |
159 | | zmin(i_ctx_t *i_ctx_p) |
160 | 3.01M | { |
161 | 3.01M | os_ptr op = osp; |
162 | 3.01M | int code; |
163 | | |
164 | 3.01M | check_op(2); |
165 | 3.01M | code = obj_le(op - 1, op); |
166 | 3.01M | if (code < 0) |
167 | 3 | return code; |
168 | 3.01M | if (!code) { |
169 | 5 | ref_assign(op - 1, op); |
170 | 5 | } |
171 | 3.01M | pop(1); |
172 | 3.01M | return 0; |
173 | 3.01M | } |
174 | | |
175 | | /* <bool1> <bool2> and <bool> */ |
176 | | /* <int1> <int2> and <int> */ |
177 | | int |
178 | | zand(i_ctx_t *i_ctx_p) |
179 | 591M | { |
180 | 591M | os_ptr op = osp; |
181 | | |
182 | 591M | check_op(2); |
183 | 591M | switch (r_type(op)) { |
184 | 591M | case t_boolean: |
185 | 591M | check_type(op[-1], t_boolean); |
186 | 591M | op[-1].value.boolval &= op->value.boolval; |
187 | 591M | break; |
188 | 835 | case t_integer: |
189 | 835 | check_type(op[-1], t_integer); |
190 | 830 | op[-1].value.intval &= op->value.intval; |
191 | 830 | break; |
192 | 13 | default: |
193 | 13 | return_op_typecheck(op); |
194 | 591M | } |
195 | 591M | pop(1); |
196 | 591M | return 0; |
197 | 591M | } |
198 | | |
199 | | /* <bool> not <bool> */ |
200 | | /* <int> not <int> */ |
201 | | int |
202 | | znot(i_ctx_t *i_ctx_p) |
203 | 397M | { |
204 | 397M | os_ptr op = osp; |
205 | | |
206 | 397M | check_op(1); |
207 | 397M | switch (r_type(op)) { |
208 | 397M | case t_boolean: |
209 | 397M | op->value.boolval = !op->value.boolval; |
210 | 397M | break; |
211 | 90 | case t_integer: |
212 | 90 | op->value.intval = ~op->value.intval; |
213 | 90 | break; |
214 | 16 | default: |
215 | 16 | return_op_typecheck(op); |
216 | 397M | } |
217 | 397M | return 0; |
218 | 397M | } |
219 | | |
220 | | /* <bool1> <bool2> or <bool> */ |
221 | | /* <int1> <int2> or <int> */ |
222 | | int |
223 | | zor(i_ctx_t *i_ctx_p) |
224 | 166M | { |
225 | 166M | os_ptr op = osp; |
226 | | |
227 | 166M | check_op(2); |
228 | 166M | switch (r_type(op)) { |
229 | 166M | case t_boolean: |
230 | 166M | check_type(op[-1], t_boolean); |
231 | 166M | op[-1].value.boolval |= op->value.boolval; |
232 | 166M | break; |
233 | 3.94k | case t_integer: |
234 | 3.94k | check_type(op[-1], t_integer); |
235 | 3.93k | op[-1].value.intval |= op->value.intval; |
236 | 3.93k | break; |
237 | 24 | default: |
238 | 24 | return_op_typecheck(op); |
239 | 166M | } |
240 | 166M | pop(1); |
241 | 166M | return 0; |
242 | 166M | } |
243 | | |
244 | | /* <bool1> <bool2> xor <bool> */ |
245 | | /* <int1> <int2> xor <int> */ |
246 | | int |
247 | | zxor(i_ctx_t *i_ctx_p) |
248 | 46 | { |
249 | 46 | os_ptr op = osp; |
250 | | |
251 | 46 | check_op(2); |
252 | 32 | switch (r_type(op)) { |
253 | 3 | case t_boolean: |
254 | 3 | check_type(op[-1], t_boolean); |
255 | 3 | op[-1].value.boolval ^= op->value.boolval; |
256 | 3 | break; |
257 | 19 | case t_integer: |
258 | 19 | check_type(op[-1], t_integer); |
259 | 16 | op[-1].value.intval ^= op->value.intval; |
260 | 16 | break; |
261 | 10 | default: |
262 | 10 | return_op_typecheck(op); |
263 | 32 | } |
264 | 19 | pop(1); |
265 | 19 | return 0; |
266 | 32 | } |
267 | | |
268 | | /* <int> <shift> bitshift <int> */ |
269 | | int |
270 | | zbitshift(i_ctx_t *i_ctx_p) |
271 | 247 | { |
272 | 247 | os_ptr op = osp; |
273 | 247 | int shift; |
274 | 247 | short max_shift = (sizeof(ps_int) * 8) - 1; |
275 | 247 | short max_shift32 = (sizeof(ps_int32) * 8) - 1; |
276 | | |
277 | 247 | check_op(2); |
278 | 231 | check_type(*op, t_integer); |
279 | 221 | check_type(op[-1], t_integer); |
280 | 213 | if ((op->value.intval < -max_shift) || (op->value.intval > max_shift)) |
281 | 24 | op[-1].value.intval = 0; |
282 | 189 | 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 | 189 | else if ((shift = op->value.intval) < 0) { |
285 | 37 | 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 | 37 | else { |
290 | 37 | op[-1].value.intval = ((ps_int)(op[-1].value.intval)) >> -shift; |
291 | 37 | } |
292 | 37 | } |
293 | 152 | else { |
294 | 152 | 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 | 152 | else |
300 | 152 | op[-1].value.intval <<= shift; |
301 | 152 | } |
302 | 213 | pop(1); |
303 | 213 | return 0; |
304 | 221 | } |
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 | 418M | { |
369 | 418M | switch (r_type(op1)) { |
370 | 275M | case t_integer: |
371 | 275M | switch (r_type(op)) { |
372 | 272M | case t_integer: |
373 | 272M | return (op1->value.intval <= op->value.intval); |
374 | 2.56M | case t_real: |
375 | 2.56M | return ((double)op1->value.intval <= op->value.realval); |
376 | 10 | default: |
377 | 10 | return_op_typecheck(op); |
378 | 275M | } |
379 | 31.1M | case t_real: |
380 | 31.1M | switch (r_type(op)) { |
381 | 31.1M | case t_real: |
382 | 31.1M | return (op1->value.realval <= op->value.realval); |
383 | 20.8k | case t_integer: |
384 | 20.8k | return (op1->value.realval <= (double)op->value.intval); |
385 | 8 | default: |
386 | 8 | return_op_typecheck(op); |
387 | 31.1M | } |
388 | 112M | case t_string: |
389 | 112M | check_read(*op1); |
390 | 112M | check_read_type(*op, t_string); |
391 | 112M | return (bytes_compare(op1->value.bytes, r_size(op1), |
392 | 112M | op->value.bytes, r_size(op)) <= 0); |
393 | 57 | default: |
394 | 57 | return_op_typecheck(op1); |
395 | 418M | } |
396 | 418M | } |