Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/psi/zfunc4.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
/* PostScript language support for FunctionType 4 (PS Calculator) Functions */
18
#include "memory_.h"
19
#include "ghost.h"
20
#include "oper.h"
21
#include "opextern.h"
22
#include "gsfunc.h"
23
#include "gsfunc4.h"
24
#include "gsutil.h"
25
#include "idict.h"
26
#include "ifunc.h"
27
#include "iname.h"
28
#include "dstack.h"
29
#include "ialloc.h"
30
#include "gzstate.h"      /* these are needed to check device parameters */
31
#include "gsparam.h"      /* these are needed to check device parameters */
32
#include "zfunc.h"
33
#include "zcolor.h"
34
#include "gxdevsop.h"
35
36
/*
37
 * FunctionType 4 functions are not defined in the PostScript language.  We
38
 * provide support for them because they are needed for PDF 1.3.  In
39
 * addition to the standard FunctionType, Domain, and Range keys, they have
40
 * a Function key whose value is a procedure in a restricted subset of the
41
 * PostScript language.  Specifically, the procedure must (recursively)
42
 * contain only integer, real, Boolean, and procedure constants (only as
43
 * literal operands of if and and ifelse), and operators chosen from the set
44
 * given below.  Note that names other than true and false are not allowed:
45
 * the procedure must be 'bound'.
46
 *
47
 * The following list is taken directly from the PDF 1.3 documentation.
48
 */
49
#define XOP(zfn) int zfn(i_ctx_t *)
50
XOP(zabs); XOP(zand); XOP(zatan); XOP(zbitshift);
51
XOP(zceiling); XOP(zcos); XOP(zcvi); XOP(zcvr);
52
XOP(zdiv); XOP(zexp); XOP(zfloor); XOP(zidiv);
53
XOP(zln); XOP(zlog); XOP(zmod); XOP(zmul);
54
XOP(zneg); XOP(znot); XOP(zor); XOP(zround);
55
XOP(zsin); XOP(zsqrt); XOP(ztruncate); XOP(zxor);
56
XOP(zeq); XOP(zge); XOP(zgt); XOP(zle); XOP(zlt); XOP(zne);
57
XOP(z2copy);
58
#undef XOP
59
typedef struct calc_op_s {
60
    op_proc_t proc;
61
    gs_PtCr_opcode_t opcode;
62
} calc_op_t;
63
static const calc_op_t calc_ops[] = {
64
65
    /* Arithmetic operators */
66
67
    {zabs, PtCr_abs},
68
    {zadd, PtCr_add},
69
    {zand, PtCr_and},
70
    {zatan, PtCr_atan},
71
    {zbitshift, PtCr_bitshift},
72
    {zceiling, PtCr_ceiling},
73
    {zcos, PtCr_cos},
74
    {zcvi, PtCr_cvi},
75
    {zcvr, PtCr_cvr},
76
    {zdiv, PtCr_div},
77
    {zexp, PtCr_exp},
78
    {zfloor, PtCr_floor},
79
    {zidiv, PtCr_idiv},
80
    {zln, PtCr_ln},
81
    {zlog, PtCr_log},
82
    {zmod, PtCr_mod},
83
    {zmul, PtCr_mul},
84
    {zneg, PtCr_neg},
85
    {znot, PtCr_not},
86
    {zor, PtCr_or},
87
    {zround, PtCr_round},
88
    {zsin, PtCr_sin},
89
    {zsqrt, PtCr_sqrt},
90
    {zsub, PtCr_sub},
91
    {ztruncate, PtCr_truncate},
92
    {zxor, PtCr_xor},
93
94
    /* Comparison operators */
95
96
    {zeq, PtCr_eq},
97
    {zge, PtCr_ge},
98
    {zgt, PtCr_gt},
99
    {zle, PtCr_le},
100
    {zlt, PtCr_lt},
101
    {zne, PtCr_ne},
102
103
    /* Stack operators */
104
105
    {zcopy, PtCr_copy},
106
    {z2copy, PtCr_copy},
107
    {zdup, PtCr_dup},
108
    {zexch, PtCr_exch},
109
    {zindex, PtCr_index},
110
    {zpop, PtCr_pop},
111
    {zroll, PtCr_roll}
112
113
    /* Special operators */
114
115
    /*{zif, PtCr_if},*/
116
    /*{zifelse, PtCr_ifelse},*/
117
    /*{ztrue, PtCr_true},*/
118
    /*{zfalse, PtCr_false}*/
119
};
120
121
/* Fix up an if or ifelse forward reference. */
122
static void
123
psc_fixup(byte *p, byte *to)
124
0
{
125
0
    int skip = to - (p + 3);
126
127
0
    p[1] = (byte)(skip >> 8);
128
0
    p[2] = (byte)skip;
129
0
}
130
131
/* Check whether the ref is a given operator or resolves to it */
132
static bool
133
resolves_to_oper(i_ctx_t *i_ctx_p, const ref *pref, const op_proc_t proc)
134
0
{
135
0
    if (!r_has_attr(pref, a_executable))
136
0
        return false;
137
0
    if (r_btype(pref) == t_operator) {
138
0
        return pref->value.opproc == proc;
139
0
    } else if (r_btype(pref) == t_name) {
140
0
        ref * val;
141
0
        if (dict_find(systemdict, pref, &val) <= 0)
142
0
            return false;
143
0
        if (r_btype(val) != t_operator)
144
0
            return false;
145
0
        if (!r_has_attr(val, a_executable))
146
0
            return false;
147
0
        return val->value.opproc == proc;
148
0
    }
149
0
   else
150
0
      return false;
151
0
}
152
153
/* Store an int in the  buffer */
154
static int
155
3.97k
put_int(byte **p, int n) {
156
3.97k
   if (n == (byte)n) {
157
3.87k
       if (*p) {
158
3.87k
          (*p)[0] = PtCr_byte;
159
3.87k
          (*p)[1] = (byte)n;
160
3.87k
          *p += 2;
161
3.87k
       }
162
3.87k
       return 2;
163
3.87k
   } else {
164
97
       if (*p) {
165
97
          **p = PtCr_int;
166
97
          memcpy(*p + 1, &n, sizeof(int));
167
97
          *p += sizeof(int) + 1;
168
97
       }
169
97
       return (sizeof(int) + 1);
170
97
   }
171
3.97k
}
172
173
/* Store a float in the  buffer */
174
static int
175
8.45k
put_float(byte **p, float n) {
176
8.45k
   if (*p) {
177
8.45k
      **p = PtCr_float;
178
8.45k
      memcpy(*p + 1, &n, sizeof(float));
179
8.45k
      *p += sizeof(float) + 1;
180
8.45k
   }
181
8.45k
   return (sizeof(float) + 1);
182
8.45k
}
183
184
/* Store an op code in the  buffer */
185
static int
186
0
put_op(byte **p, byte op) {
187
0
   if (*p)
188
0
      *(*p)++ = op;
189
0
   return 1;
190
0
}
191
192
/*
193
 * Check a calculator function for validity, optionally storing its encoded
194
 * representation and add the size of the encoded representation to *psize.
195
 * Note that we arbitrarily limit the depth of procedure nesting.  pref is
196
 * known to be a procedure.
197
 */
