1 /* Copyright (C) 1989, 1995, 1997, 1998, 1999 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zrelbit.c,v 1.6 2004/08/04 19:36:13 stefan Exp $ */
18 /* Relational, boolean, and bit operators */
19 #include "ghost.h"
20 #include "oper.h"
21 #include "gsutil.h"
22 #include "idict.h"
23 #include "store.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 switch ( r_type(opp) ) {\
35 case t_string:\
36 check_read(*(opp));\
37 break;\
38 default:\
39 dflt;\
40 }
41
42 /* Forward references */
43 private int obj_le(os_ptr, os_ptr);
44
45 /* <obj1> <obj2> eq <bool> */
46 int
zeq(i_ctx_t * i_ctx_p)47 zeq(i_ctx_t *i_ctx_p)
48 {
49 os_ptr op = osp;
50 EQ_CHECK_READ(op - 1, check_op(2));
51 EQ_CHECK_READ(op, DO_NOTHING);
52 make_bool(op - 1, (obj_eq(imemory, op - 1, op) ? 1 : 0));
53 pop(1);
54 return 0;
55 }
56
57 /* <obj1> <obj2> ne <bool> */
58 int
zne(i_ctx_t * i_ctx_p)59 zne(i_ctx_t *i_ctx_p)
60 { /* We'll just be lazy and use eq. */
61 int code = zeq(i_ctx_p);
62
63 if (!code)
64 osp->value.boolval ^= 1;
65 return code;
66 }
67
68 /* <num1> <num2> ge <bool> */
69 /* <str1> <str2> ge <bool> */
70 int
zge(i_ctx_t * i_ctx_p)71 zge(i_ctx_t *i_ctx_p)
72 {
73 os_ptr op = osp;
74 int code = obj_le(op, op - 1);
75
76 if (code < 0)
77 return code;
78 make_bool(op - 1, code);
79 pop(1);
80 return 0;
81 }
82
83 /* <num1> <num2> gt <bool> */
84 /* <str1> <str2> gt <bool> */
85 int
zgt(i_ctx_t * i_ctx_p)86 zgt(i_ctx_t *i_ctx_p)
87 {
88 os_ptr op = osp;
89 int code = obj_le(op - 1, op);
90
91 if (code < 0)
92 return code;
93 make_bool(op - 1, code ^ 1);
94 pop(1);
95 return 0;
96 }
97
98 /* <num1> <num2> le <bool> */
99 /* <str1> <str2> le <bool> */
100 int
zle(i_ctx_t * i_ctx_p)101 zle(i_ctx_t *i_ctx_p)
102 {
103 os_ptr op = osp;
104 int code = obj_le(op - 1, op);
105
106 if (code < 0)
107 return code;
108 make_bool(op - 1, code);
109 pop(1);
110 return 0;
111 }
112
113 /* <num1> <num2> lt <bool> */
114 /* <str1> <str2> lt <bool> */
115 int
zlt(i_ctx_t * i_ctx_p)116 zlt(i_ctx_t *i_ctx_p)
117 {
118 os_ptr op = osp;
119 int code = obj_le(op, op - 1);
120
121 if (code < 0)
122 return code;
123 make_bool(op - 1, code ^ 1);
124 pop(1);
125 return 0;
126 }
127
128 /* <num1> <num2> .max <num> */
129 /* <str1> <str2> .max <str> */
130 private int
zmax(i_ctx_t * i_ctx_p)131 zmax(i_ctx_t *i_ctx_p)
132 {
133 os_ptr op = osp;
134 int code = obj_le(op - 1, op);
135
136 if (code < 0)
137 return code;
138 if (code) {
139 ref_assign(op - 1, op);
140 }
141 pop(1);
142 return 0;
143 }
144
145 /* <num1> <num2> .min <num> */
146 /* <str1> <str2> .min <str> */
147 private int
zmin(i_ctx_t * i_ctx_p)148 zmin(i_ctx_t *i_ctx_p)
149 {
150 os_ptr op = osp;
151 int code = obj_le(op - 1, op);
152
153 if (code < 0)
154 return code;
155 if (!code) {
156 ref_assign(op - 1, op);
157 }
158 pop(1);
159 return 0;
160 }
161
162 /* <bool1> <bool2> and <bool> */
163 /* <int1> <int2> and <int> */
164 int
zand(i_ctx_t * i_ctx_p)165 zand(i_ctx_t *i_ctx_p)
166 {
167 os_ptr op = osp;
168
169 switch (r_type(op)) {
170 case t_boolean:
171 check_type(op[-1], t_boolean);
172 op[-1].value.boolval &= op->value.boolval;
173 break;
174 case t_integer:
175 check_type(op[-1], t_integer);
176 op[-1].value.intval &= op->value.intval;
177 break;
178 default:
179 return_op_typecheck(op);
180 }
181 pop(1);
182 return 0;
183 }
184
185 /* <bool> not <bool> */
186 /* <int> not <int> */
187 int
znot(i_ctx_t * i_ctx_p)188 znot(i_ctx_t *i_ctx_p)
189 {
190 os_ptr op = osp;
191
192 switch (r_type(op)) {
193 case t_boolean:
194 op->value.boolval = !op->value.boolval;
195 break;
196 case t_integer:
197 op->value.intval = ~op->value.intval;
198 break;
199 default:
200 return_op_typecheck(op);
201 }
202 return 0;
203 }
204
205 /* <bool1> <bool2> or <bool> */
206 /* <int1> <int2> or <int> */
207 int
zor(i_ctx_t * i_ctx_p)208 zor(i_ctx_t *i_ctx_p)
209 {
210 os_ptr op = osp;
211
212 switch (r_type(op)) {
213 case t_boolean:
214 check_type(op[-1], t_boolean);
215 op[-1].value.boolval |= op->value.boolval;
216 break;
217 case t_integer:
218 check_type(op[-1], t_integer);
219 op[-1].value.intval |= op->value.intval;
220 break;
221 default:
222 return_op_typecheck(op);
223 }
224 pop(1);
225 return 0;
226 }
227
228 /* <bool1> <bool2> xor <bool> */
229 /* <int1> <int2> xor <int> */
230 int
zxor(i_ctx_t * i_ctx_p)231 zxor(i_ctx_t *i_ctx_p)
232 {
233 os_ptr op = osp;
234
235 switch (r_type(op)) {
236 case t_boolean:
237 check_type(op[-1], t_boolean);
238 op[-1].value.boolval ^= op->value.boolval;
239 break;
240 case t_integer:
241 check_type(op[-1], t_integer);
242 op[-1].value.intval ^= op->value.intval;
243 break;
244 default:
245 return_op_typecheck(op);
246 }
247 pop(1);
248 return 0;
249 }
250
251 /* <int> <shift> bitshift <int> */
252 int
zbitshift(i_ctx_t * i_ctx_p)253 zbitshift(i_ctx_t *i_ctx_p)
254 {
255 os_ptr op = osp;
256 int shift;
257
258 check_type(*op, t_integer);
259 check_type(op[-1], t_integer);
260 #define MAX_SHIFT (arch_sizeof_long * 8 - 1)
261 if (op->value.intval < -MAX_SHIFT || op->value.intval > MAX_SHIFT)
262 op[-1].value.intval = 0;
263 #undef MAX_SHIFT
264 else if ((shift = op->value.intval) < 0)
265 op[-1].value.intval = ((ulong)(op[-1].value.intval)) >> -shift;
266 else
267 op[-1].value.intval <<= shift;
268 pop(1);
269 return 0;
270 }
271
272 /* ------ Extensions ------ */
273
274 /* <obj1> <obj2> .identeq <bool> */
275 private int
zidenteq(i_ctx_t * i_ctx_p)276 zidenteq(i_ctx_t *i_ctx_p)
277 {
278 os_ptr op = osp;
279
280 EQ_CHECK_READ(op - 1, check_op(2));
281 EQ_CHECK_READ(op, DO_NOTHING);
282 make_bool(op - 1, (obj_ident_eq(imemory, op - 1, op) ? 1 : 0));
283 pop(1);
284 return 0;
285
286 }
287
288 /* <obj1> <obj2> .identne <bool> */
289 private int
zidentne(i_ctx_t * i_ctx_p)290 zidentne(i_ctx_t *i_ctx_p)
291 {
292 /* We'll just be lazy and use .identeq. */
293 int code = zidenteq(i_ctx_p);
294
295 if (!code)
296 osp->value.boolval ^= 1;
297 return code;
298 }
299
300 /* ------ Initialization procedure ------ */
301
302 const op_def zrelbit_op_defs[] =
303 {
304 {"2and", zand},
305 {"2bitshift", zbitshift},
306 {"2eq", zeq},
307 {"2ge", zge},
308 {"2gt", zgt},
309 {"2le", zle},
310 {"2lt", zlt},
311 {"2.max", zmax},
312 {"2.min", zmin},
313 {"2ne", zne},
314 {"1not", znot},
315 {"2or", zor},
316 {"2xor", zxor},
317 /* Extensions */
318 {"2.identeq", zidenteq},
319 {"2.identne", zidentne},
320 op_def_end(0)
321 };
322
323 /* ------ Internal routines ------ */
324
325 /* Compare two operands (both numeric, or both strings). */
326 /* Return 1 if op[-1] <= op[0], 0 if op[-1] > op[0], */
327 /* or a (negative) error code. */
328 private int
obj_le(register os_ptr op1,register os_ptr op)329 obj_le(register os_ptr op1, register os_ptr op)
330 {
331 switch (r_type(op1)) {
332 case t_integer:
333 switch (r_type(op)) {
334 case t_integer:
335 return (op1->value.intval <= op->value.intval);
336 case t_real:
337 return ((double)op1->value.intval <= op->value.realval);
338 default:
339 return_op_typecheck(op);
340 }
341 case t_real:
342 switch (r_type(op)) {
343 case t_real:
344 return (op1->value.realval <= op->value.realval);
345 case t_integer:
346 return (op1->value.realval <= (double)op->value.intval);
347 default:
348 return_op_typecheck(op);
349 }
350 case t_string:
351 check_read(*op1);
352 check_read_type(*op, t_string);
353 return (bytes_compare(op1->value.bytes, r_size(op1),
354 op->value.bytes, r_size(op)) <= 0);
355 default:
356 return_op_typecheck(op1);
357 }
358 }
359