Coverage Report

Created: 2025-06-10 07:27

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