Coverage Report

Created: 2025-06-10 06:56

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