198
static int
199
check_psc_function(i_ctx_t *i_ctx_p, const ref *pref, int depth, byte *ops, int *psize, bool AllowRepeat)
200
2.49k
{
201
2.49k
    int code;
202
2.49k
    uint i, j;
203
2.49k
    uint size = r_size(pref);
204
2.49k
    byte *p;
205
206
2.49k
    if (size == 2 && depth == 0) {
207
        /* Bug 690986. Recognize and replace Corel tint transform function.
208
           { tint_params CorelTintTransformFunction }
209
210
           Where tint_params resolves to an arrey like:
211
             [ 1.0 0.0 0.0 0.0
212
               0.0 1.0 0.0 0.0
213
               0.0 0.0 1.0 0.0
214
               0.0 0.0 0.0 1.0
215
               0.2 0.81 0.76 0.61
216
            ]
217
           And CorelTintTransformFunction is:
218
            { /colorantSpecArray exch def
219
              /nColorants colorantSpecArray length 4 idiv def
220
              /inColor nColorants 1 add 1 roll nColorants array astore def
221
              /outColor 4 array def
222
              0 1 3 {
223
                /nOutInk exch def
224
                1
225
                0 1 nColorants 1 sub {
226
                  dup inColor exch get
227
                  exch 4 mul nOutInk add colorantSpecArray exch get mul
228
                  1 exch sub mul
229
                } for
230
                1 exch sub
231
                outColor nOutInk 3 -1 roll put
232
              } for
233
              outColor aload pop
234
            }
235
        */
236
2
        ref r_tp, r_cttf; /* original references */
237
2
        ref n_tp, n_cttf; /* names */
238
2
        ref *v_tp, *v_cttf; /* values */
239
2
        int sz;
240
241
2
        p = ops;
242
2
        sz = *psize;
243
2
        if(array_get(imemory, pref, 0, &r_tp) < 0)
244
0
            goto idiom_failed;
245
2
        if (array_get(imemory, pref, 1, &r_cttf) < 0)
246
0
            goto idiom_failed;
247
2
        if (r_has_type(&r_tp, t_name) && r_has_type(&r_cttf, t_name)) {
248
0
            if ((code = name_enter_string(imemory, "tint_params", &n_tp)) < 0)
249
0
                return code;
250
0
            if (r_tp.value.pname == n_tp.value.pname) {
251
0
                if ((code = name_enter_string(imemory, "CorelTintTransformFunction", &n_cttf)) < 0)
252
0
                    return code;
253
0
                if (r_cttf.value.pname == n_cttf.value.pname) {
254
0
                    v_tp   = dict_find_name(&n_tp);
255
0
                    v_cttf = dict_find_name(&n_cttf);
256
0
                    if (v_tp && v_cttf && r_is_array(v_tp) && r_is_array(v_cttf)) {
257
0
                        uint n_elem = r_size(v_tp);
258
259
0
                        if ((n_elem & 3) == 0 && r_size(v_cttf) == 31) {
260
                            /* Enough testing, idiom recognition tests less. */
261
0
                            uint n_col = n_elem/4;
262
263
0
                            for (i = 0; i < 4; i ++) {
264
0
                                ref v;
265
0
                                float fv;
266
0
                                bool first = true;
267
268
0
                                for (j = 0; j < n_col; j++) {
269
0
                                    if (array_get(imemory, v_tp, j*4 + i, &v) < 0)
270
0
                                        goto idiom_failed;
271
0
                                    if (r_type(&v) == t_integer)
272
0
                                        fv = (float)v.value.intval;
273
0
                                    else if (r_type(&v) == t_real)
274
0
                                        fv = v.value.realval;
275
0
                                    else
276
0
                                        goto idiom_failed;
277
278
0
                                    if (fv != 0.) {
279
0
                                        if (first)
280
0
                                            sz += put_int(&p, 1);
281
0
                                        sz += put_int(&p, 1);
282
0
                                        sz += put_int(&p, n_col + 1 - j + i + !first);
283
0
                                        sz += put_op(&p, PtCr_index);
284
0
                                        if (fv != 1.) {
285
0
                                            sz += put_float(&p, fv);
286
0
                                            sz += put_op(&p, PtCr_mul);
287
0
                                        }
288
0
                                        sz += put_op(&p, PtCr_sub);
289
0
                                        if (first)
290
0
                                            first = false;
291
0
                                        else
292
0
                                            sz += put_op(&p, PtCr_mul);
293
0
                                    }
294
0
                                }
295
0
                                if (first)
296
0
                                    sz += put_int(&p, 0);
297
0
                                else
298
0
                                    sz += put_op(&p, PtCr_sub);
299
0
                            }
300
                            /* n_col+4 4 roll pop ... pop  */
301
0
                            sz += put_int(&p, n_col + 4);
302
0
                            sz += put_int(&p, 4);
303
0
                            sz += put_op(&p, PtCr_roll);
304
0
                            for (j = 0; j < n_col; j++)
305
0
                                sz += put_op(&p, PtCr_pop);
306
0
                            *psize = sz;
307
0
                            return 0;
308
0
                        }
309
0
                    }
310
0
                }
311
0
            }
312
0
        }
313
2
    }
314
2.49k
  idiom_failed:;
315
17.2k
    for (i = 0; i < size; ++i) {
316
14.8k
        byte no_ops[1 + max(sizeof(int), sizeof(float))];
317
14.8k
        ref elt, elt2, elt3;
318
14.8k
        ref * delp;
319
320
14.8k
        p = (ops ? ops + *psize : no_ops);
321
14.8k
        array_get(imemory, pref, i, &elt);
322
14.8k
        switch (r_btype(&elt)) {
323
3.97k
        case t_integer:
324
3.97k
            *psize += put_int(&p, elt.value.intval);
325
3.97k
            break;
326
8.45k
        case t_real:
327
8.45k
            *psize += put_float(&p, elt.value.realval);
328
8.45k
            break;
329
0
        case t_boolean:
330
0
            *p = (elt.value.boolval ? PtCr_true : PtCr_false);
331
0
            ++*psize;
332
0
            break;
333
2.39k
        case t_name:
334
2.39k
            if (!r_has_attr(&elt, a_executable))
335
5
                return_error(gs_error_rangecheck);
336
2.39k
            name_string_ref(imemory, &elt, &elt);
337
2.39k
            if (!bytes_compare(elt.value.bytes, r_size(&elt),
338
2.39k
                               (const byte *)"true", 4)) {
339
0
                *p = PtCr_true;
340
0
                ++*psize;
341
0
                break;
342
0
            }
343
2.39k
            if (!bytes_compare(elt.value.bytes, r_size(&elt),
344
2.39k
                                      (const byte *)"false", 5)) {
345
0
                *p = PtCr_false;
346
0
                ++*psize;
347
0
                break;
348
0
            }
349
            /* Check if the name is a valid operator in systemdict */
350
2.39k
            if (dict_find(systemdict, &elt, &delp) <= 0)
351
23
                return_error(gs_error_undefined);
352
2.37k
            if (r_btype(delp) != t_operator)
353
37
                return_error(gs_error_typecheck);
354
2.33k
            if (!r_has_attr(delp, a_executable))
355
0
                return_error(gs_error_rangecheck);
356
2.33k
            elt = *delp;
357
            /* Fall into the operator case */
358
2.33k
        case t_operator: {
359
2.33k
            int j;
360
361
84.0k
            for (j = 0; j < countof(calc_ops); ++j)
362
84.0k
                if (elt.value.opproc == calc_ops[j].proc) {
363
2.33k
                    *p = calc_ops[j].opcode;
364
2.33k
                    ++*psize;
365
2.33k
                    goto next;
366
2.33k
                }
367
2.33k
            return_error(gs_error_rangecheck);
368
2.33k
        }
369
0
        default: {
370
0
            if (!r_is_proc(&elt))
371
0
                return_error(gs_error_typecheck);
372
0
            if (depth == MAX_PSC_FUNCTION_NESTING)
373
0
                return_error(gs_error_limitcheck);
374
0
            if ((code = array_get(imemory, pref, ++i, &elt2)) < 0)
375
0
                return code;
376
0
            *psize += 3;
377
0
            code = check_psc_function(i_ctx_p, &elt, depth + 1, ops, psize, AllowRepeat);
378
0
            if (code < 0)
379
0
                return code;
380
            /* Check for { proc } repeat | {proc} if | {proc1} {proc2} ifelse */
381
0
            if (resolves_to_oper(i_ctx_p, &elt2, zrepeat)) {
382
0
                if (!AllowRepeat)
383
0
                    return_error(gs_error_rangecheck);
384
0
                if (ops) {
385
0
                    *p = PtCr_repeat;
386
0
                    psc_fixup(p, ops + *psize);
387
0
                    p = ops + *psize;
388
0
                    *p++ = PtCr_repeat_end;
389
0
                }
390
0
                *psize += 1;  /* extra room for repeat_end */
391
0
            } else if (resolves_to_oper(i_ctx_p, &elt2, zif)) {
392
0
                if (ops) {
393
0
                    *p = PtCr_if;
394
0
                    psc_fixup(p, ops + *psize);
395
0
                }
396
0
            } else if (!r_is_proc(&elt2))
397
0
                return_error(gs_error_rangecheck);
398
0
            else if ((code = array_get(imemory, pref, ++i, &elt3)) < 0)
399
0
                return code;
400
0
            else if (resolves_to_oper(i_ctx_p, &elt3, zifelse)) {
401
0
                if (ops) {
402
0
                    *p = PtCr_if;
403
0
                    psc_fixup(p, ops + *psize + 3);
404
0
                    p = ops + *psize;
405
0
                    *p = PtCr_else;
406
0
                }
407
0
                *psize += 3;
408
0
                code = check_psc_function(i_ctx_p, &elt2, depth + 1, ops, psize, AllowRepeat);
409
0
                if (code < 0)
410
0
                    return code;
411
0
                if (ops)
412
0
                    psc_fixup(p, ops + *psize);
413
0
            } else
414
0
                return_error(gs_error_rangecheck);
415
0
            }   /* end 'default' */
416
14.8k
        }
417
14.7k
    next:
418
14.7k
        DO_NOTHING;
419
14.7k
    }
420
2.42k
    return 0;
421
2.49k
}
422
#undef MAX_PSC_FUNCTION_NESTING
423
424
/* Check prototype */
425
build_function_proc(gs_build_function_4);
426
427
/* Finish building a FunctionType 4 (PostScript Calculator) function. */
428
int
429
gs_build_function_4(i_ctx_t *i_ctx_p, const ref *op, const gs_function_params_t * mnDR,
430
                    int depth, gs_function_t ** ppfn, gs_memory_t *mem)
