Coverage Report

Created: 2026-09-14 07:34

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
82.8M
#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
36.0M
{
67
36.0M
    vsp->value.f = f;
68
36.0M
    vsp->type = CVT_FLOAT;
69
36.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
5.95M
{
109
5.95M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
5.95M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
5.95M
    calc_value_t *vstack = &vstack_buf[1];
112
5.95M
    calc_value_t *vsp = vstack + pfn->params.m;
113
5.95M
    const byte *p = pfn->params.ops.data;
114
5.95M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
5.95M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
5.95M
    int repeat_nesting_level = -1;
117
5.95M
    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
5.95M
    static const struct op_defn_s {
125
5.95M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
5.95M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
434M
#define O4(op) op,op,op,op
130
958M
#define E PtCr_typecheck
131
244M
#define E4 O4(E)
132
5.95M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
5.95M
#define OP_NONE(op)\
135
47.6M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
5.95M
#define OP1(b, i, f)\
138
119M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
5.95M
#define OP_NUM1(i, f)\
140
47.6M
  OP1(E, i, f)
141
5.95M
#define OP_MATH1(f)\
142
29.7M
  OP1(E, PtCr_int_to_float, f)
143
5.95M
#define OP_ANY1(op)\
144
11.9M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
5.95M
#define OP_NUM2(i, f)\
147
41.6M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
5.95M
#define OP_INT_BOOL2(i)\
149
17.8M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
5.95M
#define OP_MATH2(f)\
151
17.8M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
17.8M
    E,E,PtCr_int_to_float,f}}
153
5.95M
#define OP_INT2(i)\
154
23.8M
  {{E4, E4, E,E,i,E, E4}}
155
5.95M
#define OP_REL2(i, f)\
156
11.9M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
5.95M
#define OP_ANY2(op)\
158
5.95M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
5.95M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
5.95M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
5.95M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
5.95M
        OP_MATH2(PtCr_atan),  /* atan */
166
5.95M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
5.95M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
5.95M
        OP_MATH1(PtCr_cos), /* cos */
169
5.95M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
5.95M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
5.95M
        OP_MATH2(PtCr_div), /* div */
172
5.95M
        OP_MATH2(PtCr_exp), /* exp */
173
5.95M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
5.95M
        OP_INT2(PtCr_idiv),  /* idiv */
175
5.95M
        OP_MATH1(PtCr_ln),  /* ln */
176
5.95M
        OP_MATH1(PtCr_log), /* log */
177
5.95M
        OP_INT2(PtCr_mod), /* mod */
178
5.95M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
5.95M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
5.95M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
5.95M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
5.95M
        OP_NUM1(N, PtCr_round),  /* round */
183
5.95M
        OP_MATH1(PtCr_sin), /* sin */
184
5.95M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
5.95M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
5.95M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
5.95M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
5.95M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
5.95M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
5.95M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
5.95M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
5.95M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
5.95M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
5.95M
        OP1(E, PtCr_copy, E),  /* copy */
201
5.95M
        OP_ANY1(PtCr_dup), /* dup */
202
5.95M
        OP_ANY2(PtCr_exch),  /* exch */
203
5.95M
        OP1(E, PtCr_index, E), /* index */
204
5.95M
        OP_ANY1(PtCr_pop), /* pop */
205
5.95M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
5.95M
        OP_NONE(PtCr_byte),    /* byte */
210
5.95M
        OP_NONE(PtCr_int),   /* int */
211
5.95M
        OP_NONE(PtCr_float),   /* float */
212
5.95M
        OP_NONE(PtCr_true),    /* true */
213
5.95M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
5.95M
        OP1(PtCr_if, E, E),    /* if */
218
5.95M
        OP_NONE(PtCr_else),    /* else */
219
5.95M
        OP_NONE(PtCr_return),    /* return */
220
5.95M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
5.95M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
5.95M
    };
223
224
5.95M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
5.95M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
5.95M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
5.95M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
25.6M
    for (i = 0; i < pfn->params.m; ++i)
