Coverage Report

Created: 2026-08-08 08:00

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
70.1M
#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
35.2M
{
67
35.2M
    vsp->value.f = f;
68
35.2M
    vsp->type = CVT_FLOAT;
69
35.2M
}
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.78M
{
109
5.78M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
5.78M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
5.78M
    calc_value_t *vstack = &vstack_buf[1];
112
5.78M
    calc_value_t *vsp = vstack + pfn->params.m;
113
5.78M
    const byte *p = pfn->params.ops.data;
114
5.78M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
5.78M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
5.78M
    int repeat_nesting_level = -1;
117
5.78M
    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.78M
    static const struct op_defn_s {
125
5.78M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
5.78M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
422M
#define O4(op) op,op,op,op
130
930M
#define E PtCr_typecheck
131
237M
#define E4 O4(E)
132
5.78M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
5.78M
#define OP_NONE(op)\
135
46.2M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
5.78M
#define OP1(b, i, f)\
138
115M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
5.78M
#define OP_NUM1(i, f)\
140
46.2M
  OP1(E, i, f)
141
5.78M
#define OP_MATH1(f)\
142
28.9M
  OP1(E, PtCr_int_to_float, f)
143
5.78M
#define OP_ANY1(op)\
144
11.5M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
5.78M
#define OP_NUM2(i, f)\
147
40.4M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
5.78M
#define OP_INT_BOOL2(i)\
149
17.3M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
5.78M
#define OP_MATH2(f)\
151
17.3M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
17.3M
    E,E,PtCr_int_to_float,f}}
153
5.78M
#define OP_INT2(i)\
154
23.1M
  {{E4, E4, E,E,i,E, E4}}
155
5.78M
#define OP_REL2(i, f)\
156
11.5M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
5.78M
#define OP_ANY2(op)\
158
5.78M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
5.78M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
5.78M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
5.78M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
5.78M
        OP_MATH2(PtCr_atan),  /* atan */
166
5.78M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
5.78M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
5.78M
        OP_MATH1(PtCr_cos), /* cos */
169
5.78M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
5.78M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
5.78M
        OP_MATH2(PtCr_div), /* div */
172
5.78M
        OP_MATH2(PtCr_exp), /* exp */
173
5.78M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
5.78M
        OP_INT2(PtCr_idiv),  /* idiv */
175
5.78M
        OP_MATH1(PtCr_ln),  /* ln */
176
5.78M
        OP_MATH1(PtCr_log), /* log */
177
5.78M
        OP_INT2(PtCr_mod), /* mod */
178
5.78M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
5.78M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
5.78M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
5.78M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
5.78M
        OP_NUM1(N, PtCr_round),  /* round */
183
5.78M
        OP_MATH1(PtCr_sin), /* sin */
184
5.78M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
5.78M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
5.78M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
5.78M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
5.78M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
5.78M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
5.78M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
5.78M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
5.78M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
5.78M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
5.78M
        OP1(E, PtCr_copy, E),  /* copy */
201
5.78M
        OP_ANY1(PtCr_dup), /* dup */
202
5.78M
        OP_ANY2(PtCr_exch),  /* exch */
203
5.78M
        OP1(E, PtCr_index, E), /* index */
204
5.78M
        OP_ANY1(PtCr_pop), /* pop */
205
5.78M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
5.78M
        OP_NONE(PtCr_byte),    /* byte */
210
5.78M
        OP_NONE(PtCr_int),   /* int */
211
5.78M
        OP_NONE(PtCr_float),   /* float */
212
5.78M
        OP_NONE(PtCr_true),    /* true */
213
5.78M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
5.78M
        OP1(PtCr_if, E, E),    /* if */
218
5.78M
        OP_NONE(PtCr_else),    /* else */
219
5.78M
        OP_NONE(PtCr_return),    /* return */
220
5.78M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
5.78M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
5.78M
    };