431
0
{
432
0
    gs_function_PtCr_params_t params;
433
0
    ref *proc;
434
0
    int code;
435
0
    byte *ops;
436
0
    int size;
437
0
    int AllowRepeat = 1; /* Default to permitting Repeat, devices which can't handle it implement the spec_op */
438
439
0
    *(gs_function_params_t *)&params = *mnDR;
440
0
    params.ops.data = 0;  /* in case of failure */
441
0
    params.ops.size = 0;  /* ditto */
442
0
    if (dict_find_string(op, "Function", &proc) <= 0) {
443
0
        code = gs_note_error(gs_error_rangecheck);
444
0
        goto fail;
445
0
    }
446
0
    if (!r_is_proc(proc)) {
447
0
        code = gs_note_error(gs_error_typecheck);
448
0
        goto fail;
449
0
    }
450
0
    size = 0;
451
452
    /* Check if the device allows the use of repeat in functions */
453
    /* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
454
0
    {
455
0
        char data[] = {"AllowPSRepeatFunctions"};
456
0
        dev_param_req_t request;
457
0
        gs_c_param_list list;
458
459
0
        gs_c_param_list_write(&list, i_ctx_p->pgs->device->memory);
460
        /* Stuff the data into a structure for passing to the spec_op */
461
0
        request.Param = data;
462
0
        request.list = &list;
463
0
        code = dev_proc(i_ctx_p->pgs->device, dev_spec_op)(i_ctx_p->pgs->device, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
464
0
        if (code < 0 && code != gs_error_undefined) {
465
0
            gs_c_param_list_release(&list);
466
0
            return code;
467
0
        }
468
0
        gs_c_param_list_read(&list);
469
0
        code = param_read_bool((gs_param_list *)&list,
470
0
            "AllowPSRepeatFunctions",
471
0
            &AllowRepeat);
472
0
        gs_c_param_list_release(&list);
473
0
        if (code < 0)
474
0
            return code;
475
0
    }
476
477
0
    code = check_psc_function(i_ctx_p, proc, 0, NULL, &size, AllowRepeat);
478
0
    if (code < 0)
479
0
        goto fail;
480
0
    ops = gs_alloc_string(mem, size + 1, "gs_build_function_4(ops)");
481
0
    if (ops == 0) {
482
0
        code = gs_note_error(gs_error_VMerror);
483
0
        goto fail;
484
0
    }
485
0
    size = 0;
486
0
    check_psc_function(i_ctx_p, proc, 0, ops, &size, AllowRepeat); /* can't fail */
487
0
    ops[size] = PtCr_return;
488
0
    params.ops.data = ops;
489
0
    params.ops.size = size + 1;
490
0
    code = gs_function_PtCr_init(ppfn, &params, mem);
491
0
    if (code >= 0)
492
0
        return 0;
493
    /* free_params will free the ops string */
494
0
fail:
495
0
    gs_function_PtCr_free_params(&params, mem);
496
0
    return code;
497
0
}
498
499
int make_type4_function(i_ctx_t * i_ctx_p, ref *arr, ref *pproc, gs_function_t **func)
500
1.28k
{
501
1.28k
    int code, size, num_components, CIESubst;
502
1.28k
    byte *ops;
503
1.28k
    gs_function_PtCr_params_t params;
504
1.28k
    float *ptr;
505
1.28k
    ref alternatespace, *palternatespace = &alternatespace;
506
1.28k
    PS_colour_space_t *space, *altspace;
507
1.28k
    int AllowRepeat = 1; /* Default to permitting Repeat, devices which can't handle it implement the spec_op */
508
509
1.28k
    code = get_space_object(i_ctx_p, arr, &space);
510
1.28k
    if (code < 0)
511
0
        return code;
512
1.28k
    if (!space->alternateproc)
513
0
        return gs_error_typecheck;
514
1.28k
    code = space->alternateproc(i_ctx_p, arr, &palternatespace, &CIESubst);
515
1.28k
    if (code < 0)
516
0
        return code;
517
1.28k
    code = get_space_object(i_ctx_p, palternatespace, &altspace);
518
1.28k
    if (code < 0)
519
0
        return code;
520
521
1.28k
    code = space->numcomponents(i_ctx_p, arr, &num_components);
522
1.28k
    if (code < 0)
523
0
        return code;
524
1.28k
    ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Domain)");
