Coverage Report

Created: 2025-06-10 07:15

/src/ghostpdl/base/gsfunc4.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2023 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* 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
12.5M
#define MAX_VSTACK 256    /* Max 100 is enough per PDF spec, but we use this
44
                                 * for DeviceN handling. Must be at least as large
45
                                 * as the number of components
46
                                 */
47
48
/* Define the structure of values on the stack. */
49
typedef enum {
50
    CVT_NONE = 0, /* empty stack slot */
51
    CVT_BOOL,
52
    CVT_INT,
53
    CVT_FLOAT
54
} calc_value_type_t;
55
typedef struct calc_value_s {
56
    calc_value_type_t type;
57
    union {
58
        int i;      /* also used for Boolean */
59
        float f;
60
    } value;
61
} calc_value_t;
62
63
/* Store a float. */
64
static inline void
65
store_float(calc_value_t *vsp, double f)
66
9.71M
{
67
9.71M
    vsp->value.f = f;
68
9.71M
    vsp->type = CVT_FLOAT;
69
9.71M
}
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
2.32M
{
109
2.32M
    const gs_function_PtCr_t *pfn = (const gs_function_PtCr_t *)pfn_common;
110
2.32M
    calc_value_t vstack_buf[2 + MAX_VSTACK + 1];
111
2.32M
    calc_value_t *vstack = &vstack_buf[1];
112
2.32M
    calc_value_t *vsp = vstack + pfn->params.m;
113
2.32M
    const byte *p = pfn->params.ops.data;
114
2.32M
    int repeat_count[MAX_PSC_FUNCTION_NESTING];
115
2.32M
    int repeat_proc_size[MAX_PSC_FUNCTION_NESTING];
116
2.32M
    int repeat_nesting_level = -1;
117
2.32M
    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
2.32M
    static const struct op_defn_s {
125
2.32M
        byte opcode[16];  /* 4 * type[-1] + type[0] */
126
2.32M
    } op_defn_table[] = {
127
        /* Keep this consistent with opcodes in gsfunc4.h! */
128
129
170M
#define O4(op) op,op,op,op
130
375M
#define E PtCr_typecheck
131
95.4M
#define E4 O4(E)
132
2.32M
#define N PtCr_no_op
133
        /* 0-operand operators */
134
2.32M
#define OP_NONE(op)\
135
18.6M
  {{O4(op), O4(op), O4(op), O4(op)}}
136
        /* 1-operand operators */
137
2.32M
#define OP1(b, i, f)\
138
46.5M
  {{E,b,i,f, E,b,i,f, E,b,i,f, E,b,i,f}}
139
2.32M
#define OP_NUM1(i, f)\
140
18.6M
  OP1(E, i, f)
141
2.32M
#define OP_MATH1(f)\
142
11.6M
  OP1(E, PtCr_int_to_float, f)
143
2.32M
#define OP_ANY1(op)\
144
4.65M
  OP1(op, op, op)
145
        /* 2-operand operators */
146
2.32M
#define OP_NUM2(i, f)\
147
16.3M
  {{E4, E4, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
148
2.32M
#define OP_INT_BOOL2(i)\
149
6.98M
  {{E4, E,i,i,E, E,i,i,E, E4}}
150
2.32M
#define OP_MATH2(f)\
151
6.98M
  {{E4, E4, E,E,PtCr_int2_to_float,PtCr_2nd_int_to_float,\
152
6.98M
    E,E,PtCr_int_to_float,f}}
153
2.32M
#define OP_INT2(i)\
154
9.31M
  {{E4, E4, E,E,i,E, E4}}
155
2.32M
#define OP_REL2(i, f)\
156
4.65M
  {{E4, E,i,E,E, E,E,i,PtCr_2nd_int_to_float, E,E,PtCr_int_to_float,f}}
157
2.32M
#define OP_ANY2(op)\
158
2.32M
  {{E4, E,op,op,op, E,op,op,op, E,op,op,op}}
159
160
    /* Arithmetic operators */
161
162
2.32M
        OP_NUM1(PtCr_abs_int, PtCr_abs), /* abs */
163
2.32M
        OP_NUM2(PtCr_add_int, PtCr_add), /* add */
164
2.32M
        OP_INT_BOOL2(PtCr_and),  /* and */
165
2.32M
        OP_MATH2(PtCr_atan),  /* atan */
166
2.32M
        OP_INT2(PtCr_bitshift),  /* bitshift */
167
2.32M
        OP_NUM1(N, PtCr_ceiling),  /* ceiling */
168
2.32M
        OP_MATH1(PtCr_cos), /* cos */
169
2.32M
        OP_NUM1(N, PtCr_cvi),  /* cvi */
170
2.32M
        OP_NUM1(PtCr_int_to_float, N), /* cvr */
171
2.32M
        OP_MATH2(PtCr_div), /* div */
172
2.32M
        OP_MATH2(PtCr_exp), /* exp */
173
2.32M
        OP_NUM1(N, PtCr_floor),  /* floor */
174
2.32M
        OP_INT2(PtCr_idiv),  /* idiv */
175
2.32M
        OP_MATH1(PtCr_ln),  /* ln */
176
2.32M
        OP_MATH1(PtCr_log), /* log */
177
2.32M
        OP_INT2(PtCr_mod), /* mod */
178
2.32M
        OP_NUM2(PtCr_mul_int, PtCr_mul), /* mul */
179
2.32M
        OP_NUM1(PtCr_neg_int, PtCr_neg), /* neg */
180
2.32M
        OP1(PtCr_not, PtCr_not, E),  /* not */
181
2.32M
        OP_INT_BOOL2(PtCr_or),  /* or */
182
2.32M
        OP_NUM1(N, PtCr_round),  /* round */
183
2.32M
        OP_MATH1(PtCr_sin), /* sin */
184
2.32M
        OP_MATH1(PtCr_sqrt),  /* sqrt */
185
2.32M
        OP_NUM2(PtCr_sub_int, PtCr_sub), /* sub */
186
2.32M
        OP_NUM1(N, PtCr_truncate), /* truncate */
187
2.32M
        OP_INT_BOOL2(PtCr_xor),  /* xor */
188
189
    /* Comparison operators */
190
191
2.32M
        OP_REL2(PtCr_eq_int, PtCr_eq), /* eq */
192
2.32M
        OP_NUM2(PtCr_ge_int, PtCr_ge), /* ge */
193
2.32M
        OP_NUM2(PtCr_gt_int, PtCr_gt), /* gt */
194
2.32M
        OP_NUM2(PtCr_le_int, PtCr_le), /* le */
195
2.32M
        OP_NUM2(PtCr_lt_int, PtCr_lt), /* lt */
196
2.32M
        OP_REL2(PtCr_ne_int, PtCr_ne), /* ne */
197
198
    /* Stack operators */
199
200
2.32M
        OP1(E, PtCr_copy, E),  /* copy */
201
2.32M
        OP_ANY1(PtCr_dup), /* dup */
202
2.32M
        OP_ANY2(PtCr_exch),  /* exch */
203
2.32M
        OP1(E, PtCr_index, E), /* index */
204
2.32M
        OP_ANY1(PtCr_pop), /* pop */
205
2.32M
        OP_INT2(PtCr_roll),  /* roll */
206
207
    /* Constants */
208
209
2.32M
        OP_NONE(PtCr_byte),    /* byte */
210
2.32M
        OP_NONE(PtCr_int),   /* int */
211
2.32M
        OP_NONE(PtCr_float),   /* float */
212
2.32M
        OP_NONE(PtCr_true),    /* true */
213
2.32M
        OP_NONE(PtCr_false),   /* false */
214
215
    /* Special */
216
217
2.32M
        OP1(PtCr_if, E, E),    /* if */
218
2.32M
        OP_NONE(PtCr_else),    /* else */
219
2.32M
        OP_NONE(PtCr_return),    /* return */
220
2.32M
        OP1(E, PtCr_repeat, E),    /* repeat */
221
2.32M
        OP_NONE(PtCr_repeat_end) /* repeat_end */
222
2.32M
    };
223
224
2.32M
    memset(repeat_count, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
225
2.32M
    memset(repeat_proc_size, 0x00, MAX_PSC_FUNCTION_NESTING * sizeof(int));
226
227
2.32M
    vstack[-1].type = CVT_NONE;  /* for type dispatch in empty stack case */
228
2.32M
    vstack[0].type = CVT_NONE;  /* catch underflow */
229
11.2M
    for (i = 0; i < pfn->params.m; ++i)
230
8.87M
        store_float(&vstack[i + 1], in[i]);
231
232
23.7M
    for (; ; ) {
233
23.7M
        int code, n;
234
235
23.7M
        switch (op_defn_table[*p++].opcode[(vsp[-1].type << 2) + vsp->type]) {
236
237
            /* Miscellaneous */
238
239
10.0k
        case PtCr_no_op:
240
10.0k
            continue;
241
1
        case PtCr_typecheck:
242
1
            return_error(gs_error_typecheck);
243
244
            /* Coerce and re-dispatch */
245
246
557k
        case PtCr_int_to_float:
247
557k
            store_float(vsp, (double)vsp->value.i);
248
557k
            --p; continue;
249
0
        case PtCr_int2_to_float:
250
0
            store_float(vsp, (double)vsp->value.i);
251
            /* fall through */
252
280k
        case PtCr_2nd_int_to_float:
253
280k
            store_float(vsp - 1, (double)vsp[-1].value.i);
254
280k
            --p; continue;
255
256
            /* Arithmetic operators */
257
258
166k
        case PtCr_abs:
259
166k
            vsp->value.f = fabs(vsp->value.f);
260
166k
            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
0
        }
270
538k
        case PtCr_add:
271
538k
            vsp[-1].value.f += vsp->value.f;
272
538k
            --vsp; continue;
273
0
        case PtCr_and:
274
0
            vsp[-1].value.i &= vsp->value.i;
275
0
            --vsp; continue;
276
132k
        case PtCr_atan: {
277
132k
            double result;
278
279
132k
            code = gs_atan2_degrees(vsp[-1].value.f, vsp->value.f,
280
132k
                                    &result);
281
132k
            if (code < 0)
282
0
                return code;
283
132k
            vsp[-1].value.f = result;
284
132k
            --vsp; continue;
285
132k
        }
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
132k
        case PtCr_cos:
300
132k
            vsp->value.f = gs_cos_degrees(vsp->value.f);
301
132k
            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
132k
        }
313
0
        case PtCr_cvr:
314
0
            continue;  /* prepare handled it */
315
132k
        case PtCr_div:
316
132k
            if (vsp->value.f == 0)
317
0
                return_error(gs_error_undefinedresult);
318
132k
            vsp[-1].value.f /= vsp->value.f;
319
132k
            --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
117k
        case PtCr_mul_int: {
347
            /* We don't bother to optimize this. */
348
117k
            double prod = (double)vsp[-1].value.i * vsp->value.i;
349
350
117k
            if (prod < min_int || prod > max_int)
351
0
                store_float(vsp - 1, prod);
352
117k
            else
353
117k
                vsp[-1].value.i = (int)prod;
354
117k
            --vsp; continue;
355
0
        }
356
1.06M
        case PtCr_mul:
357
1.06M
            vsp[-1].value.f *= vsp->value.f;
358
1.06M
            --vsp; continue;
359
0
        case PtCr_abs_int:
360
0
            if (vsp->value.i >= 0)
361
0
                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
132k
        case PtCr_sin:
385
132k
            vsp->value.f = gs_sin_degrees(vsp->value.f);
386
132k
            continue;
387
132k
        case PtCr_sqrt:
388
132k
            vsp->value.f = sqrt(vsp->value.f);
389
132k
            continue;
390
196k
        case PtCr_sub_int: {
391
196k
            int int1 = vsp[-1].value.i, int2 = vsp->value.i;
392
393
196k
            if ((int1 ^ int2) < 0 && ((int1 - int2) ^ int1) >= 0)
394
0
                store_float(vsp - 1, (double)int1 - int2);
395
196k
            else
396
196k
                vsp[-1].value.i = int1 - int2;
397
196k
            --vsp; continue;
398
0
        }
399
665k
        case PtCr_sub:
400
665k
            vsp[-1].value.f -= vsp->value.f;
401
665k
            --vsp; continue;
402
0
        case PtCr_truncate:
403
0
            vsp->value.f = (vsp->value.f < 0 ? ceil(vsp->value.f) :
404
0
                            floor(vsp->value.f));
405
0
            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
149k
  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
1
        case PtCr_ge_int:
419
1
            DO_REL(>=, i);
420
1
            goto rel;
421
4
        case PtCr_ge:
422
4
            DO_REL(>=, f);
423
4
            goto rel;
424
51
        case PtCr_gt_int:
425
51
            DO_REL(>, i);
426
51
            goto rel;
427
17
        case PtCr_gt:
428
17
            DO_REL(>, f);
429
17
            goto rel;
430
0
        case PtCr_le_int:
431
0
            DO_REL(<=, i);
432
0
            goto rel;
433
17.0k
        case PtCr_le:
434
17.0k
            DO_REL(<=, f);
435
17.0k
            goto rel;
436
0
        case PtCr_lt_int:
437
0
            DO_REL(<, i);
438
0
            goto rel;
439
132k
        case PtCr_lt:
440
132k
            DO_REL(<, f);
441
132k
            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
149k
        rel:
451
149k
            vsp[-1].type = CVT_BOOL;
452
149k
            --vsp; continue;
453
454
0
#undef DO_REL
455
456
            /* Stack operators */
457
458
17.0k
        case PtCr_copy:
459
17.0k
            i = vsp->value.i;
460
17.0k
            n = vsp - vstack;
461
17.0k
            if (i < 0 || i >= n)
462
0
                return_error(gs_error_rangecheck);
463
17.0k
            if (i > MAX_VSTACK - (n - 1))
464
0
                return_error(gs_error_limitcheck);
465
17.0k
            memcpy(vsp, vsp - i, i * sizeof(*vsp));
466
17.0k
            vsp += i - 1;
467
17.0k
            continue;
468
883k
        case PtCr_dup:
469
883k
            vsp[1] = *vsp;
470
883k
            goto push;
471
1.71M
        case PtCr_exch:
472
1.71M
            vstack[MAX_VSTACK] = *vsp;
473
1.71M
            *vsp = vsp[-1];
474
1.71M
            vsp[-1] = vstack[MAX_VSTACK];
475
1.71M
            continue;
476
761k
        case PtCr_index:
477
761k
            i = vsp->value.i;
478
761k
            if (i < 0 || i >= vsp - vstack - 1)
479
0
                return_error(gs_error_rangecheck);
480
761k
            *vsp = vsp[-i - 1];
481
761k
            continue;
482
2.63M
        case PtCr_pop:
483
2.63M
            --vsp;
484
2.63M
            continue;
485
2.62M
        case PtCr_roll:
486
2.62M
            n = vsp[-1].value.i;
487
2.62M
            i = vsp->value.i;
488
2.62M
            if (n < 0 || n > vsp - vstack - 2)
489
0
                return_error(gs_error_rangecheck);
490
            /* We don't bother to do this efficiently. */
491
9.26M
            for (; i > 0; i--) {
492
6.64M
                memmove(vsp - n, vsp - (n + 1), n * sizeof(*vsp));
493
6.64M
                vsp[-(n + 1)] = vsp[-1];
494
6.64M
            }
495
2.89M
            for (; i < 0; i++) {
496
269k
                vsp[-1] = vsp[-(n + 1)];
497
269k
                memmove(vsp - (n + 1), vsp - n, n * sizeof(*vsp));
498
269k
            }
499
2.62M
            vsp -= 2;
500
2.62M
            continue;
501
502
            /* Constants */
503
504
6.84M
        case PtCr_byte:
505
6.84M
            vsp[1].value.i = *p++, vsp[1].type = CVT_INT;
506
6.84M
            goto push;
507
534k
        case PtCr_int /* native */:
508
534k
            memcpy(&vsp[1].value.i, p, sizeof(int));
509
534k
            vsp[1].type = CVT_INT;
510
534k
            p += sizeof(int);
511
534k
            goto push;
512
880k
        case PtCr_float /* native */:
513
880k
            memcpy(&vsp[1].value.f, p, sizeof(float));
514
880k
            vsp[1].type = CVT_FLOAT;
515
880k
            p += sizeof(float);
516
880k
            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
9.14M
        push:
523
9.14M
            if (vsp == &vstack[MAX_VSTACK])
524
0
                return_error(gs_error_limitcheck);
525
9.14M
            ++vsp;
526
9.14M
            continue;
527
528
            /* Special */
529
530
149k
        case PtCr_if:
531
149k
            if ((vsp--)->value.i) { /* value is true, execute body */
532
126k
                p += 2;
533
126k
                continue;
534
126k
            }
535
            /* falls through */
536
32.0k
        case PtCr_else:
537
32.0k
            p += 2 + (p[0] << 8) + p[1];  /* skip the past body */
538
32.0k
            continue;
539
2.32M
        case PtCr_return:
540
2.32M
            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
23.7M
        }
558
23.7M
    }
559
2.32M
 fin:
560
2.32M
    {   /* Following Acrobat, take the desired number of parameters */
561
        /* from the top of stack and ignore the rest. Bug 702950. */
562
2.32M
        int extra_ops = vsp - vstack - pfn->params.n;
563
2.32M
        if (extra_ops < 0)
564
1
            return_error(gs_error_rangecheck);
565
9.33M
        for (i = 0; i < pfn->params.n; ++i) {
566
7.00M
            switch (vstack[i + 1 + extra_ops].type) {
567
198k
            case CVT_INT:
568
198k
                out[i] = (float)vstack[i + 1 + extra_ops].value.i;
569
198k
                break;
570
6.81M
            case CVT_FLOAT:
571
6.81M
                out[i] = vstack[i + 1 + extra_ops].value.f;
572
6.81M
                break;
573
0
            default:
574
0
                return_error(gs_error_typecheck);
575
7.00M
            }
576
7.00M
        }
577
2.32M
    }
578
2.32M
    return 0;
579
2.32M
}
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
549
{
600
549
    const byte *p;
601
602
549
    spputc(s, '{');
603
3.68k
    for (p = ops; p < ops + size; )
604
3.13k
        switch (*p++) {
605
986
        case PtCr_byte:
606
986
            pprintd1(s, "%d ", *p++);
607
986
            break;
608
133
        case PtCr_int: {
609
133
            int i;
610
611
133
            memcpy(&i, p, sizeof(int));
612
133
            pprintd1(s, "%d ", i);
613
133
            p += sizeof(int);
614
133
            break;
615
0
        }
616
862
        case PtCr_float: {
617
862
            float f;
618
619
862
            memcpy(&f, p, sizeof(float));
620
862
            pprintg1(s, "%g ", f);
621
862
            p += sizeof(float);
622
862
            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
114
        case PtCr_if: {
631
114
            int skip = (p[0] << 8) + p[1];
632
114
            int code;
633
634
114
            code = calc_put_ops(s, p += 2, skip);
635
114
            p += skip;
636
114
            if (code < 0)
637
0
                return code;
638
114
            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
114
                stream_puts(s, " if ");
647
114
            break;
648
114
        }
649
114
        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
1.03k
        default: {    /* must be < PtCr_NUM_OPS */
659
1.03k
                static const char *const op_names[] = {
660
                    /* Keep this consistent with opcodes in gsfunc4.h! */
661
1.03k
                    "abs", "add", "and", "atan", "bitshift",
662
1.03k
                    "ceiling", "cos", "cvi", "cvr", "div", "exp",
663
1.03k
                    "floor", "idiv", "ln", "log", "mod", "mul",
664
1.03k
                    "neg", "not", "or", "round", "sin", "sqrt", "sub",
665
1.03k
                    "truncate", "xor",
666
1.03k
                    "eq", "ge", "gt", "le", "lt", "ne",
667
1.03k
                    "copy", "dup", "exch", "index", "pop", "roll"
668
1.03k
                };
669
670
1.03k
                pprints1(s, "%s ", op_names[p[-1]]);
671
1.03k
            }
672
3.13k
        }
673
549
    spputc(s, '}');
674
549
    return 0;
675
549
}
676
static int
677
calc_put(stream *s, const gs_function_PtCr_t *pfn)
678
435
{
679
435
    calc_put_ops(s, pfn->params.ops.data, pfn->params.ops.size - 1);
680
435
    return 0;
681
435
}
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
222
{
688
222
    const gs_function_PtCr_t *const pfn =
689
222
        (const gs_function_PtCr_t *)
690
222
          ((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
222
    stream_SFD_state st;
700
222
    stream ds, bs;
701
222
    byte dbuf[200];   /* arbitrary */
702
222
    const stream_template *const templat = &s_SFD_template;
703
704
    /* Set up the stream that writes into the buffer. */
705
222
    s_init(&bs, NULL);
706
222
    swrite_string(&bs, buf, length);
707
    /* Set up the SubFileDecode stream. */
708
222
    s_init(&ds, NULL);
709
222
    s_init_state((stream_state *)&st, templat, NULL);
710
222
    templat->set_defaults((stream_state *)&st);
711
222
    st.skip_count = start;
712
222
    s_init_filter(&ds, (stream_state *)&st, dbuf, sizeof(dbuf), &bs);
713
222
    calc_put(&ds, pfn);
714
222
    sclose(&ds);
715
222
    if (ptr)
716
222
        *ptr = buf;
717
222
    return 0;
718
222
}
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
213
{
724
213
    const gs_function_PtCr_t *const pfn =
725
213
        (const gs_function_PtCr_t *)pfn_common;
726
727
213
    gs_function_get_info_default(pfn_common, pfi);
728
213
    pfi->DataSource = &pfn->data_source;
729
213
    {
730
213
        stream s;
731
732
213
        s_init(&s, NULL);
733
213
        swrite_position_only(&s);
734
213
        calc_put(&s, pfn);
735
213
        pfi->data_size = stell(&s);
736
213
    }
737
213
}
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
4.69k
{
805
4.69k
    gs_free_const_string(mem, params->ops.data, params->ops.size, "ops");
806
4.69k
    params->ops.data = NULL;
807
4.69k
    params->ops.size = 0;
808
4.69k
    fn_common_free_params((gs_function_params_t *) params, mem);
809
4.69k
}
810
811
/* Serialize. */
812
static int
813
gs_function_PtCr_serialize(const gs_function_t * pfn, stream *s)
814
1.90k
{
815
1.90k
    uint n;
816
1.90k
    const gs_function_PtCr_params_t * p = (const gs_function_PtCr_params_t *)&pfn->params;
817
1.90k
    int code = fn_common_serialize(pfn, s);
818
819
1.90k
    if (code < 0)
820
0
        return code;
821
1.90k
    code = sputs(s, (const byte *)&p->ops.size, sizeof(p->ops.size), &n);
822
1.90k
    if (code < 0)
823
0
        return code;
824
1.90k
    return sputs(s, p->ops.data, p->ops.size, &n);
825
1.90k
}
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
5.22k
{
832
5.22k
    static const gs_function_head_t function_PtCr_head = {
833
5.22k
        function_type_PostScript_Calculator,
834
5.22k
        {
835
5.22k
            (fn_evaluate_proc_t) fn_PtCr_evaluate,
836
5.22k
            (fn_is_monotonic_proc_t) fn_PtCr_is_monotonic,
837
5.22k
            (fn_get_info_proc_t) fn_PtCr_get_info,
838
5.22k
            fn_common_get_params,
839
5.22k
            (fn_make_scaled_proc_t) fn_PtCr_make_scaled,
840
5.22k
            (fn_free_params_proc_t) gs_function_PtCr_free_params,
841
5.22k
            fn_common_free,
842
5.22k
            (fn_serialize_proc_t) gs_function_PtCr_serialize,
843
5.22k
        }
844
5.22k
    };
845
5.22k
    int code;
846
847
5.22k
    *ppfn = 0;      /* in case of error */
848
5.22k
    code = fn_check_mnDR((const gs_function_params_t *)params,
849
5.22k
                         params->m, params->n);
850
5.22k
    if (code < 0)
851
4
        return code;
852
5.22k
    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
5.22k
    {
858
5.22k
        const byte *p = params->ops.data;
859
860
221k
        for (; *p != PtCr_return; ++p)
861
216k
            switch ((gs_PtCr_opcode_t)*p) {
862
61.7k
            case PtCr_byte:
863
61.7k
                ++p; break;
864
9.82k
            case PtCr_int:
865
9.82k
                p += sizeof(int); break;
866
19.4k
            case PtCr_float:
867
19.4k
                p += sizeof(float); break;
868
0
            case PtCr_repeat:
869
2.19k
            case PtCr_if:
870
4.32k
            case PtCr_else:
871
4.32k
                p += 2;
872
4.32k
            case PtCr_repeat_end:
873
4.32k
            case PtCr_true:
874
4.32k
            case PtCr_false:
875
4.32k
                break;
876
121k
            default:
877
121k
                if (*p >= PtCr_NUM_OPS)
878
0
                    return_error(gs_error_rangecheck);
879
216k
            }
880
5.22k
        if (p != params->ops.data + params->ops.size - 1)
881
0
            return_error(gs_error_rangecheck);
882
5.22k
    }
883
5.22k
    {
884
5.22k
        gs_function_PtCr_t *pfn =
885
5.22k
            gs_alloc_struct(mem, gs_function_PtCr_t, &st_function_PtCr,
886
5.22k
                            "gs_function_PtCr_init");
887
888
5.22k
        if (pfn == 0)
889
0
            return_error(gs_error_VMerror);
890
5.22k
        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
5.22k
        data_source_init_string2(&pfn->data_source, NULL, 0);
897
5.22k
        pfn->data_source.access = calc_access;
898
5.22k
        pfn->head = function_PtCr_head;
899
5.22k
        *ppfn = (gs_function_t *) pfn;
900
5.22k
    }
901
0
    return 0;
902
5.22k
}