Coverage Report

Created: 2026-10-28 08:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ghostpdl/base/gsfunc4.c
Line
Count
Source
1
/* Copyright (C) 2001-2026 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
/* Implementation of FunctionType 4 (PostScript Calculator) Functions */
18
#include "math_.h"
19
#include "memory_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsdsrc.h"
23
#include "gsfunc4.h"
24
#include "gxfarith.h"
25
#include "gxfunc.h"
26
#include "stream.h"
27
#include "strimpl.h"
28
#include "sfilter.h"    /* for SubFileDecode */
29
#include "spprint.h"
30
#include "stream.h"
31
32
typedef struct gs_function_PtCr_s {
33
    gs_function_head_t head;
34
    gs_function_PtCr_params_t params;
35
    /* Define a bogus DataSource for get_function_info. */
36
    gs_data_source_t data_source;
37
} gs_function_PtCr_t;
38
39
/* GC descriptor */
40
private_st_function_PtCr();
41
42
/* Define the maximum stack depth. */
43
87.5M
#define MAX_VSTACK 256    /* Max 100 is enough per PDF spec, but we use this
44
                                 * for DeviceN handling. Must be at least as large
45
                                 * as the number of components
46
                                 */
47
48
/* Define the structure of values on the stack. */
49
typedef enum {
50
    CVT_NONE = 0, /* empty stack slot */
51
    CVT_BOOL,
52
    CVT_INT,
53
    CVT_FLOAT
54
} calc_value_type_t;
55
typedef struct calc_value_s {
56
    calc_value_type_t type;
57
    union {
58
        int i;      /* also used for Boolean */
59
        float f;
60
    } value;
61
} calc_value_t;
62
63
/* Store a float. */
64
static inline void
65
store_float(calc_value_t *vsp, double f)
66
38.0M
{
67
38.0M
    vsp->value.f = f;
68
38.0M
    vsp->type = CVT_FLOAT;
69
38.0M
}
70
71
/*
72
 * Define extended opcodes with typed operands.  We use the original
73
 * opcodes for the floating-point case.
74
 */
75
typedef enum {
76
77
        /* Typed variants */
78
79
    PtCr_abs_int = PtCr_NUM_OPCODES,
80
    PtCr_add_int,
81
    PtCr_mul_int,
82
    PtCr_neg_int,
83
    PtCr_not_bool,    /* default is int */
84
    PtCr_sub_int,
85
    PtCr_eq_int,
86
    PtCr_ge_int,
87
    PtCr_gt_int,
88
    PtCr_le_int,
89
    PtCr_lt_int,
90
    PtCr_ne_int,
91
92
        /* Coerce and re-dispatch */
93
94
    PtCr_int_to_float,
95
    PtCr_2nd_int_to_float,
96
    PtCr_int2_to_float,
97
98
        /* Miscellaneous */
99
100
    PtCr_no_op,
101
    PtCr_typecheck
102
103
} gs_PtCr_typed_opcode_t;
104
105
/* Evaluate a PostScript Calculator function. */
106
static int
107
fn_PtCr_evaluate(const gs_function_t *pfn_common, const float *in, float *out)
108
6.37M
{
109
6.37M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
6.37M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
6.37M
    calc_value_t *vstack = &vstack_buf[1];
112
6.37M
    calc_value_t *vsp = vstack + pfn->params.m;
113
6.37M
    const byte *p = pfn->params.ops.data;
114
6.37M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
6.37M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
6.37M
    int repeat_nesting_level = -1;
117
6.37M
    int i;
118
119
    /*
120
     * Define the table for mapping explicit opcodes to typed opcodes.
121
     * We index this table with the opcode and the types of the top 2
122
     * values on the stack.
123
     */
124
6.37M
    static const struct op_defn_s {
125
6.37M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
6.37M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
465M
#define O4(op) op,op,op,op
130
1.02G
#define E PtCr_typecheck
131
261M
#define E4 O4(E)
132
6.37M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
6.37M
#define OP_NONE(op)\
135
51.0M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
6.37M
#define OP1(b, i, f)\
138
127M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
6.37M
#define OP_NUM1(i, f)\
140
51.0M
  OP1(E, i, f)
141
6.37M
#define OP_MATH1(f)\
142
31.8M
  OP1(E, PtCr_int_to_float, f)
143
6.37M
#define OP_ANY1(op)\
144
12.7M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
6.37M
#define OP_NUM2(i, f)\
147
44.6M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
6.37M
#define OP_INT_BOOL2(i)\
149
19.1M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
6.37M
#define OP_MATH2(f)\
151
19.1M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
19.1M
    E,E,PtCr_int_to_float,f}}
