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