230
19.6M
        store_float(&vstack[i + 1], in[i]);
231
232
158M
    for (; ; ) {
233
158M
        int code, n;
234
235
158M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
124k
        case PtCr_no_op:
240
124k
            continue;
241
35
        case PtCr_typecheck:
242
35
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
12.8M
        case PtCr_int_to_float:
247
12.8M
            store_float(vsp, (double)vsp->value.i);
248
12.8M
            --p; continue;
249
127k
        case PtCr_int2_to_float:
250
127k
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
3.36M
        case PtCr_2nd_int_to_float:
253
3.36M
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
3.36M
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
3.55M
        case PtCr_abs:
259
3.55M
            vsp->value.f = fabs(vsp->value.f);
260
3.55M
            continue;
261
0
        case PtCr_add_int: {
262
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
263
264
0
            if ((int1 ^ int2) >= 0 && ((int1 + int2) ^ int1) < 0)
265
0
                store_float(vsp - 1, (double)int1 + int2);
266
0
            else
267
0
                vsp[-1].value.i = int1 + int2;
268
0
            --vsp; continue;
269
127k
        }
270
4.13M
        case PtCr_add:
271
4.13M
            vsp[-1].value.f += vsp->value.f;
272
4.13M
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
2.45M
        case PtCr_atan: {
277
2.45M
            double result;
278
279
2.45M
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
2.45M
                                    &result);
281
2.45M
            if (code < 0)
282
0
                return code;
283
2.45M
            vsp[-1].value.f = result;
284
2.45M
            --vsp; continue;
285
2.45M
        }
286
0
        case PtCr_bitshift:
287
0
#define MAX_SHIFT (ARCH_SIZEOF_INT * 8 - 1)
288
0
            if (vsp->value.i < -MAX_SHIFT || vsp->value.i > MAX_SHIFT)
289
0
                vsp[-1].value.i = 0;
290
0
#undef MAX_SHIFT
291
0
            else if ((n = vsp->value.i) < 0)
292
0
                vsp[-1].value.i = ((uint)(vsp[-1].value.i)) >> -n;
293
0
            else
294
0
                vsp[-1].value.i <<= n;
295
0
            --vsp; continue;
296
0
        case PtCr_ceiling:
297
0
            vsp->value.f = ceil(vsp->value.f);
298
0
            continue;
299
2.45M
        case PtCr_cos:
300
2.45M
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
2.45M
            continue;
302
0
        case PtCr_cvi:
303
0
        {
304
           /* Strictly speaking assigning one element of union
305
            * to another, overlapping element of a different size is
306
            * undefined behavior, hence assign to an intermediate variable
307
            */
308
0
            int int1 = (int)(vsp->value.f);
309
0
            vsp->value.i = int1;
310
0
            vsp->type = CVT_INT;
311
0
            continue;
312
2.45M
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
3.03M
        case PtCr_div:
316
3.03M
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
3.03M
            vsp[-1].value.f /= vsp->value.f;
319
3.03M
            --vsp; continue;
320
0
        case PtCr_exp:
321
0
            vsp[-1].value.f = pow(vsp[-1].value.f, vsp->value.f);
322
0
            --vsp; continue;
323
0
        case PtCr_floor:
324
0
            vsp->value.f = floor(vsp->value.f);
325
0
            continue;
326
0
        case PtCr_idiv:
327
0
            if (vsp->value.i == 0)
328
0
                return_error(gs_error_undefinedresult);
329
0
            if (vsp[-1].value.i == min_int &&
330
0
                vsp->value.i == -1)  /* anomalous boundary case, fail */
331
0
                return_error(gs_error_rangecheck);
332
0
            else
333
0
                vsp[-1].value.i /= vsp->value.i;
334
0
            --vsp; continue;
335
0
        case PtCr_ln:
336
0
            vsp->value.f = log(vsp->value.f);
337
0
            continue;
338
0
        case PtCr_log:
339
0
            vsp->value.f = log10(vsp->value.f);
340
0
            continue;
341
0
        case PtCr_mod:
342
0
            if (vsp->value.i == 0)
343
0
                return_error(gs_error_undefinedresult);
344
0
            if (vsp[-1].value.i == min_int &&
345
0
                vsp->value.i == -1)  /* anomalous boundary case, fail */
346
0
                return_error(gs_error_rangecheck);
347
0
            vsp[-1].value.i %= vsp->value.i;
348
0
            --vsp; continue;
349
2.66M
        case PtCr_mul_int: {
350
            /* We don't bother to optimize this. */
351
2.66M
            double prod = (double)vsp[-1].value.i * vsp->value.i;
352
353
2.66M
            if (prod < min_int || prod > max_int)
354
0
                store_float(vsp - 1, prod);
355
2.66M
            else
356
2.66M
                vsp[-1].value.i = (int)prod;
357
2.66M
            --vsp; continue;
358
0
        }
359
9.46M
        case PtCr_mul:
360
9.46M
            vsp[-1].value.f *= vsp->value.f;
361
9.46M
            --vsp; continue;
362
127k
        case PtCr_abs_int:
363
127k
            if (vsp->value.i >= 0)
364
127k
                continue;
365
            /* fallthrough */
366
0
        case PtCr_neg_int:
367
0
            if (vsp->value.i == min_int)
368
0
                store_float(vsp, (double)vsp->value.i); /* =self negated */
369
0
            else
370
0
                vsp->value.i = -vsp->value.i;
371
0
            continue;
372
0
        case PtCr_neg:
373
0
            vsp->value.f = -vsp->value.f;
374
0
            continue;
375
0
        case PtCr_not_bool:
376
0
            vsp->value.i = !vsp->value.i;
377
0
            continue;
378
0
        case PtCr_not:
379
0
            vsp->value.i = ~vsp->value.i;
380
0
            continue;
381
0
        case PtCr_or:
382
0
            vsp[-1].value.i |= vsp->value.i;
383
0
            --vsp; continue;
384
0
        case PtCr_round:
385
0
            vsp->value.f = floor(vsp->value.f + 0.5);
386
0
            continue;
387
3.03M
        case PtCr_sin:
388
3.03M
            vsp->value.f = gs_sin_degrees(vsp->value.f);
389
3.03M
            continue;
390
3.03M
        case PtCr_sqrt:
391
3.03M
            if (vsp->value.f < 0.0)
392
0
                return_error(gs_error_rangecheck);
393
3.03M
            vsp->value.f = sqrt(vsp->value.f);
394
3.03M
            continue;
395
0
        case PtCr_sub_int: {
396
0
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
397
398
0
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
399
0
                store_float(vsp - 1, (double)int1 - int2);
400
0
            else
401
0
                vsp[-1].value.i = int1 - int2;
402
0
            --vsp; continue;
403
3.03M
        }
404
10.3M
        case PtCr_sub:
405
10.3M
            vsp[-1].value.f -= vsp->value.f;
406
10.3M
            --vsp; continue;
407
5
        case PtCr_truncate:
408
5
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
409
5
                            floor(vsp->value.f));
410
5
            continue;
411
0
        case PtCr_xor:
412
0
            vsp[-1].value.i ^= vsp->value.i;
413
0
            --vsp; continue;
414
415
            /* Boolean operators */
416
417
0
#define DO_REL(rel, m)\
418
3.29M
  vsp[-1].value.i = vsp[-1].value.m rel vsp->value.m
419
420
0
        case PtCr_eq_int:
421
0
            DO_REL(==, i);
422
0
            goto rel;
423
17
        case PtCr_ge_int:
424
17
            DO_REL(>=, i);
425
17
            goto rel;
426
45
        case PtCr_ge:
427
45
            DO_REL(>=, f);
428
45
            goto rel;
429
288
        case PtCr_gt_int:
430
288
            DO_REL(>, i);
431
288
            goto rel;
432
96
        case PtCr_gt:
433
96
            DO_REL(>, f);
434
96
            goto rel;
435
0
        case PtCr_le_int:
436
0
            DO_REL(<=, i);
437
0
            goto rel;
438
263k
        case PtCr_le:
439
263k
            DO_REL(<=, f);
440
263k
            goto rel;
441
0
        case PtCr_lt_int:
442
0
            DO_REL(<, i);
443
0
            goto rel;
444
3.03M
        case PtCr_lt:
445
3.03M
            DO_REL(<, f);
446
3.03M
            goto rel;
447
0
        case PtCr_ne_int:
448
0
            DO_REL(!=, i);
449
0
            goto rel;
450
0
        case PtCr_ne:
451
0
            DO_REL(!=, f);
452
0
            goto rel;
453
0
        case PtCr_eq:
454
0
            DO_REL(==, f);
455
3.29M
        rel:
456
3.29M
            vsp[-1].type = CVT_BOOL;
457
3.29M
            --vsp; continue;
458
459
0
#undef DO_REL
460
461
            /* Stack operators */
462
463
263k
        case PtCr_copy:
464
263k
            i = vsp->value.i;
465
263k
            n = vsp - vstack;
466
263k
            if (i < 0 || i >= n)
467
0
                return_error(gs_error_rangecheck);
468
263k
            if (i > MAX_VSTACK - (n - 1))
469
0
                return_error(gs_error_limitcheck);
470
263k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
471
263k
            vsp += i - 1;
472
263k
            continue;
473
13.6M
        case PtCr_dup:
474
13.6M
            vsp[1] = *vsp;
475
13.6M
            goto push;
476
15.3M
        case PtCr_exch:
477
15.3M
            vstack[MAX_VSTACK] = *vsp;
478
15.3M
            *vsp = vsp[-1];
479
15.3M
            vsp[-1] = vstack[MAX_VSTACK];
480
15.3M
            continue;
481
4.79M
        case PtCr_index:
482
4.79M
            i = vsp->value.i;
483
4.79M
            if (i < 0 || i >= vsp - vstack - 1)
484
1
                return_error(gs_error_rangecheck);
485
4.79M
            *vsp = vsp[-i - 1];
486
4.79M
            continue;
487
9.59M
        case PtCr_pop:
488
9.59M
            --vsp;
489
9.59M
            continue;
490
3.01M
        case PtCr_roll:
491
3.01M
            n = vsp[-1].value.i;
492
3.01M
            i = vsp->value.i;
493
3.01M
            if (n < 0 || n > vsp - vstack - 2)
494
0
                return_error(gs_error_rangecheck);
495
            /* We don't bother to do this efficiently. */
496
11.5M
            for (; i > 0; i--) {
497
8.53M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
498
8.53M
                vsp[-(n + 1)] = vsp[-1];
499
8.53M
            }
500
3.09M
            for (; i < 0; i++) {
501
79.6k
                vsp[-1] = vsp[-(n + 1)];
502
79.6k
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
503
79.6k
            }
504
3.01M
            vsp -= 2;
505
3.01M
            continue;
506
507
            /* Constants */
508
509
24.6M
        case PtCr_byte:
510
24.6M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
511
24.6M
            goto push;
512
5.56M
        case PtCr_int /* native */:
513
5.56M
            memcpy(&vsp[1].value.i, p, sizeof(int));
514
5.56M
            vsp[1].type = CVT_INT;
515
5.56M
            p += sizeof(int);
516
5.56M
            goto push;
517
7.94M
        case PtCr_float /* native */:
518
7.94M
            memcpy(&vsp[1].value.f, p, sizeof(float));
519
7.94M
            vsp[1].type = CVT_FLOAT;
520
7.94M
            p += sizeof(float);
521
7.94M
            goto push;
522
0
        case PtCr_true:
523
0
            vsp[1].value.i = true, vsp[1].type = CVT_BOOL;
524
0
            goto push;
525
0
        case PtCr_false:
526
0
            vsp[1].value.i = false, vsp[1].type = CVT_BOOL;
527
51.7M
        push:
528
51.7M
            if (vsp == &vstack[MAX_VSTACK])