525
1.28k
    if (!ptr)
526
0
        return gs_error_VMerror;
527
1.28k
    code = space->domain(i_ctx_p, arr, ptr);
528
1.28k
    if (code < 0) {
529
0
        gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
530
0
        return code;
531
0
    }
532
1.28k
    params.Domain = ptr;
533
1.28k
    params.m = num_components;
534
535
1.28k
    code = altspace->numcomponents(i_ctx_p, &alternatespace, &num_components);
536
1.28k
    if (code < 0) {
537
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
538
0
        return code;
539
0
    }
540
1.28k
    ptr = (float *)gs_alloc_byte_array(imemory, num_components * 2, sizeof(float), "make_type4_function(Range)");
541
1.28k
    if (!ptr) {
542
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Domain)");
543
0
        return gs_error_VMerror;
544
0
    }
545
1.28k
    code = altspace->range(i_ctx_p, &alternatespace, ptr);
546
1.28k
    if (code < 0) {
547
0
        gs_free_const_object(imemory, ptr, "make_type4_function(Domain)");
548
0
        gs_free_const_object(imemory, params.Domain, "make_type4_function(Range)");
549
0
        return code;
550
0
    }
551
1.28k
    params.Range = ptr;
552
1.28k
    params.n = num_components;
553
554
1.28k
    params.ops.data = 0;  /* in case of failure, see gs_function_PtCr_free_params */
