Coverage Report

Created: 2026-02-14 07:09

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