Coverage Report

Created: 2025-11-16 07:40

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