153
6.37M
#define OP_INT2(i)\
154
25.5M
  {{E4, E4, E,E,i,E, E4}}
155
6.37M
#define OP_REL2(i, f)\
156
12.7M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
6.37M
#define OP_ANY2(op)\
158
6.37M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
6.37M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
6.37M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
6.37M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
6.37M
        OP_MATH2(PtCr_atan),  /* atan */
166
6.37M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
6.37M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
6.37M
        OP_MATH1(PtCr_cos), /* cos */
169
6.37M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
6.37M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
6.37M
        OP_MATH2(PtCr_div), /* div */
172
6.37M
        OP_MATH2(PtCr_exp), /* exp */
173
6.37M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
6.37M
        OP_INT2(PtCr_idiv),  /* idiv */
175
6.37M
        OP_MATH1(PtCr_ln),  /* ln */
176
6.37M
        OP_MATH1(PtCr_log), /* log */
177
6.37M
        OP_INT2(PtCr_mod), /* mod */
178
6.37M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
6.37M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
6.37M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
6.37M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
6.37M
        OP_NUM1(N, PtCr_round),  /* round */
183
6.37M
        OP_MATH1(PtCr_sin), /* sin */
184
6.37M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
6.37M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
6.37M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
6.37M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
6.37M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
6.37M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
6.37M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
6.37M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
6.37M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
6.37M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
6.37M
        OP1(E, PtCr_copy, E),  /* copy */
201
6.37M
        OP_ANY1(PtCr_dup), /* dup */
202
6.37M
        OP_ANY2(PtCr_exch),  /* exch */
203
6.37M
        OP1(E, PtCr_index, E), /* index */
204
6.37M
        OP_ANY1(PtCr_pop), /* pop */
205
6.37M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
6.37M
        OP_NONE(PtCr_byte),    /* byte */
210
6.37M
        OP_NONE(PtCr_int),   /* int */
211
6.37M
        OP_NONE(PtCr_float),   /* float */
212
6.37M
        OP_NONE(PtCr_true),    /* true */
213
6.37M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
6.37M
        OP1(PtCr_if, E, E),    /* if */
218
6.37M
        OP_NONE(PtCr_else),    /* else */
219
6.37M
        OP_NONE(PtCr_return),    /* return */
220
6.37M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
6.37M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
6.37M
    };
223
224
6.37M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
6.37M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
6.37M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
6.37M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
26.5M
    for (i = 0; i < pfn->params.m; ++i)
230
20.1M
        store_float(&vstack[i + 1], in[i]);
231
232
162M
    for (; ; ) {
233
162M
        int code, n;
234
235
162M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
2.10M
        case PtCr_no_op:
240
2.10M
            continue;
241
35
        case PtCr_typecheck:
242
35
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
14.0M
        case PtCr_int_to_float:
247
14.0M
            store_float(vsp, (double)vsp->value.i);
248
14.0M
            --p; continue;
249
159k
        case PtCr_int2_to_float:
250
159k
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
3.69M
        case PtCr_2nd_int_to_float:
253
3.69M
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
3.69M
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
3.89M
        case PtCr_abs:
259
3.89M
            vsp->value.f = fabs(vsp->value.f);
260
3.89M
            continue;
261
0
        case PtCr_add_int: {
262
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
263
264
            /* Test the signs first, if they are different then integer addition can't overflow */
265
0
            if ((int1 ^ int2) < 0) {
266
0
                vsp[-1].value.i = int1 - int2;
267
0
            } else {
268
0
                unsigned int u1, u2;
269
270
0
                if (int1 < 0) {
271
                    /* minimum signed int converted to unsigned, doubled, can overflow */
272
0
                    u1 = (unsigned int)(~int1) + 1;
273
0
                    u2 = u1 + (unsigned int)(~int2) + 1;
274
275
0
                    if (u2 < u1 || u2 > (unsigned int)max_int + 1)
276
0
                        store_float(vsp - 1, (double)int1 - int2);
277
0
                    else
278
0
                        vsp[-1].value.i = int1 - int2;
279
0
                } else {
280
                    /* maximum signed int + maximum signed int fits into an unsigned int, so no overflow */
281
0
                    u1 = int1 + int2;
282
283
0
                    if (u1 > (unsigned int)max_int)
284
0
                        store_float(vsp - 1, (double)int1 - int2);
285
0
                    else
286
0
                        vsp[-1].value.i = int1 - int2;
287
0
                }
288
0
            }
289
0
            --vsp; continue;
290
159k
        }
291
1.19M
        case PtCr_add:
292
1.19M
            vsp[-1].value.f += vsp->value.f;
293
1.19M
            --vsp; continue;
294
0
        case PtCr_and:
295
0
            vsp[-1].value.i &= vsp->value.i;
296
0
            --vsp; continue;
297
2.58M
        case PtCr_atan: {
298
2.58M
            double result;
299
300
2.58M
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
301
2.58M
                                    &result);
302
2.58M
            if (code < 0)
303
0
                return code;
304
2.58M
            vsp[-1].value.f = result;
305
2.58M
            --vsp; continue;
306
2.58M
        }