529
0
                return_error(gs_error_limitcheck);
530
51.7M
            ++vsp;
531
51.7M
            continue;
532
533
            /* Special */
534
535
3.29M
        case PtCr_if:
536
3.29M
            if ((vsp--)->value.i) { /* value is true, execute body */
537
2.79M
                p += 2;
538
2.79M
                continue;
539
2.79M
            }
540
            /* falls through */
541
631k
        case PtCr_else:
542
631k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
543
631k
            continue;
544
5.95M
        case PtCr_return:
545
5.95M
            goto fin;
546
0
        case PtCr_repeat:
547
0
            repeat_nesting_level++;
548
0
            repeat_count[repeat_nesting_level] = vsp->value.i;
549
0
            repeat_proc_size[repeat_nesting_level] = 1 + (p[0] << 8) + p[1];  /* body size */
550
0
            --vsp;    /* pop the counter */
551
0
            p += 3 + (p[0] <<8) + p[1];       /* advance just past the repeat_end */
552
            /* falls through */
553
0
        case PtCr_repeat_end:
554
0
            if (repeat_nesting_level < 0)
555
0
                return_error(gs_error_rangecheck);
556
557
0
            if ((repeat_count[repeat_nesting_level])-- <= 0)
558
0
                repeat_nesting_level--;
559
0
            else
560
0
                p -= repeat_proc_size[repeat_nesting_level];
561
0
            continue;
562
158M
        }
563
158M
    }
564
5.95M
 fin:
565
5.95M
    {   /* Following Acrobat, take the desired number of parameters */
566
        /* from the top of stack and ignore the rest. Bug 702950. */
567
5.95M
        int extra_ops = vsp - vstack - pfn->params.n;
568
5.95M
        if (extra_ops < 0)
569
49
            return_error(gs_error_rangecheck);
570
23.1M
        for (i = 0; i < pfn->params.n; ++i) {
571
17.2M
            switch (vstack[i + 1 + extra_ops].type) {
572
13.4k
            case CVT_INT:
573
13.4k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
574
13.4k
                break;
575
17.1M
            case CVT_FLOAT:
576
17.1M
                out[i] = vstack[i + 1 + extra_ops].value.f;
577
17.1M
                break;
578
0
            default:
579
0
                return_error(gs_error_typecheck);
580
17.2M
            }
581
17.2M
        }
582
5.95M
    }
583
5.95M
    return 0;
584
5.95M
}
585
586
/* Test whether a PostScript Calculator function is monotonic. */
587
static int
588
fn_PtCr_is_monotonic(const gs_function_t * pfn_common,
589
                     const float *lower, const float *upper, uint *mask)
