xref: /plan9/sys/src/cmd/gs/src/zrelbit.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
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