/src/ghostpdl/psi/zrelbit.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 | | /* 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 | 4.85G | switch ( r_type(opp) ) {\ |
35 | 128M | case t_string:\ |
36 | 128M | check_read(*(opp));\ |
37 | 128M | break;\ |
38 | 4.73G | default:\ |
39 | 7.09G | dflt;\ |
40 | 4.85G | } |
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 | 2.42G | { |
49 | 2.42G | os_ptr op = osp; |
50 | 2.42G | EQ_CHECK_READ(op - 1, check_op(2)); |
51 | 2.42G | EQ_CHECK_READ(op, DO_NOTHING); |
52 | 2.42G | make_bool(op - 1, (obj_eq(imemory, op - 1, op) ? 1 : 0)); |
53 | 2.42G | pop(1); |
54 | 2.42G | return 0; |
55 | 2.42G | } |
56 | | |
57 | | /* <obj1> <obj2> ne <bool> */ |
58 | | int |
59 | | zne(i_ctx_t *i_ctx_p) |
60 | 529M | { /* We'll just be lazy and use eq. */ |
61 | 529M | int code = zeq(i_ctx_p); |
62 | | |
63 | 529M | if (!code) |
64 | 529M | osp->value.boolval ^= 1; |
65 | 529M | return code; |
66 | 529M | } |
67 | | |
68 | | /* <num1> <num2> ge <bool> */ |
69 | | /* <str1> <str2> ge <bool> */ |
70 | | int |
71 | | zge(i_ctx_t *i_ctx_p) |
72 | 4.85M | { |
73 | 4.85M | os_ptr op = osp; |
74 | 4.85M | int code = obj_le(op, op - 1); |
75 | | |
76 | 4.85M | if (code < 0) |
77 | 31 | return code; |
78 | 4.85M | make_bool(op - 1, code); |
79 | 4.85M | pop(1); |
80 | 4.85M | return 0; |
81 | 4.85M | } |
82 | | |
83 | | /* <num1> <num2> gt <bool> */ |
84 | | /* <str1> <str2> gt <bool> */ |
85 | | int |
86 | | zgt(i_ctx_t *i_ctx_p) |
87 | 174M | { |
88 | 174M | os_ptr op = osp; |
89 | 174M | int code = obj_le(op - 1, op); |
90 | | |
91 | 174M | if (code < 0) |
92 | 28 | return code; |
93 | 174M | make_bool(op - 1, code ^ 1); |
94 | 174M | pop(1); |
95 | 174M | return 0; |
96 | 174M | } |
97 | | |
98 | | /* <num1> <num2> le <bool> */ |
99 | | /* <str1> <str2> le <bool> */ |
100 | | int |
101 | | zle(i_ctx_t *i_ctx_p) |
102 | 29.3M | { |
103 | 29.3M | os_ptr op = osp; |
104 | 29.3M | int code = obj_le(op - 1, op); |
105 | | |
106 | 29.3M | if (code < 0) |
107 | 27 | return code; |
108 | 29.3M | make_bool(op - 1, code); |
109 | 29.3M | pop(1); |
110 | 29.3M | return 0; |
111 | 29.3M | } |
112 | | |
113 | | /* <num1> <num2> lt <bool> */ |
114 | | /* <str1> <str2> lt <bool> */ |
115 | | int |
116 | | zlt(i_ctx_t *i_ctx_p) |
117 | 11.1M | { |
118 | 11.1M | os_ptr op = osp; |
119 | 11.1M | int code = obj_le(op, op - 1); |
120 | | |
121 | 11.1M | if (code < 0) |
122 | 29 | return code; |
123 | 11.1M | make_bool(op - 1, code ^ 1); |
124 | 11.1M | pop(1); |
125 | 11.1M | return 0; |
126 | 11.1M | } |
127 | | |
128 | | /* <num1> <num2> .max <num> */ |
129 | | /* <str1> <str2> .max <str> */ |
130 | | static int |
131 | | zmax(i_ctx_t *i_ctx_p) |
132 | 358k | { |
133 | 358k | os_ptr op = osp; |
134 | 358k | int code = obj_le(op - 1, op); |
135 | | |
136 | 358k | if (code < 0) |
137 | 12 | return code; |
138 | 358k | if (code) { |
139 | 357k | ref_assign(op - 1, op); |
140 | 357k | } |
141 | 358k | pop(1); |
142 | 358k | return 0; |
143 | 358k | } |
144 | | |
145 | | /* <num1> <num2> .min <num> */ |
146 | | /* <str1> <str2> .min <str> */ |
147 | | static int |
148 | | zmin(i_ctx_t *i_ctx_p) |
149 | 1.76M | { |
150 | 1.76M | os_ptr op = osp; |
151 | 1.76M | int code = obj_le(op - 1, op); |
152 | | |
153 | 1.76M | if (code < 0) |
154 | 10 | return code; |
155 | 1.76M | if (!code) { |
156 | 1 | ref_assign(op - 1, op); |
157 | 1 | } |
158 | 1.76M | pop(1); |
159 | 1.76M | return 0; |
160 | 1.76M | } |
161 | | |
162 | | /* <bool1> <bool2> and <bool> */ |
163 | | /* <int1> <int2> and <int> */ |
164 | | int |
165 | | zand(i_ctx_t *i_ctx_p) |
166 | 322M | { |
167 | 322M | os_ptr op = osp; |
168 | | |
169 | 322M | switch (r_type(op)) { |
170 | 322M | case t_boolean: |
171 | 322M | check_type(op[-1], t_boolean); |
172 | 322M | op[-1].value.boolval &= op->value.boolval; |
173 | 322M | break; |
174 | 1.14k | case t_integer: |
175 | 1.14k | check_type(op[-1], t_integer); |
176 | 1.12k | op[-1].value.intval &= op->value.intval; |
177 | 1.12k | break; |
178 | 16 | default: |
179 | 16 | return_op_typecheck(op); |
180 | 322M | } |
181 | 322M | pop(1); |
182 | 322M | return 0; |
183 | 322M | } |
184 | | |
185 | | /* <bool> not <bool> */ |
186 | | /* <int> not <int> */ |
187 | | int |
188 | | znot(i_ctx_t *i_ctx_p) |
189 | 309M | { |
190 | 309M | os_ptr op = osp; |
191 | | |
192 | 309M | switch (r_type(op)) { |
193 | 309M | case t_boolean: |
194 | 309M | op->value.boolval = !op->value.boolval; |
195 | 309M | break; |
196 | 87 | case t_integer: |
197 | 87 | op->value.intval = ~op->value.intval; |
198 | 87 | break; |
199 | 13 | default: |
200 | 13 | return_op_typecheck(op); |
201 | 309M | } |
202 | 309M | return 0; |
203 | 309M | } |
204 | | |
205 | | /* <bool1> <bool2> or <bool> */ |
206 | | /* <int1> <int2> or <int> */ |
207 | | int |
208 | | zor(i_ctx_t *i_ctx_p) |
209 | 87.8M | { |
210 | 87.8M | os_ptr op = osp; |
211 | | |
212 | 87.8M | switch (r_type(op)) { |
213 | 87.8M | case t_boolean: |
214 | 87.8M | check_type(op[-1], t_boolean); |
215 | 87.8M | op[-1].value.boolval |= op->value.boolval; |
216 | 87.8M | break; |
217 | 473 | case t_integer: |
218 | 473 | check_type(op[-1], t_integer); |
219 | 463 | op[-1].value.intval |= op->value.intval; |
220 | 463 | break; |
221 | 22 | default: |
222 | 22 | return_op_typecheck(op); |
223 | 87.8M | } |
224 | 87.8M | pop(1); |
225 | 87.8M | return 0; |
226 | 87.8M | } |
227 | | |
228 | | /* <bool1> <bool2> xor <bool> */ |
229 | | /* <int1> <int2> xor <int> */ |
230 | | int |
231 | | zxor(i_ctx_t *i_ctx_p) |
232 | 33 | { |
233 | 33 | os_ptr op = osp; |
234 | | |
235 | 33 | switch (r_type(op)) { |
236 | 4 | case t_boolean: |
237 | 4 | check_type(op[-1], t_boolean); |
238 | 3 | op[-1].value.boolval ^= op->value.boolval; |
239 | 3 | break; |
240 | 20 | case t_integer: |
241 | 20 | check_type(op[-1], t_integer); |
242 | 13 | op[-1].value.intval ^= op->value.intval; |
243 | 13 | break; |
244 | 9 | default: |
245 | 9 | return_op_typecheck(op); |
246 | 33 | } |
247 | 16 | pop(1); |
248 | 16 | return 0; |
249 | 33 | } |
250 | | |
251 | | /* <int> <shift> bitshift <int> */ |
252 | | int |
253 | | zbitshift(i_ctx_t *i_ctx_p) |
254 | 115 | { |
255 | 115 | os_ptr op = osp; |
256 | 115 | int shift; |
257 | 115 | short max_shift = (sizeof(ps_int) * 8) - 1; |
258 | 115 | short max_shift32 = (sizeof(ps_int32) * 8) - 1; |
259 | | |
260 | 115 | check_type(*op, t_integer); |
261 | 101 | check_type(op[-1], t_integer); |
262 | 92 | if ((op->value.intval < -max_shift) || (op->value.intval > max_shift)) |
263 | 18 | op[-1].value.intval = 0; |
264 | 74 | else if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory) && (op->value.intval < -max_shift32 || op->value.intval > max_shift32)) |
265 | 0 | op[-1].value.intval = 0; |
266 | 74 | else if ((shift = op->value.intval) < 0) { |
267 | 33 | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
268 | 0 | ps_int32 val = (ps_int32)(op[-1].value.intval); |
269 | 0 | op[-1].value.intval = (ps_int)((uint)(val)) >> -shift; |
270 | 0 | } |
271 | 33 | else { |
272 | 33 | op[-1].value.intval = ((ps_int)(op[-1].value.intval)) >> -shift; |
273 | 33 | } |
274 | 33 | } |
275 | 41 | else { |
276 | 41 | if (sizeof(ps_int) != 4 && gs_currentcpsimode(imemory)) { |
277 | 0 | ps_int32 val = (ps_int32)(op[-1].value.intval); |
278 | |
|
279 | 0 | op[-1].value.intval = (ps_int)(val << shift); |
280 | 0 | } |
281 | 41 | else |
282 | 41 | op[-1].value.intval <<= shift; |
283 | 41 | } |
284 | 92 | pop(1); |
285 | 92 | return 0; |
286 | 101 | } |
287 | | |
288 | | /* ------ Extensions ------ */ |
289 | | |
290 | | /* <obj1> <obj2> .identeq <bool> */ |
291 | | static int |
292 | | zidenteq(i_ctx_t *i_ctx_p) |
293 | 0 | { |
294 | 0 | os_ptr op = osp; |
295 | |
|
296 | 0 | EQ_CHECK_READ(op - 1, check_op(2)); |
297 | 0 | EQ_CHECK_READ(op, DO_NOTHING); |
298 | 0 | make_bool(op - 1, (obj_ident_eq(imemory, op - 1, op) ? 1 : 0)); |
299 | 0 | pop(1); |
300 | 0 | return 0; |
301 | |
|
302 | 0 | } |
303 | | |
304 | | /* <obj1> <obj2> .identne <bool> */ |
305 | | static int |
306 | | zidentne(i_ctx_t *i_ctx_p) |
307 | 0 | { |
308 | | /* We'll just be lazy and use .identeq. */ |
309 | 0 | int code = zidenteq(i_ctx_p); |
310 | |
|
311 | 0 | if (!code) |
312 | 0 | osp->value.boolval ^= 1; |
313 | 0 | return code; |
314 | 0 | } |
315 | | |
316 | | /* ------ Initialization procedure ------ */ |
317 | | |
318 | | const op_def zrelbit_op_defs[] = |
319 | | { |
320 | | {"2and", zand}, |
321 | | {"2bitshift", zbitshift}, |
322 | | {"2eq", zeq}, |
323 | | {"2ge", zge}, |
324 | | {"2gt", zgt}, |
325 | | {"2le", zle}, |
326 | | {"2lt", zlt}, |
327 | | {"2.max", zmax}, |
328 | | {"2.min", zmin}, |
329 | | {"2ne", zne}, |
330 | | {"1not", znot}, |
331 | | {"2or", zor}, |
332 | | {"2xor", zxor}, |
333 | | /* Extensions */ |
334 | | {"2.identeq", zidenteq}, |
335 | | {"2.identne", zidentne}, |
336 | | op_def_end(0) |
337 | | }; |
338 | | |
339 | | /* ------ Internal routines ------ */ |
340 | | |
341 | | /* Compare two operands (both numeric, or both strings). */ |
342 | | /* Return 1 if op[-1] <= op[0], 0 if op[-1] > op[0], */ |
343 | | /* or a (negative) error code. */ |
344 | | static int |
345 | | obj_le(register os_ptr op1, register os_ptr op) |
346 | 222M | { |
347 | 222M | switch (r_type(op1)) { |
348 | 158M | case t_integer: |
349 | 158M | switch (r_type(op)) { |
350 | 156M | case t_integer: |
351 | 156M | return (op1->value.intval <= op->value.intval); |
352 | 1.46M | case t_real: |
353 | 1.46M | return ((double)op1->value.intval <= op->value.realval); |
354 | 12 | default: |
355 | 12 | return_op_typecheck(op); |
356 | 158M | } |
357 | 14.1M | case t_real: |
358 | 14.1M | switch (r_type(op)) { |
359 | 14.1M | case t_real: |
360 | 14.1M | return (op1->value.realval <= op->value.realval); |
361 | 7.36k | case t_integer: |
362 | 7.36k | return (op1->value.realval <= (double)op->value.intval); |
363 | 13 | default: |
364 | 13 | return_op_typecheck(op); |
365 | 14.1M | } |
366 | 49.8M | case t_string: |
367 | 49.8M | check_read(*op1); |
368 | 49.8M | check_read_type(*op, t_string); |
369 | 49.8M | return (bytes_compare(op1->value.bytes, r_size(op1), |
370 | 49.8M | op->value.bytes, r_size(op)) <= 0); |
371 | 100 | default: |
372 | 100 | return_op_typecheck(op1); |
373 | 222M | } |
374 | 222M | } |