590
0
{
591
    /*
592
     * No reasonable way to tell.  Eventually we should check for
593
     * functions consisting of only stack-manipulating operations,
594
     * since these may be common for DeviceN color spaces and *are*
595
     * monotonic.
596
     */
597
0
    *mask = 0x49249249;
598
0
    return 0;
599
0
}
600
601
/* Write the function definition in symbolic form on a stream. */
602
static int
603
calc_put_ops(stream *s, const byte *ops, uint size)
604
1.52k
{
605
1.52k
    const byte *p;
606
607
1.52k
    spputc(s, '{');
608
11.0k
    for (p = ops; p < ops + size; )
609
9.51k
        switch (*p++) {
610
2.61k
        case PtCr_byte:
611
2.61k
            pprintd1(s, "%d ", *p++);
612
2.61k
            break;
613
509
        case PtCr_int: {
614
509
            int i;
615
616
509
            memcpy(&i, p, sizeof(int));
617
509
            pprintd1(s, "%d ", i);
618
509
            p += sizeof(int);
619
509
            break;
620
0
        }
621
2.83k
        case PtCr_float: {
622
2.83k
            float f;
623
624
2.83k
            memcpy(&f, p, sizeof(float));
625
2.83k
            pprintg1(s, "%g ", f);
626
2.83k
            p += sizeof(float);
627
2.83k
            break;
628
0
        }
629
0
        case PtCr_true:
630
0
            stream_puts(s, "true ");
631
0
            break;
632
0
        case PtCr_false:
633
0
            stream_puts(s, "false ");
634
0
            break;
635
166
        case PtCr_if: {
636
166
            int skip = (p[0] << 8) + p[1];
637
166
            int code;
638
639
166
            code = calc_put_ops(s, p += 2, skip);
640
166
            p += skip;
641
166
            if (code < 0)
642
0
                return code;
643
166
            if (code > 0) { /* else */
644
0
                skip = (p[-2] << 8) + p[-1];
645
0
                code = calc_put_ops(s, p, skip);
646
0
                p += skip;
647
0
                if (code < 0)
648
0
                    return code;
649
0
                stream_puts(s, " ifelse ");
650
0
            } else
651
166
                stream_puts(s, " if ");
652
166
            break;
653
166
        }
654
166
        case PtCr_else:
655
0
            if (p != ops + size - 2)
656
0
                return_error(gs_error_rangecheck);
657
0
            spputc(s, '}');
658
0
            return 1;
659
        /*case PtCr_return:*/ /* not possible */
660
0
        case PtCr_repeat:   /* We shouldn't encounter this, but just in case */
661
0
        case PtCr_repeat_end:
662
0
            return_error(gs_error_rangecheck);
663
3.39k
        default: {    /* must be < PtCr_NUM_OPS */
664
3.39k
                static const char *const op_names[] = {
665
                    /* Keep this consistent with opcodes in gsfunc4.h! */
666
3.39k
                    "abs", "add", "and", "atan", "bitshift",
667
3.39k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
668
3.39k
                    "floor", "idiv", "ln", "log", "mod", "mul",
669
3.39k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
670
3.39k
                    "truncate", "xor",
671
3.39k
                    "eq", "ge", "gt", "le", "lt", "ne",
672
3.39k
                    "copy", "dup", "exch", "index", "pop", "roll"
673
3.39k
                };
674
675
3.39k
                pprints1(s, "%s ", op_names[p[-1]]);
676
3.39k
            }
677
9.51k
        }
678
1.52k
    spputc(s, '}');
679
1.52k
    return 0;
680
1.52k
}
681
static int
682
calc_put(stream *s, const gs_function_PtCr_t *pfn)
683
1.35k
{
684
1.35k
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
685
1.35k
    return 0;
686
1.35k
}
687
688
/* Access the symbolic definition as a DataSource. */
689
static int
690
calc_access(const gs_data_source_t *psrc, ulong start, uint length,
691
            byte *buf, const byte **ptr)
692
694
{
693
694
    const gs_function_PtCr_t *const pfn =
694
694
        (const gs_function_PtCr_t *)
695
694
          ((const char *)psrc - offset_of(gs_function_PtCr_t, data_source));
696
    /*
697
     * The caller wants a specific substring of the symbolic definition.
698
     * Generate the entire definition, using a SubFileDecode filter (in an
699
     * output pipeline!) to extract the substring.  This is very
700
     * inefficient, but this code is rarely used, and almost never actually
701
     * has to break up the definition into pieces to fit in the caller's
702
     * buffer.
703
     */
704
694
    stream_SFD_state st;
705
694
    stream ds, bs;
706
694
    byte dbuf[200];   /* arbitrary */
707
694
    const stream_template *const templat = &s_SFD_template;
708
709
    /* Set up the stream that writes into the buffer. */
710
694
    s_init(&bs, NULL);
711
694
    swrite_string(&bs, buf, length);
712
    /* Set up the SubFileDecode stream. */
713
694
    s_init(&ds, NULL);
714
694
    s_init_state((stream_state *)&st, templat, NULL);
715
694
    templat->set_defaults((stream_state *)&st);
716
694
    st.skip_count = start;
717
694
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
718
694
    calc_put(&ds, pfn);
719
694
    sclose(&ds);
720
694
    if (ptr)
721
694
        *ptr = buf;
722
694
    return 0;
723
694
}
724
725
/* Return PostScript Calculator function information. */
726
static void
727
fn_PtCr_get_info(const gs_function_t *pfn_common, gs_function_info_t *pfi)
728
665
{
729
665
    const gs_function_PtCr_t *const pfn =
730
665
        (const gs_function_PtCr_t *)pfn_common;
731
732
665
    gs_function_get_info_default(pfn_common, pfi);
733
665
    pfi->DataSource = &pfn->data_source;
734
665
    {
735
665
        stream s;
736
737
665
        s_init(&s, NULL);
738
665
        swrite_position_only(&s);
739
665
        calc_put(&s, pfn);
740
665
        pfi->data_size = stell(&s);
741
665
    }
742
665
}
743
744
/* Make a scaled copy of a PostScript Calculator function. */
745
static int
746
fn_PtCr_make_scaled(const gs_function_PtCr_t *pfn, gs_function_PtCr_t **ppsfn,
747
                    const gs_range_t *pranges, gs_memory_t *mem)