223
224
5.78M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
5.78M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
5.78M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
5.78M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
24.7M
    for (i = 0; i < pfn->params.m; ++i)
230
18.9M
        store_float(&vstack[i + 1], in[i]);
231
232
133M
    for (; ; ) {
233
133M
        int code, n;
234
235
133M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
533k
        case PtCr_no_op:
240
533k
            continue;
241
34
        case PtCr_typecheck:
242
34
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
12.7M
        case PtCr_int_to_float:
247
12.7M
            store_float(vsp, (double)vsp->value.i);
248
12.7M
            --p; continue;
249
127k
        case PtCr_int2_to_float:
250
127k
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
3.42M
        case PtCr_2nd_int_to_float:
253
3.42M
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
3.42M
            --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
959k
        case PtCr_add:
271
959k
            vsp[-1].value.f += vsp->value.f;
272
959k
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
2.49M
        case PtCr_atan: {
277
2.49M
            double result;
278
279
2.49M
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
2.49M
                                    &result);
281
2.49M
            if (code < 0)
282
0
                return code;
283
2.49M
            vsp[-1].value.f = result;
284
2.49M
            --vsp; continue;
285
2.49M
        }
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.49M
        case PtCr_cos:
300
2.49M
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
2.49M
            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.49M
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
3.01M
        case PtCr_div:
316
3.01M
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
3.01M
            vsp[-1].value.f /= vsp->value.f;
319
3.01M
            --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
2.65M
        case PtCr_mul_int: {
347
            /* We don't bother to optimize this. */
348
2.65M
            double prod = (double)vsp[-1].value.i * vsp->value.i;
349
350
2.65M
            if (prod < min_int || prod > max_int)
351
0
                store_float(vsp - 1, prod);
352
2.65M
            else
353
2.65M
                vsp[-1].value.i = (int)prod;
354
2.65M
            --vsp; continue;
355
0
        }
356
3.96M
        case PtCr_mul:
357
3.96M
            vsp[-1].value.f *= vsp->value.f;
358
3.96M
            --vsp; continue;
359
127k
        case PtCr_abs_int:
360
127k
            if (vsp->value.i >= 0)
361
127k
                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.01M
        case PtCr_sin:
385
3.01M
            vsp->value.f = gs_sin_degrees(vsp->value.f);
386
3.01M
            continue;
387
3.01M
        case PtCr_sqrt:
388
3.01M
            vsp->value.f = sqrt(vsp->value.f);
389
3.01M
            continue;
390
91.5k
        case PtCr_sub_int: {
391
91.5k
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393
91.5k
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394
0
                store_float(vsp - 1, (double)int1 - int2);
395
91.5k
            else
396
91.5k
                vsp[-1].value.i = int1 - int2;
397
91.5k
            --vsp; continue;
398
127k
        }
399
10.2M
        case PtCr_sub:
400
10.2M
            vsp[-1].value.f -= vsp->value.f;
401
10.2M
            --vsp; continue;
402
5
        case PtCr_truncate:
403
5
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404
5
                            floor(vsp->value.f));
405
5
            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.28M
  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
16
        case PtCr_ge_int:
419
16
            DO_REL(>=, i);
420
16
            goto rel;
421
42
        case PtCr_ge:
422
42
            DO_REL(>=, f);
423
42
            goto rel;
424
291
        case PtCr_gt_int:
425
291
            DO_REL(>, i);
426
291
            goto rel;
427
97
        case PtCr_gt:
428
97
            DO_REL(>, f);
429
97
            goto rel;
430
0
        case PtCr_le_int:
431
0
            DO_REL(<=, i);
432
0
            goto rel;
433
269k
        case PtCr_le:
434
269k
            DO_REL(<=, f);
435
269k
            goto rel;
436
0
        case PtCr_lt_int:
437
0
            DO_REL(<, i);
438
0
            goto rel;
439
3.01M
        case PtCr_lt:
440
3.01M
            DO_REL(<, f);
441
3.01M
            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.28M
        rel:
451
3.28M
            vsp[-1].type = CVT_BOOL;
452
3.28M
            --vsp; continue;
453
454
0
#undef DO_REL
455
456
            /* Stack operators */
457
458
269k
        case PtCr_copy:
459
269k
            i = vsp->value.i;
460
269k
            n = vsp - vstack;
461
269k
            if (i < 0 || i >= n)
462
0
                return_error(gs_error_rangecheck);
463
269k
            if (i > MAX_VSTACK - (n - 1))
464
0
                return_error(gs_error_limitcheck);
465
269k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
466
269k
            vsp += i - 1;
467
269k
            continue;
468
12.1M
        case PtCr_dup:
469
12.1M
            vsp[1] = *vsp;
470
12.1M
            goto push;
471
13.1M
        case PtCr_exch:
472
13.1M
            vstack[MAX_VSTACK] = *vsp;
473
13.1M
            *vsp = vsp[-1];
474
13.1M
            vsp[-1] = vstack[MAX_VSTACK];
475
13.1M
            continue;
476
178k
        case PtCr_index:
477
178k
            i = vsp->value.i;
478
178k
            if (i < 0 || i >= vsp - vstack - 1)
479
0
                return_error(gs_error_rangecheck);
480
178k
            *vsp = vsp[-i - 1];
481
178k
            continue;
482
8.12M
        case PtCr_pop:
483
8.12M
            --vsp;
484
8.12M
            continue;
485
3.66M
        case PtCr_roll:
486
3.66M
            n = vsp[-1].value.i;
487
3.66M
            i = vsp->value.i;
488
3.66M
            if (n < 0 || n > vsp - vstack - 2)
489
0
                return_error(gs_error_rangecheck);
490
            /* We don't bother to do this efficiently. */
491
11.3M
            for (; i > 0; i--) {
492
7.71M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493
7.71M
                vsp[-(n + 1)] = vsp[-1];
494
7.71M
            }
495
4.19M
            for (; i < 0; i++) {
496
528k
                vsp[-1] = vsp[-(n + 1)];
497
528k
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498
528k
            }
499
3.66M
            vsp -= 2;
500
3.66M
            continue;
501
502
            /* Constants */
503
504
21.0M
        case PtCr_byte:
505
21.0M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506
21.0M
            goto push;
507
6.03M
        case PtCr_int /* native */:
508
6.03M
            memcpy(&vsp[1].value.i, p, sizeof(int));
509
6.03M
            vsp[1].type = CVT_INT;
510
6.03M
            p += sizeof(int);
511
6.03M
            goto push;
512
4.12M
        case PtCr_float /* native */:
513
4.12M
            memcpy(&vsp[1].value.f, p, sizeof(float));
514
4.12M
            vsp[1].type = CVT_FLOAT;
515
4.12M
            p += sizeof(float);
516
4.12M
            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
43.3M
        push:
523
43.3M
            if (vsp == &vstack[MAX_VSTACK])
524
0
                return_error(gs_error_limitcheck);
525
43.3M
            ++vsp;
526
43.3M
            continue;
527
528
            /* Special */
529
530
3.28M
        case PtCr_if:
531
3.28M
            if ((vsp--)->value.i) { /* value is true, execute body */
532
2.78M
                p += 2;
533
2.78M
                continue;
534
2.78M
            }
535
            /* falls through */
536
639k
        case PtCr_else:
537
639k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
538
639k
            continue;
539
5.78M
        case PtCr_return:
540
5.78M
            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
133M
        }
558
133M
    }
559
5.78M
 fin:
560
5.78M
    {   /* Following Acrobat, take the desired number of parameters */
561
        /* from the top of stack and ignore the rest. Bug 702950. */
562
5.78M
        int extra_ops = vsp - vstack - pfn->params.n;
563
5.78M
        if (extra_ops < 0)
564
54
            return_error(gs_error_rangecheck);
565
22.5M
        for (i = 0; i < pfn->params.n; ++i) {
566
16.7M
            switch (vstack[i + 1 + extra_ops].type) {
567
107k
            case CVT_INT:
568
107k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
569
107k
                break;
570
16.6M
            case CVT_FLOAT:
571
16.6M
                out[i] = vstack[i + 1 + extra_ops].value.f;
572
16.6M
                break;
573
0
            default:
574
0
                return_error(gs_error_typecheck);
575
16.7M
            }
576
16.7M
        }
577
5.78M
    }
578
5.78M
    return 0;
579
5.78M
}
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
1.61k
{
600
1.61k
    const byte *p;
601
602
1.61k
    spputc(s, '{');
603
18.1k
    for (p = ops; p < ops + size; )
604
16.5k
        switch (*p++) {
605
4.88k
        case PtCr_byte:
606
4.88k
            pprintd1(s, "%d ", *p++);
607
4.88k
            break;
608
915
        case PtCr_int: {
609
915
            int i;
610
611
915
            memcpy(&i, p, sizeof(int));
612
915
            pprintd1(s, "%d ", i);
613
915
            p += sizeof(int);
614
915
            break;
615
0
        }
616
3.61k
        case PtCr_float: {
617
3.61k
            float f;
618
619
3.61k
            memcpy(&f, p, sizeof(float));
620
3.61k
            pprintg1(s, "%g ", f);
621
3.61k
            p += sizeof(float);
622
3.61k
            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
152
        case PtCr_if: {
631
152
            int skip = (p[0] << 8) + p[1];
632
152
            int code;
633
634
152
            code = calc_put_ops(s, p += 2, skip);
635
152
            p += skip;
636
152
            if (code < 0)
637
0
                return code;
638
152
            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
152
                stream_puts(s, " if ");
647
152
            break;
648
152
        }
649
152
        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
7.01k
        default: {    /* must be < PtCr_NUM_OPS */
659
7.01k
                static const char *const op_names[] = {
660
                    /* Keep this consistent with opcodes in gsfunc4.h! */
661
7.01k
                    "abs", "add", "and", "atan", "bitshift",
662
7.01k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
663
7.01k
                    "floor", "idiv", "ln", "log", "mod", "mul",
664
7.01k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
665
7.01k
                    "truncate", "xor",
666
7.01k
                    "eq", "ge", "gt", "le", "lt", "ne",
667
7.01k
                    "copy", "dup", "exch", "index", "pop", "roll"
668
7.01k
                };
669
670
7.01k
                pprints1(s, "%s ", op_names[p[-1]]);
671
7.01k
            }
672
16.5k
        }
673
1.61k
    spputc(s, '}');
674
1.61k
    return 0;
675
1.61k
}
676
static int
677
calc_put(stream *s, const gs_function_PtCr_t *pfn)
678
1.46k
{
679
1.46k
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
680
1.46k
    return 0;
681
1.46k
}
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
770
{
688
770
    const gs_function_PtCr_t *const pfn =
689
770
        (const gs_function_PtCr_t *)
690
770
          ((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
770
    stream_SFD_state st;
700
770
    stream ds, bs;
701
770
    byte dbuf[200];   /* arbitrary */
702
770
    const stream_template *const templat = &s_SFD_template;
703
704
    /* Set up the stream that writes into the buffer. */
705
770
    s_init(&bs, NULL);
706
770
    swrite_string(&bs, buf, length);
707
    /* Set up the SubFileDecode stream. */
708
770
    s_init(&ds, NULL);
709
770
    s_init_state((stream_state *)&st, templat, NULL);
710
770
    templat->set_defaults((stream_state *)&st);
711
770
    st.skip_count = start;
712
770
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
713
770
    calc_put(&ds, pfn);
714
770
    sclose(&ds);
715
770
    if (ptr)
716
770
        *ptr = buf;
717
770
    return 0;
718
770
}
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
690
{
724
690
    const gs_function_PtCr_t *const pfn =
725
690
        (const gs_function_PtCr_t *)pfn_common;
726
727
690
    gs_function_get_info_default(pfn_common, pfi);
728
690
    pfi->DataSource = &pfn->data_source;
729
690
    {
730
690
        stream s;
731
732
690
        s_init(&s, NULL);
733
690
        swrite_position_only(&s);
734
690
        calc_put(&s, pfn);
735
690
        pfi->data_size = stell(&s);
736
690
    }
737
690
}
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
45.2k
{
805
45.2k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
806
45.2k
    params->ops.data = NULL;
807
45.2k
    params->ops.size = 0;
808
45.2k
    fn_common_free_params((gs_function_params_t *) params, mem);
809
45.2k
}
810
811
/* Serialize. */
812
static int
813
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
814
12.2k
{
815
12.2k
    uint n;
816
12.2k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
817
12.2k
    int code = fn_common_serialize(pfn, s);
818
819
12.2k
    if (code < 0)
820
0
        return code;
821
12.2k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
822
12.2k
    if (code < 0)
823
0
        return code;
824
12.2k
    return sputs(s, p->ops.data, p->ops.size, &n);
825
12.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
50.5k
{
832
50.5k
    static const gs_function_head_t function_PtCr_head = {
833
50.5k
        function_type_PostScript_Calculator,
834
50.5k
        {
835
50.5k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
836
50.5k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
837
50.5k
            (fn_get_info_proc_t) fn_PtCr_get_info,
838
50.5k
            fn_common_get_params,
839
50.5k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
840
50.5k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
841
50.5k
            fn_common_free,
842
50.5k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
843
50.5k
        }
844
50.5k
    };
845
50.5k
    int code;
846
847
50.5k
    *ppfn = 0;      /* in case of error */
848
50.5k
    code = fn_check_mnDR((const gs_function_params_t *)params,
849
50.5k
                         params->m, params->n);
850
50.5k
    if (code < 0)
851
28
        return code;
852
50.4k
    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
50.4k
    {
858
50.4k
        const byte *p = params->ops.data;
859
860
1.66M
        for (; *p != PtCr_return; ++p)
861
1.61M
            switch ((gs_PtCr_opcode_t)*p) {
862
369k
            case PtCr_byte:
863
369k
                ++p; break;
864
40.4k
            case PtCr_int:
865
40.4k
                p += sizeof(int); break;
866
82.7k
            case PtCr_float:
867
82.7k
                p += sizeof(float); break;
868
0
            case PtCr_repeat:
869
34.2k
            case PtCr_if:
870
67.9k
            case PtCr_else:
871
67.9k
                p += 2;
872
67.9k
            case PtCr_repeat_end:
873
67.9k
            case PtCr_true:
874
67.9k
            case PtCr_false:
875
67.9k
                break;
876
1.05M
            default:
877
1.05M
                if (*p >= PtCr_NUM_OPS)
878
0
                    return_error(gs_error_rangecheck);
879
1.61M
            }
880
50.4k
        if (p != params->ops.data + params->ops.size - 1)
881
0
            return_error(gs_error_rangecheck);
882
50.4k
    }
883
50.4k
    {
884
50.4k
        gs_function_PtCr_t *pfn =
885
50.4k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
886
50.4k
                            "gs_function_PtCr_init");
887
888
50.4k
        if (pfn == 0)
889
0
            return_error(gs_error_VMerror);
890
50.4k
        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
50.4k
        data_source_init_string2(&pfn->data_source, NULL, 0);
897
50.4k
        pfn->data_source.access = calc_access;
898
50.4k
        pfn->head = function_PtCr_head;
899
50.4k
        *ppfn = (gs_function_t *) pfn;
900
50.4k
    }
901
0
    return 0;
902
50.4k
}