Coverage Report

Created: 2022-10-31 07:00

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