748
0
{
749
0
    gs_function_PtCr_t *psfn =
750
0
        gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
751
0
                        "fn_PtCr_make_scaled");
752
    /* We are adding {<int> 1 roll <float> mul <float> add} for each output. */
753
0
    int n = pfn->params.n;
754
0
    uint opsize = pfn->params.ops.size + (9 + 2 * sizeof(float)) * n;
755
0
    byte *ops = gs_alloc_string(mem, opsize, "fn_PtCr_make_scaled(ops)");
756
0
    byte *p;
757
0
    int code, i;
758
759
0
    if (psfn == 0 || ops == 0) {
760
0
        gs_free_string(mem, ops, opsize, "fn_PtCr_make_scaled(ops)");
761
0
        gs_free_object(mem, psfn, "fn_PtCr_make_scaled");
762
0
        return_error(gs_error_VMerror);
763
0
    }
764
0
    psfn->params = pfn->params;
765
0
    psfn->params.ops.data = ops;
766
0
    psfn->params.ops.size = opsize;
767
0
    psfn->data_source = pfn->data_source;
768
0
    code = fn_common_scale((gs_function_t *)psfn, (const gs_function_t *)pfn,
769
0
                           pranges, mem);
770
0
    if (code < 0) {
771
0
        gs_function_free((gs_function_t *)psfn, true, mem);
772
0
        return code;
773
0
    }
774
0
    memcpy(ops, pfn->params.ops.data, pfn->params.ops.size - 1); /* minus return */
775
0
    p = ops + pfn->params.ops.size - 1;
776
0
    for (i = n; --i >= 0; ) {
777
0
        float base = pranges[i].rmin;
778
0
        float factor = pranges[i].rmax - base;
779
780
0
        if (factor != 1) {
781
0
            p[0] = PtCr_float; memcpy(p + 1, &factor, sizeof(float));
782
0
            p += 1 + sizeof(float);
783
0
            *p++ = PtCr_mul;
784
0
        }
785
0
        if (base != 0) {
786
0
            p[0] = PtCr_float; memcpy(p + 1, &base, sizeof(float));
787
0
            p += 1 + sizeof(float);
788
0
            *p++ = PtCr_add;
789
0
        }
790
0
        if (n != 1) {
791
0
            p[0] = PtCr_byte; p[1] = (byte)n;
792
0
            p[2] = PtCr_byte; p[3] = 1;
793
0
            p[4] = PtCr_roll;
794
0
            p += 5;
795
0
        }
796
0
    }
797
0
    *p++ = PtCr_return;
798
0
    psfn->params.ops.size = p - ops;
799
0
    psfn->params.ops.data =
800
0
        gs_resize_string(mem, ops, opsize, psfn->params.ops.size,
801
0
                         "fn_PtCr_make_scaled");
802
0
    *ppsfn = psfn;
803
0
    return 0;