555
1.28k
    params.ops.size = 0;  /* ditto */
556
1.28k
    size = 0;
557
558
    /* Check if the device allows the use of repeat in functions */
559
    /* We can't handle 'repeat' with pdfwrite since it emits FunctionType 4 */
560
1.28k
    {
561
1.28k
        char data[] = {"AllowPSRepeatFunctions"};
562
1.28k
        dev_param_req_t request;
563
1.28k
        gs_c_param_list list;
564
565
1.28k
        gs_c_param_list_write(&list, i_ctx_p->pgs->device->memory);
566
        /* Stuff the data into a structure for passing to the spec_op */
567
1.28k
        request.Param = data;
568
1.28k
        request.list = &list;
569
1.28k
        code = dev_proc(i_ctx_p->pgs->device, dev_spec_op)(i_ctx_p->pgs->device, gxdso_get_dev_param, &request, sizeof(dev_param_req_t));
570
1.28k
        if (code < 0 && code != gs_error_undefined) {
571
0
            gs_c_param_list_release(&list);
572
0
            return code;
573
0
        }
574
1.28k
        gs_c_param_list_read(&list);
575
1.28k
        code = param_read_bool((gs_param_list *)&list,
576
1.28k
            "AllowPSRepeatFunctions",
577
1.28k
            &AllowRepeat);
578
1.28k
        gs_c_param_list_release(&list);
579
1.28k
        if (code < 0)
580
0
            return code;
581
1.28k
    }
582
583
1.28k
    code = check_psc_function(i_ctx_p, (const ref *)pproc, 0, NULL, &size, AllowRepeat);
584
1.28k
    if (code < 0) {
585
69
        gs_function_PtCr_free_params(&params, imemory);
586
69
        return code;
587
69
    }
588
1.21k
    ops = gs_alloc_string(imemory, size + 1, "make_type4_function(ops)");
589
1.21k
    size = 0;
590
1.21k
    check_psc_function(i_ctx_p, (const ref *)pproc, 0, ops, &size, AllowRepeat); /* can't fail */
591
1.21k
    ops[size] = PtCr_return;
592
1.21k
    params.ops.data = ops;
593
1.21k
    params.ops.size = size + 1;
594
1.21k
    code = gs_function_PtCr_init(func, &params, imemory);
595
1.21k
    if (code < 0)
596
0
        gs_function_PtCr_free_params(&params, imemory);
597
598
1.21k
    return code;
599
1.28k
}