307
0
        case PtCr_bitshift:
308
0
#define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
309
0
            if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
310
0
                vsp[-1].value.i = 0;
311
0
#undef MAX_SHIFT
312
0
            else if ((n = vsp->value.i) < 0)
313
0
                vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
314
0
            else
315
0
                vsp[-1].value.i <<= n;
316
0
            --vsp; continue;
317
0
        case PtCr_ceiling:
318
0
            vsp->value.f = ceil(vsp->value.f);
319
0
            continue;
320
2.58M
        case PtCr_cos:
321
2.58M
            vsp->value.f = gs_cos_degrees(vsp->value.f);
322
2.58M
            continue;
323
0
        case PtCr_cvi:
324
0
        {
325
           /* Strictly speaking assigning one element of union
326
            * to another, overlapping element of a different size is
327
            * undefined behavior, hence assign to an intermediate variable
328
            */
329
0
            int int1 = (int)(vsp->value.f);
330
0
            vsp->value.i = int1;
331
0
            vsp->type = CVT_INT;
332
0
            continue;
333
2.58M
        }
334
0
        case PtCr_cvr:
335
0
            continue;  /* prepare handled it */
336
3.29M
        case PtCr_div:
337
3.29M
            if (vsp->value.f == 0)
338
0
                return_error(gs_error_undefinedresult);
339
3.29M
            vsp[-1].value.f /= vsp->value.f;
340
3.29M
            --vsp; continue;
341
0
        case PtCr_exp:
342
0
            vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
343
0
            --vsp; continue;
344
0
        case PtCr_floor:
345
0
            vsp->value.f = floor(vsp->value.f);
346
0
            continue;
347
0
        case PtCr_idiv:
348
0
            if (vsp->value.i == 0)
349
0
                return_error(gs_error_undefinedresult);
350
0
            if (vsp[-1].value.i == min_int &&
351
0
                vsp->value.i == -1)  /* anomalous boundary case, fail */
352
0
                return_error(gs_error_rangecheck);
353
0
            else
354
0
                vsp[-1].value.i /= vsp->value.i;
355
0
            --vsp; continue;
356
0
        case PtCr_ln:
357
0
            vsp->value.f = log(vsp->value.f);
358
0
            continue;
359
0
        case PtCr_log:
360
0
            vsp->value.f = log10(vsp->value.f);
361
0
            continue;
362
0
        case PtCr_mod:
363
0
            if (vsp->value.i == 0)
364
0
                return_error(gs_error_undefinedresult);
365
0
            if (vsp[-1].value.i == min_int &&
366
0
                vsp->value.i == -1)  /* anomalous boundary case, fail */
367
0
                return_error(gs_error_rangecheck);
368
0
            vsp[-1].value.i %= vsp->value.i;
369
0
            --vsp; continue;
370
2.89M
        case PtCr_mul_int: {
371
            /* We don't bother to optimize this. */
372
2.89M
            double prod = (double)vsp[-1].value.i * vsp->value.i;
373
374
2.89M
            if (prod < min_int || prod > max_int)
375
0
                store_float(vsp - 1, prod);
376
2.89M
            else
377
2.89M
                vsp[-1].value.i = (int)prod;
378
2.89M
            --vsp; continue;
379
0
        }
380
4.36M
        case PtCr_mul:
381
4.36M
            vsp[-1].value.f *= vsp->value.f;
382
4.36M
            --vsp; continue;
383
159k
        case PtCr_abs_int:
384
159k
            if (vsp->value.i >= 0)
385
159k
                continue;
386
            /* fallthrough */
387
0
        case PtCr_neg_int:
388
0
            if (vsp->value.i == min_int)
389
0
                store_float(vsp, (double)vsp->value.i); /* =self negated */
390
0
            else
391
0
                vsp->value.i = -vsp->value.i;
392
0
            continue;
393
0
        case PtCr_neg:
394
0
            vsp->value.f = -vsp->value.f;
395
0
            continue;
396
0
        case PtCr_not_bool:
397
0
            vsp->value.i = !vsp->value.i;
398
0
            continue;
399
0
        case PtCr_not:
400
0
            vsp->value.i = ~vsp->value.i;
401
0
            continue;
402
0
        case PtCr_or:
403
0
            vsp[-1].value.i |= vsp->value.i;
404
0
            --vsp; continue;
405
0
        case PtCr_round:
406
0
            vsp->value.f = floor(vsp->value.f + 0.5);
407
0
            continue;
408
3.29M
        case PtCr_sin:
409
3.29M
            vsp->value.f = gs_sin_degrees(vsp->value.f);
410
3.29M
            continue;
411
3.29M
        case PtCr_sqrt:
412
3.29M
            if (vsp->value.f < 0.0)
413
0
                return_error(gs_error_rangecheck);
414
3.29M
            vsp->value.f = sqrt(vsp->value.f);
415
3.29M
            continue;
416
0
        case PtCr_sub_int: {
417
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
418
419
            /* Test the signs first, if they are the same then integer subtraction can't overflow */
420
0
            if ((int1 ^ int2) >= 0) {
421
0
                vsp[-1].value.i = int1 - int2;
422
0
            } else {
423
0
                unsigned int u1, u2;
424
425
0
                if (int1 < 0) {
426
                    /* -ve minus +ve, convert -ve to +ve and add as unsigned, defined behaviour if overflow (wraps round) */
427
0
                    u1 = (unsigned int)(~int1) + 1;
428
0
                    u2 = u1 + int2;
429
                    /* If adding 2 positive values produced a smaller value, then the addition overflowed.
430
                     * If the result is larger than the max signed int (+1 for -ve) then subtraction will overflow
431
                     */
432
0
                    if (u2 < u1 || u2 > ((unsigned int)max_int + 1))
433
0
                        store_float(vsp - 1, (double)int1 - int2);
434
0
                    else
435
0
                        vsp[-1].value.i = int1 - int2;
436
0
                } else {
437
                    /* +ve minus -ve = +ve plus +ve, can overflow a *signed* int, but not an unsigned int */
438
0
                    u1 = int1 + ((unsigned int)(~int2) + 1);
439
0
                    if (u1 > (unsigned int)max_int)
440
0
                        store_float(vsp - 1, (double)int1 - int2);
441
0
                    else
442
0
                        vsp[-1].value.i = int1 - int2;
443
0
                }
444
0
            }
445
0
            --vsp; continue;
446
3.29M
        }
447
12.6M
        case PtCr_sub:
448
12.6M
            vsp[-1].value.f -= vsp->value.f;
449
12.6M
            --vsp; continue;
450
5
        case PtCr_truncate:
451
5
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
452
5
                            floor(vsp->value.f));
453
5
            continue;
454
0
        case PtCr_xor:
455
0
            vsp[-1].value.i ^= vsp->value.i;
456
0
            --vsp; continue;
457
458
            /* Boolean operators */
459
460
0
#define DO_REL(rel, m)\
461
3.59M
  vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
462
463
0
        case PtCr_eq_int:
464
0
            DO_REL(==, i);
465
0
            goto rel;
466
17
        case PtCr_ge_int:
467
17
            DO_REL(>=, i);
468
17
            goto rel;
469
46
        case PtCr_ge:
470
46
            DO_REL(>=, f);
471
46
            goto rel;
472
336
        case PtCr_gt_int:
473
336
            DO_REL(>, i);
474
336
            goto rel;
475
112
        case PtCr_gt:
476
112
            DO_REL(>, f);
477
112
            goto rel;
478
0
        case PtCr_le_int:
479
0
            DO_REL(<=, i);
480
0
            goto rel;
481
298k
        case PtCr_le:
482
298k
            DO_REL(<=, f);
483
298k
            goto rel;
484
0
        case PtCr_lt_int:
485
0
            DO_REL(<, i);
486
0
            goto rel;
487
3.29M
        case PtCr_lt:
488
3.29M
            DO_REL(<, f);
489
3.29M
            goto rel;
490
0
        case PtCr_ne_int:
491
0
            DO_REL(!=, i);
492
0
            goto rel;
493
0
        case PtCr_ne:
494
0
            DO_REL(!=, f);
495
0
            goto rel;
496
0
        case PtCr_eq:
497
0
            DO_REL(==, f);
498
3.59M
        rel:
499
3.59M
            vsp[-1].type = CVT_BOOL;
500
3.59M
            --vsp; continue;
501
502
0
#undef DO_REL
503
504
            /* Stack operators */
505
506
298k
        case PtCr_copy:
507
298k
            i = vsp->value.i;