804
0
}
805
806
/* Free the parameters of a PostScript Calculator function. */
807
void
808
gs_function_PtCr_free_params(gs_function_PtCr_params_t * params, gs_memory_t * mem)
809
40.6k
{
810
40.6k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
811
40.6k
    params->ops.data = NULL;
812
40.6k
    params->ops.size = 0;
813
40.6k
    fn_common_free_params((gs_function_params_t *) params, mem);
814
40.6k
}
815
816
/* Serialize. */
817
static int
818
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
819
9.52k
{
820
9.52k
    uint n;
821
9.52k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
822
9.52k
    int code = fn_common_serialize(pfn, s);
823
824
9.52k
    if (code < 0)
825
0
        return code;
826
9.52k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
827
9.52k
    if (code < 0)
828
0
        return code;
829
9.52k
    return sputs(s, p->ops.data, p->ops.size, &n);
830
9.52k
}
831
832
/* Allocate and initialize a PostScript Calculator function. */
833
int
834
gs_function_PtCr_init(gs_function_t ** ppfn,
835
                  const gs_function_PtCr_params_t * params, gs_memory_t * mem)
836
45.9k
{
837
45.9k
    static const gs_function_head_t function_PtCr_head = {
838
45.9k
        function_type_PostScript_Calculator,
839
45.9k
        {
840
45.9k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
841
45.9k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
842
45.9k
            (fn_get_info_proc_t) fn_PtCr_get_info,
843
45.9k
            fn_common_get_params,
844
45.9k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
845
45.9k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
846
45.9k
            fn_common_free,
847
45.9k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
848
45.9k
        }
849
45.9k
    };
850
45.9k
    int code;
851
852
45.9k
    *ppfn = 0;      /* in case of error */
853
45.9k
    code = fn_check_mnDR((const gs_function_params_t *)params,
854
45.9k
                         params->m, params->n);
855
45.9k
    if (code < 0)
856
24
        return code;
857
45.9k
    if (params->m > MAX_VSTACK || params->n > MAX_VSTACK)
858
0
        return_error(gs_error_limitcheck);
859
    /*
860
     * Pre-validate the operation string to reduce evaluation overhead.
861
     */
862
45.9k
    {
863
45.9k
        const byte *p = params->ops.data;
864
865
1.45M
        for (; *p != PtCr_return; ++p)
866
1.41M
            switch ((gs_PtCr_opcode_t)*p) {
867
297k
            case PtCr_byte:
868
297k
                ++p; break;
869
25.7k
            case PtCr_int:
870
25.7k
                p += sizeof(int); break;
871
77.4k
            case PtCr_float:
872
77.4k
                p += sizeof(float); break;
873
0
            case PtCr_repeat:
874
33.4k
            case PtCr_if:
875
66.2k
            case PtCr_else:
876
66.2k
                p += 2;
877
66.2k
            case PtCr_repeat_end:
878
66.2k
            case PtCr_true:
879
66.2k
            case PtCr_false:
880
66.2k
                break;
881
944k
            default:
882
944k
                if (*p >= PtCr_NUM_OPS)
883
0
                    return_error(gs_error_rangecheck);
884
1.41M
            }
885
45.9k
        if (p != params->ops.data + params->ops.size - 1)
886
0
            return_error(gs_error_rangecheck);
887
45.9k
    }
888
45.9k
    {
889
45.9k
        gs_function_PtCr_t *pfn =
890
45.9k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
891
45.9k
                            "gs_function_PtCr_init");
892
893
45.9k
        if (pfn == 0)
894
0
            return_error(gs_error_VMerror);
895
45.9k
        pfn->params = *params;
896
        /*
897
         * We claim to have a DataSource, in order to write the function
898
         * definition in symbolic form for embedding in PDF files.
899
         * ****** THIS IS A HACK. ******
900
         */
901
45.9k
        data_source_init_string2(&pfn->data_source, NULL, 0);
902
45.9k
        pfn->data_source.access = calc_access;
903
45.9k
        pfn->head = function_PtCr_head;
904
45.9k
        *ppfn = (gs_function_t *) pfn;
905
45.9k
    }
906
0
    return 0;
907
45.9k
}