508
298k
            n = vsp - vstack;
509
298k
            if (i < 0 || i >= n)
510
0
                return_error(gs_error_rangecheck);
511
298k
            if (i > MAX_VSTACK - (n - 1))
512
0
                return_error(gs_error_limitcheck);
513
298k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
514
298k
            vsp += i - 1;
515
298k
            continue;
516
13.0M
        case PtCr_dup:
517
13.0M
            vsp[1] = *vsp;
518
13.0M
            goto push;
519
15.4M
        case PtCr_exch:
520
15.4M
            vstack[MAX_VSTACK] = *vsp;
521
15.4M
            *vsp = vsp[-1];
522
15.4M
            vsp[-1] = vstack[MAX_VSTACK];
523
15.4M
            continue;
524
522k
        case PtCr_index:
525
522k
            i = vsp->value.i;
526
522k
            if (i < 0 || i >= vsp - vstack - 1)
527
0
                return_error(gs_error_rangecheck);
528
522k
            *vsp = vsp[-i - 1];
529
522k
            continue;
530
8.94M
        case PtCr_pop:
531
8.94M
            --vsp;
532
8.94M
            continue;
533
7.22M
        case PtCr_roll:
534
7.22M
            n = vsp[-1].value.i;
535
7.22M
            i = vsp->value.i;
536
7.22M
            if (n < 0 || n > vsp - vstack - 2)
537
0
                return_error(gs_error_rangecheck);
538
            /* We don't bother to do this efficiently. */
539
17.3M
            for (; i > 0; i--) {
540
10.1M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
541
10.1M
                vsp[-(n + 1)] = vsp[-1];
542
10.1M
            }
543
8.87M
            for (; i < 0; i++) {
544
1.65M
                vsp[-1] = vsp[-(n + 1)];
545
1.65M
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
546
1.65M
            }
547
7.22M
            vsp -= 2;
548
7.22M
            continue;
549
550
            /* Constants */
551
552
28.5M
        case PtCr_byte:
553
28.5M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
554
28.5M
            goto push;
555
7.53M
        case PtCr_int /* native */:
556
7.53M
            memcpy(&vsp[1].value.i, p, sizeof(int));
557
7.53M
            vsp[1].type = CVT_INT;
558
7.53M
            p += sizeof(int);
559
7.53M
            goto push;
560
6.97M
        case PtCr_float /* native */:
561
6.97M
            memcpy(&vsp[1].value.f, p, sizeof(float));
562
6.97M
            vsp[1].type = CVT_FLOAT;
563
6.97M
            p += sizeof(float);
564
6.97M
            goto push;
565
0
        case PtCr_true:
566
0
            vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
567
0
            goto push;
568
0
        case PtCr_false:
569
0
            vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
570
56.1M
        push:
571
56.1M
            if (vsp == &vstack[MAX_VSTACK])
572
0
                return_error(gs_error_limitcheck);
573
56.1M
            ++vsp;
574
56.1M
            continue;
575
576
            /* Special */
577
578
3.59M
        case PtCr_if:
579
3.59M
            if ((vsp--)->value.i) { /* value is true, execute body */
580
3.04M
                p += 2;
581
3.04M
                continue;
582
3.04M
            }
583
            /* falls through */
584
698k
        case PtCr_else:
585
698k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
586
698k
            continue;
587
6.37M
        case PtCr_return:
588
6.37M
            goto fin;
589
0
        case PtCr_repeat:
590
0
            repeat_nesting_level++;
591
0
            repeat_count[repeat_nesting_level] = vsp->value.i;
592
0
            repeat_proc_size[repeat_nesting_level] = 1 + (p[0] << 8) + p[1];  /* body size */
593
0
            --vsp;    /* pop the counter */
594
0
            p += 3 + (p[0] <<8) + p[1];       /* advance just past the repeat_end */
595
            /* falls through */
596
0
        case PtCr_repeat_end:
597
0
            if (repeat_nesting_level < 0)
598
0
                return_error(gs_error_rangecheck);
599
600
0
            if ((repeat_count[repeat_nesting_level])-- <= 0)
601
0
                repeat_nesting_level--;
602
0
            else
603
0
                p -= repeat_proc_size[repeat_nesting_level];
604
0
            continue;
605
162M
        }
606
162M
    }
607
6.37M
 fin:
608
6.37M
    {   /* Following Acrobat, take the desired number of parameters */
609
        /* from the top of stack and ignore the rest. Bug 702950. */
610
6.37M
        int extra_ops = vsp - vstack - pfn->params.n;
611
6.37M
        if (extra_ops < 0)
612
63
            return_error(gs_error_rangecheck);
613
25.1M
        for (i = 0; i < pfn->params.n; ++i) {
614
18.7M
            switch (vstack[i + 1 + extra_ops].type) {
615
15.1k
            case CVT_INT:
616
15.1k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
617
15.1k
                break;
618
18.7M
            case CVT_FLOAT:
619
18.7M
                out[i] = vstack[i + 1 + extra_ops].value.f;
620
18.7M
                break;
621
0
            default:
622
0
                return_error(gs_error_typecheck);
623
18.7M
            }
624
18.7M
        }
625
6.37M
    }
626
6.37M
    return 0;
627
6.37M
}
628
629
/* Test whether a PostScript Calculator function is monotonic. */
630
static int
631
fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
632
                     const float *lower, const float *upper, uint *mask)
633
0
{
634
    /*
635
     * No reasonable way to tell.  Eventually we should check for
636
     * functions consisting of only stack-manipulating operations,
637
     * since these may be common for DeviceN color spaces and *are*
638
     * monotonic.
639
     */
640
0
    *mask = 0x49249249;
641
0
    return 0;
642
0
}
643
644
/* Write the function definition in symbolic form on a stream. */
645
static int
646
calc_put_ops(stream *s, const byte *ops, uint size)
647
1.57k
{
648
1.57k
    const byte *p;
649
650
1.57k
    spputc(s, '{');
651
13.1k
    for (p = ops; p < ops + size; )
652
11.5k
        switch (*p++) {
653
3.30k
        case PtCr_byte:
654
3.30k
            pprintd1(s, "%d ", *p++);
655
3.30k
            break;
656
620
        case PtCr_int: {
657
620
            int i;
658
659
620
            memcpy(&i, p, sizeof(int));
660
620
            pprintd1(s, "%d ", i);
661
620
            p += sizeof(int);
662
620
            break;
663
0
        }
664
3.08k
        case PtCr_float: {
665
3.08k
            float f;
666
667
3.08k
            memcpy(&f, p, sizeof(float));
668
3.08k
            pprintg1(s, "%g ", f);
669
3.08k
            p += sizeof(float);
670
3.08k
            break;
671
0
        }
672
0
        case PtCr_true:
673
0
            stream_puts(s, "true ");
674
0
            break;
675
0
        case PtCr_false:
676
0
            stream_puts(s, "false ");
677
0
            break;
678
166
        case PtCr_if: {
679
166
            int skip = (p[0] << 8) + p[1];
680
166
            int code;
681
682
166
            code = calc_put_ops(s, p += 2, skip);
683
166
            p += skip;
684
166
            if (code < 0)
685
0
                return code;
686
166
            if (code > 0) { /* else */
687
0
                skip = (p[-2] << 8) + p[-1];
688
0
                code = calc_put_ops(s, p, skip);
689
0
                p += skip;
690
0
                if (code < 0)
691
0
                    return code;
692
0
                stream_puts(s, " ifelse ");
693
0
            } else
694
166
                stream_puts(s, " if ");
695
166
            break;
696
166
        }
697
166
        case PtCr_else:
698
0
            if (p != ops + size - 2)
699
0
                return_error(gs_error_rangecheck);
700
0
            spputc(s, '}');
701
0
            return 1;
702
        /*case PtCr_return:*/ /* not possible */
703
0
        case PtCr_repeat:   /* We shouldn't encounter this, but just in case */
704
0
        case PtCr_repeat_end:
705
0
            return_error(gs_error_rangecheck);
706
4.37k
        default: {    /* must be < PtCr_NUM_OPS */
707
4.37k
                static const char *const op_names[] = {
708
                    /* Keep this consistent with opcodes in gsfunc4.h! */
709
4.37k
                    "abs", "add", "and", "atan", "bitshift",
710
4.37k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
711
4.37k
                    "floor", "idiv", "ln", "log", "mod", "mul",
712
4.37k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
713
4.37k
                    "truncate", "xor",
714
4.37k
                    "eq", "ge", "gt", "le", "lt", "ne",
715
4.37k
                    "copy", "dup", "exch", "index", "pop", "roll"
716
4.37k
                };
717
718
4.37k
                pprints1(s, "%s ", op_names[p[-1]]);
719
4.37k
            }
720
11.5k
        }
721
1.57k
    spputc(s, '}');
722
1.57k
    return 0;
723
1.57k
}
724
static int
725
calc_put(stream *s, const gs_function_PtCr_t *pfn)
726
1.40k
{
727
1.40k
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
728
1.40k
    return 0;
729
1.40k
}
730
731
/* Access the symbolic definition as a DataSource. */
732
static int
733
calc_access(const gs_data_source_t *psrc, ulong start, uint length,
734
            byte *buf, const byte **ptr)
735
726
{
736
726
    const gs_function_PtCr_t *const pfn =
737
726
        (const gs_function_PtCr_t *)
738
726
          ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
739
    /*
740
     * The caller wants a specific substring of the symbolic definition.
741
     * Generate the entire definition, using a SubFileDecode filter (in an
742
     * output pipeline!) to extract the substring.  This is very
743
     * inefficient, but this code is rarely used, and almost never actually
744
     * has to break up the definition into pieces to fit in the caller's
745
     * buffer.
746
     */
747
726
    stream_SFD_state st;
748
726
    stream ds, bs;
749
726
    byte dbuf[200];   /* arbitrary */
750
726
    const stream_template *const templat = &s_SFD_template;
751
752
    /* Set up the stream that writes into the buffer. */
753
726
    s_init(&bs, NULL);
754
726
    swrite_string(&bs, buf, length);
755
    /* Set up the SubFileDecode stream. */
756
726
    s_init(&ds, NULL);
757
726
    s_init_state((stream_state *)&st, templat, NULL);
758
726
    templat->set_defaults((stream_state *)&st);
759
726
    st.skip_count = start;
760
726
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
761
726
    calc_put(&ds, pfn);
762
726
    sclose(&ds);
763
726
    if (ptr)
764
726
        *ptr = buf;
765
726
    return 0;
766
726
}
767
768
/* Return PostScript Calculator function information. */
769
static void
770
fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
771
682
{
772
682
    const gs_function_PtCr_t *const pfn =
773
682
        (const gs_function_PtCr_t *)pfn_common;
774
775
682
    gs_function_get_info_default(pfn_common, pfi);
776
682
    pfi->DataSource = &pfn->data_source;
777
682
    {
778
682
        stream s;
779
780
682
        s_init(&s, NULL);
781
682
        swrite_position_only(&s);
782
682
        calc_put(&s, pfn);
783
682
        pfi->data_size = stell(&s);
784
682
    }
785
682
}
786
787
/* Make a scaled copy of a PostScript Calculator function. */
788
static int
789
fn_PtCr_make_scaled(const gs_function_PtCr_t *pfn, gs_function_PtCr_t **ppsfn,
790
                    const gs_range_t *pranges, gs_memory_t *mem)
791
0
{
792
0
    gs_function_PtCr_t *psfn =
793
0
        gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
794
0
                        "fn_PtCr_make_scaled");
795
    /* We are adding {<int> 1 roll <float> mul <float> add} for each output. */
796
0
    int n = pfn->params.n;
797
0
    uint opsize = pfn->params.ops.size + (9 + 2 * sizeof(float)) * n;
798
0
    byte *ops = gs_alloc_string(mem, opsize, "fn_PtCr_make_scaled(ops)");
799
0
    byte *p;
800
0
    int code, i;
801
802
0
    if (psfn == 0 || ops == 0) {
803
0
        gs_free_string(mem, ops, opsize, "fn_PtCr_make_scaled(ops)");
804
0
        gs_free_object(mem, psfn, "fn_PtCr_make_scaled");
805
0
        return_error(gs_error_VMerror);
806
0
    }
807
0
    psfn->params = pfn->params;
808
0
    psfn->params.ops.data = ops;
809
0
    psfn->params.ops.size = opsize;
810
0
    psfn->data_source = pfn->data_source;
811
0
    code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn,
812
0
                           pranges, mem);
813
0
    if (code < 0) {
814
0
        gs_function_free((gs_function_t *)psfn, true, mem);
815
0
        return code;
816
0
    }
817
0
    memcpy(ops, pfn->params.ops.data, pfn->params.ops.size - 1); /* minus return */
818
0
    p = ops + pfn->params.ops.size - 1;
819
0
    for (i = n; --i >= 0; ) {
820
0
        float base = pranges[i].rmin;
821
0
        float factor = pranges[i].rmax - base;
822
823
0
        if (factor != 1) {
824
0
            p[0] = PtCr_float; memcpy(p + 1, &factor, sizeof(float));
825
0
            p += 1 + sizeof(float);
826
0
            *p++ = PtCr_mul;
827
0
        }
828
0
        if (base != 0) {
829
0
            p[0] = PtCr_float; memcpy(p + 1, &base, sizeof(float));
830
0
            p += 1 + sizeof(float);
831
0
            *p++ = PtCr_add;
832
0
        }
833
0
        if (n != 1) {
834
0
            p[0] = PtCr_byte; p[1] = (byte)n;
835
0
            p[2] = PtCr_byte; p[3] = 1;
836
0
            p[4] = PtCr_roll;
837
0
            p += 5;
838
0
        }
839
0
    }
840
0
    *p++ = PtCr_return;
841
0
    psfn->params.ops.size = p - ops;
842
0
    psfn->params.ops.data =
843
0
        gs_resize_string(mem, ops, opsize, psfn->params.ops.size,
844
0
                         "fn_PtCr_make_scaled");
845
0
    *ppsfn = psfn;
846
0
    return 0;
847
0
}
848
849
/* Free the parameters of a PostScript Calculator function. */
850
void
851
gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
852
45.4k
{
853
45.4k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
854
45.4k
    params->ops.data = NULL;
855
45.4k
    params->ops.size = 0;
856
45.4k
    fn_common_free_params((gs_function_params_t *) params, mem);
857
45.4k
}
858
859
/* Serialize. */
860
static int
861
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
862
10.0k
{
863
10.0k
    uint n;
864
10.0k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
865
10.0k
    int code = fn_common_serialize(pfn, s);
866
867
10.0k
    if (code < 0)
868
0
        return code;
869
10.0k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
870
10.0k
    if (code < 0)
871
0
        return code;
872
10.0k
    return sputs(s, p->ops.data, p->ops.size, &n);
873
10.0k
}
874
875
/* Allocate and initialize a PostScript Calculator function. */
876
int
877
gs_function_PtCr_init(gs_function_t ** ppfn,
878
                  const gs_function_PtCr_params_t * params, gs_memory_t * mem)
879
51.5k
{
880
51.5k
    static const gs_function_head_t function_PtCr_head = {
881
51.5k
        function_type_PostScript_Calculator,
882
51.5k
        {
883
51.5k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
884
51.5k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
885
51.5k
            (fn_get_info_proc_t) fn_PtCr_get_info,
886
51.5k
            fn_common_get_params,
887
51.5k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
888
51.5k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
889
51.5k
            fn_common_free,
890
51.5k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
891
51.5k
        }
892
51.5k
    };
893
51.5k
    int code;
894
895
51.5k
    *ppfn = 0;      /* in case of error */
896
51.5k
    code = fn_check_mnDR((const gs_function_params_t *)params,
897
51.5k
                         params->m, params->n);
898
51.5k
    if (code < 0)
899
28
        return code;
900
51.5k
    if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
901
0
        return_error(gs_error_limitcheck);
902
    /*
903
     * Pre-validate the operation string to reduce evaluation overhead.
904
     */
905
51.5k
    {
906
51.5k
        const byte *p = params->ops.data;
907
908
1.61M
        for (; *p != PtCr_return; ++p)
909
1.56M
            switch ((gs_PtCr_opcode_t)*p) {
910
323k
            case PtCr_byte:
911
323k
                ++p; break;
912
26.5k
            case PtCr_int:
913
26.5k
                p += sizeof(int); break;
914
84.9k
            case PtCr_float:
915
84.9k
                p += sizeof(float); break;
916
0
            case PtCr_repeat:
917
37.9k
            case PtCr_if:
918
75.3k
            case PtCr_else:
919
75.3k
                p += 2;
920
75.3k
            case PtCr_repeat_end:
921
75.3k
            case PtCr_true:
922
75.3k
            case PtCr_false:
923
75.3k
                break;
924
1.05M
            default:
925
1.05M
                if (*p >= PtCr_NUM_OPS)
926
0
                    return_error(gs_error_rangecheck);
927
1.56M
            }
928
51.5k
        if (p != params->ops.data + params->ops.size - 1)
929
0
            return_error(gs_error_rangecheck);
930
51.5k
    }
931
51.5k
    {
932
51.5k
        gs_function_PtCr_t *pfn =
933
51.5k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
934
51.5k
                            "gs_function_PtCr_init");
935
936
51.5k
        if (pfn == 0)
937
0
            return_error(gs_error_VMerror);
938
51.5k
        pfn->params = *params;
939
        /*
940
         * We claim to have a DataSource, in order to write the function
941
         * definition in symbolic form for embedding in PDF files.
942
         * ****** THIS IS A HACK. ******
943
         */
944
51.5k
        data_source_init_string2(&pfn->data_source, NULL, 0);
945
51.5k
        pfn->data_source.access = calc_access;
946
51.5k
        pfn->head = function_PtCr_head;
947
51.5k
        *ppfn = (gs_function_t *) pfn;
948
51.5k
    }
949
0
    return 0;
950
51.5k
}