Coverage Report

Created: 2025-04-22 06:20

/src/libspectre/ghostscript/base/gscparam.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2020 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
/* Default implementation of parameter lists */
18
#include "memory_.h"
19
#include "string_.h"
20
#include "gx.h"
21
#include "gserrors.h"
22
#include "gsparam.h"
23
#include "gsstruct.h"
24
25
/* Forward references */
26
typedef union c_param_value_s {
27
    GS_PARAM_VALUE_UNION(gs_c_param_list);
28
} gs_c_param_value;
29
/*typedef struct gs_c_param_s gs_c_param; *//* in gsparam.h */
30
31
/* Define the GC type for a parameter list. */
32
private_st_c_param_list();
33
34
/* Lengths corresponding to various gs_param_type_xxx types */
35
const byte gs_param_type_sizes[] = {
36
    GS_PARAM_TYPE_SIZES(sizeof(gs_c_param_list))
37
};
38
39
/* Lengths of *actual* data-containing type pointed to or contained by gs_param_type_xxx's */
40
const byte gs_param_type_base_sizes[] = {
41
    GS_PARAM_TYPE_BASE_SIZES(0)
42
};
43
44
/*
45
 * Define a parameter list element.  We use gs_param_type_any to identify
46
 * elements that have been requested but not yet written.  The reading
47
 * procedures must recognize such elements as undefined, and ignore them.
48
 */
49
struct gs_c_param_s {
50
    gs_c_param *next;
51
    gs_param_key_t key;
52
    bool free_key;
53
    gs_c_param_value value;
54
    gs_param_type type;
55
    void *alternate_typed_data;
56
};
57
58
/* GC descriptor and procedures */
59
gs_private_st_composite(st_c_param, gs_c_param, "gs_c_param",
60
                        c_param_enum_ptrs, c_param_reloc_ptrs);
61
36.8k
ENUM_PTRS_WITH(c_param_enum_ptrs, gs_c_param *param) {
62
14.7k
    index -= 3;
63
14.7k
    switch (param->type) {
64
        /* Only the aggregate types are handled specially. */
65
0
    case gs_param_type_dict:
66
0
    case gs_param_type_dict_int_keys:
67
0
    case gs_param_type_array:
68
0
        return ENUM_USING(st_c_param_list, &param->value.d,
69
0
                          sizeof(param->value.d), index);
70
14.7k
    default: {
71
14.7k
        gs_param_typed_value value;
72
73
14.7k
        value.value = *(const gs_param_value *)&param->value;
74
14.7k
        value.type = param->type;
75
14.7k
        return gs_param_typed_value_enum_ptrs(mem, &value, sizeof(value), index,
76
14.7k
                                              pep, NULL, gcst);
77
0
    }
78
14.7k
    }
79
14.7k
}
80
7.37k
case 0: return ENUM_OBJ(param->next);
81
7.37k
case 1: return ENUM_OBJ(param->alternate_typed_data);
82
7.37k
case 2:
83
7.37k
    if (!param->key.persistent) {
84
7.37k
        gs_const_string key;
85
86
7.37k
        key.data = param->key.data;
87
7.37k
        key.size = param->key.size;
88
7.37k
        return ENUM_STRING(&key);
89
7.37k
    } else
90
0
        return ENUM_OBJ(0);  /* keep going */
91
36.8k
ENUM_PTRS_END
92
7.37k
RELOC_PTRS_WITH(c_param_reloc_ptrs, gs_c_param *param) {
93
7.37k
    RELOC_VAR(param->next);
94
7.37k
    RELOC_VAR(param->alternate_typed_data);
95
7.37k
    if (!param->key.persistent) {
96
7.37k
        gs_const_string key;
97
98
7.37k
        key.data = param->key.data;
99
7.37k
        key.size = param->key.size;
100
7.37k
        RELOC_CONST_STRING_VAR(key);
101
7.37k
        param->key.data = key.data;
102
7.37k
    }
103
7.37k
    switch (param->type) {
104
        /* Only the aggregate types are handled specially. */
105
0
    case gs_param_type_dict:
106
0
    case gs_param_type_dict_int_keys:
107
0
    case gs_param_type_array:
108
0
        RELOC_USING(st_c_param_list, &param->value.d, sizeof(param->value.d));
109
0
        break;
110
7.37k
    default: {
111
7.37k
        gs_param_typed_value value;
112
113
7.37k
        value.value = *(gs_param_value *)&param->value;
114
7.37k
        value.type = param->type;
115
7.37k
        gs_param_typed_value_reloc_ptrs(&value, sizeof(value), NULL, gcst);
116
7.37k
        *(gs_param_value *)&param->value = value.value;
117
7.37k
    }
118
7.37k
    }
119
7.37k
}
120
7.37k
RELOC_PTRS_END
121
122
/* ---------------- Utilities ---------------- */
123
124
gs_c_param_list *
125
gs_c_param_list_alloc(gs_memory_t *mem, client_name_t cname)
126
1.08k
{
127
1.08k
    return gs_alloc_struct(mem, gs_c_param_list, &st_c_param_list, cname);
128
1.08k
}
129
130
static gs_c_param *
131
c_param_find(const gs_c_param_list *plist, gs_param_name pkey, bool any)
132
15.6k
{
133
15.6k
    gs_c_param *pparam = plist->head;
134
15.6k
    uint len = strlen(pkey);
135
136
57.2k
    for (; pparam != 0; pparam = pparam->next)
137
44.2k
        if (pparam->key.size == len && !memcmp(pparam->key.data, pkey, len))
138
2.60k
            return (pparam->type != gs_param_type_any || any ? pparam : 0);
139
13.0k
    return 0;
140
15.6k
}
141
142
/* ---------------- Writing parameters to a list ---------------- */
143
144
static param_proc_begin_xmit_collection(c_param_begin_write_collection);
145
static param_proc_end_xmit_collection(c_param_end_write_collection);
146
static param_proc_xmit_typed(c_param_write_typed);
147
static param_proc_request(c_param_request);
148
static param_proc_requested(c_param_requested);
149
static const gs_param_list_procs c_write_procs =
150
{
151
    c_param_write_typed,
152
    c_param_begin_write_collection,
153
    c_param_end_write_collection,
154
    NULL,     /* get_next_key */
155
    c_param_request,
156
    c_param_requested
157
};
158
159
/* Initialize a list for writing. */
160
void
161
gs_c_param_list_write(gs_c_param_list * plist, gs_memory_t * mem)
162
1.95k
{
163
1.95k
    plist->memory = mem;
164
1.95k
    plist->head = 0;
165
1.95k
    plist->target = 0;    /* not used for writing */
166
1.95k
    plist->count = 0;
167
1.95k
    plist->any_requested = false;
168
1.95k
    plist->persistent_keys = true;
169
1.95k
    gs_c_param_list_write_more(plist);
170
1.95k
}
171
172
/* Set the target of a list.  Only relevant for reading. */
173
void
174
gs_c_param_list_set_target(gs_c_param_list *plist, gs_param_list *target)
175
868
{
176
868
    plist->target = target;
177
868
}
178
179
/* Re-enable a list for writing, without clearing it. */
180
/* gs_c_param_list_write must have been called previously. */
181
void
182
gs_c_param_list_write_more(gs_c_param_list * plist)
183
1.95k
{
184
1.95k
    plist->procs = &c_write_procs;
185
1.95k
    plist->coll_type = gs_param_collection_dict_any;
186
1.95k
}
187
188
/* Release a list. */
189
void
190
gs_c_param_list_release(gs_c_param_list * plist)
191
1.08k
{
192
1.08k
    gs_memory_t *mem = plist->memory;
193
1.08k
    gs_c_param *pparam;
194
195
3.69k
    while ((pparam = plist->head) != 0) {
196
2.60k
        gs_c_param *next = pparam->next;
197
198
2.60k
        switch (pparam->type) {
199
0
            case gs_param_type_dict:
200
0
            case gs_param_type_dict_int_keys:
201
0
            case gs_param_type_array:
202
0
                gs_c_param_list_release(&pparam->value.d);
203
0
                break;
204
0
            case gs_param_type_string:
205
0
            case gs_param_type_name:
206
0
            case gs_param_type_int_array:
207
0
            case gs_param_type_float_array:
208
0
            case gs_param_type_string_array:
209
0
            case gs_param_type_name_array:
210
0
                if (!pparam->value.s.persistent)
211
0
                    gs_free_const_object(mem, pparam->value.s.data,
212
0
                                         "gs_c_param_list_release data");
213
0
                break;
214
2.60k
            default:
215
2.60k
                break;
216
2.60k
        }
217
2.60k
        if (pparam->free_key) {
218
            /* We allocated this, so we must free it. */
219
0
            gs_free_const_string(mem, pparam->key.data, pparam->key.size,
220
0
                                 "gs_c_param_list_release key");
221
0
        }
222
2.60k
        gs_free_object(mem, pparam->alternate_typed_data,
223
2.60k
                       "gs_c_param_list_release alternate data");
224
2.60k
        gs_free_object(mem, pparam,
225
2.60k
                       "gs_c_param_list_release entry");
226
2.60k
        plist->head = next;
227
2.60k
        plist->count--;
228
2.60k
    }
229
1.08k
}
230
231
/* Add an entry to a list.  Doesn't set: value, type, plist->head. */
232
static gs_c_param *
233
c_param_add(gs_c_param_list * plist, gs_param_name pkey)
234
6.29k
{
235
6.29k
    gs_c_param *pparam =
236
6.29k
        gs_alloc_struct(plist->memory, gs_c_param, &st_c_param,
237
6.29k
                        "c_param_add entry");
238
6.29k
    uint len;
239
240
6.29k
    if ((pparam == NULL) || (pkey == NULL))
241
0
        return NULL;
242
243
6.29k
    len = strlen(pkey);
244
6.29k
    pparam->next = plist->head;
245
6.29k
    if (!plist->persistent_keys) {
246
        /* We must copy the key. */
247
3.68k
        byte *str = gs_alloc_string(plist->memory, len, "c_param_add key");
248
249
3.68k
        if (str == 0) {
250
0
            gs_free_object(plist->memory, pparam, "c_param_add entry");
251
0
            return 0;
252
0
        }
253
3.68k
        memcpy(str, pkey, len);
254
3.68k
        pparam->key.data = str;
255
3.68k
        pparam->key.persistent = false; /* we will free it */
256
3.68k
        pparam->free_key = true;
257
3.68k
    } else {
258
2.60k
        pparam->key.data = (const byte *)pkey;
259
2.60k
        pparam->key.persistent = true;
260
2.60k
        pparam->free_key = false;
261
2.60k
    }
262
6.29k
    pparam->key.size = len;
263
6.29k
    pparam->alternate_typed_data = 0;
264
6.29k
    return pparam;
265
6.29k
}
266
267
/*  Write a dynamically typed parameter to a list. */
268
static int
269
c_param_write(gs_c_param_list * plist, gs_param_name pkey, void *pvalue,
270
              gs_param_type type)
271
6.29k
{
272
6.29k
    unsigned top_level_sizeof = 0;
273
6.29k
    unsigned second_level_sizeof = 0;
274
6.29k
    gs_c_param *pparam = c_param_add(plist, pkey);
275
276
6.29k
    if (pparam == 0)
277
0
        return_error(gs_error_VMerror);
278
6.29k
    memcpy(&pparam->value, pvalue, gs_param_type_sizes[(int)type]);
279
6.29k
    pparam->type = type;
280
281
    /* Need deeper copies of data if it's not persistent */
282
6.29k
    switch (type) {
283
0
            gs_param_string const *curr_string;
284
0
            gs_param_string const *end_string;
285
286
0
        case gs_param_type_string_array:
287
0
        case gs_param_type_name_array:
288
            /* Determine how much mem needed to hold actual string data */
289
0
            curr_string = pparam->value.sa.data;
290
0
            end_string = curr_string + pparam->value.sa.size;
291
0
            for (; curr_string < end_string; ++curr_string)
292
0
                if (!curr_string->persistent)
293
0
                    second_level_sizeof += curr_string->size;
294
            /* fall thru */
295
296
0
        case gs_param_type_string:
297
0
        case gs_param_type_name:
298
1.73k
        case gs_param_type_int_array:
299
1.73k
        case gs_param_type_float_array:
300
1.73k
            if (!pparam->value.s.persistent) { /* Allocate & copy object pointed to by array or string */
301
1.73k
                byte *top_level_memory = NULL;
302
303
1.73k
                top_level_sizeof =
304
1.73k
                    pparam->value.s.size * gs_param_type_base_sizes[type];
305
1.73k
                if (top_level_sizeof + second_level_sizeof > 0) {
306
1.73k
                    top_level_memory =
307
1.73k
                        gs_alloc_bytes_immovable(plist->memory,
308
1.73k
                                     top_level_sizeof + second_level_sizeof,
309
1.73k
                                             "c_param_write data");
310
1.73k
                    if (top_level_memory == 0) {
311
0
                        if (pparam->key.persistent == false) {
312
0
                            gs_free_string(plist->memory, (byte *)(pparam->key.data),
313
0
                                strlen((const char *)(pparam->key.data)), "c_param_add key");
314
0
                        }
315
0
                        gs_free_object(plist->memory, pparam, "c_param_write entry");
316
0
                        return_error(gs_error_VMerror);
317
0
                    }
318
1.73k
                    memcpy(top_level_memory, pparam->value.s.data, top_level_sizeof);
319
1.73k
                }
320
1.73k
                pparam->value.s.data = top_level_memory;
321
322
                /* String/name arrays need to copy actual str data */
323
324
1.73k
                if (second_level_sizeof > 0) {
325
0
                    byte *second_level_memory =
326
0
                    top_level_memory + top_level_sizeof;
327
328
0
                    curr_string = pparam->value.sa.data;
329
0
                    end_string = curr_string + pparam->value.sa.size;
330
0
                    for (; curr_string < end_string; ++curr_string)
331
0
                        if (!curr_string->persistent) {
332
0
                            memcpy(second_level_memory,
333
0
                                   curr_string->data, curr_string->size);
334
0
                            ((gs_param_string *) curr_string)->data
335
0
                                = second_level_memory;
336
0
                            second_level_memory += curr_string->size;
337
0
                        }
338
0
                }
339
1.73k
            }
340
1.73k
            break;
341
4.55k
        default:
342
4.55k
            break;
343
6.29k
    }
344
345
6.29k
    plist->head = pparam;
346
6.29k
    plist->count++;
347
6.29k
    return 0;
348
6.29k
}
349
350
/* Individual writing routines. */
351
static int
352
c_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey,
353
               gs_param_dict * pvalue, gs_param_collection_type_t coll_type)
354
0
{
355
0
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
356
0
    gs_c_param_list *dlist =
357
0
        gs_c_param_list_alloc(cplist->memory,
358
0
                              "c_param_begin_write_collection");
359
360
0
    if (dlist == 0)
361
0
        return_error(gs_error_VMerror);
362
0
    gs_c_param_list_write(dlist, cplist->memory);
363
0
    dlist->coll_type = coll_type;
364
0
    pvalue->list = (gs_param_list *) dlist;
365
0
    return 0;
366
0
}
367
static int
368
c_param_end_write_collection(gs_param_list * plist, gs_param_name pkey,
369
                             gs_param_dict * pvalue)
370
0
{
371
0
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
372
0
    gs_c_param_list *dlist = (gs_c_param_list *) pvalue->list;
373
0
    int code;
374
375
0
    code = c_param_write(cplist, pkey, pvalue->list,
376
0
                    (dlist->coll_type == gs_param_collection_dict_int_keys ?
377
0
                     gs_param_type_dict_int_keys :
378
0
                     dlist->coll_type == gs_param_collection_array ?
379
0
                     gs_param_type_array : gs_param_type_dict));
380
381
0
    gs_free_object(plist->memory, pvalue->list, "c_param_end_write_collection");
382
0
    pvalue->list = 0;
383
0
    return code;
384
0
}
385
static int
386
c_param_write_typed(gs_param_list * plist, gs_param_name pkey,
387
                    gs_param_typed_value * pvalue)
388
6.29k
{
389
6.29k
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
390
6.29k
    gs_param_collection_type_t coll_type;
391
392
6.29k
    switch (pvalue->type) {
393
0
        case gs_param_type_dict:
394
0
            coll_type = gs_param_collection_dict_any;
395
0
            break;
396
0
        case gs_param_type_dict_int_keys:
397
0
            coll_type = gs_param_collection_dict_int_keys;
398
0
            break;
399
0
        case gs_param_type_array:
400
0
            coll_type = gs_param_collection_array;
401
0
            break;
402
6.29k
        default:
403
6.29k
            return c_param_write(cplist, pkey, &pvalue->value, pvalue->type);
404
6.29k
    }
405
0
    return c_param_begin_write_collection
406
0
        (plist, pkey, &pvalue->value.d, coll_type);
407
6.29k
}
408
409
/* Other procedures */
410
411
static int
412
c_param_request(gs_param_list * plist, gs_param_name pkey)
413
0
{
414
0
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
415
0
    gs_c_param *pparam;
416
417
0
    cplist->any_requested = true;
418
0
    if (c_param_find(cplist, pkey, true))
419
0
        return 0;
420
0
    pparam = c_param_add(cplist, pkey);
421
0
    if (pparam == 0)
422
0
        return_error(gs_error_VMerror);
423
0
    pparam->type = gs_param_type_any; /* mark as undefined */
424
0
    cplist->head = pparam;
425
0
    return 0;
426
0
}
427
428
static int
429
c_param_requested(const gs_param_list * plist, gs_param_name pkey)
430
0
{
431
0
    const gs_c_param_list *const cplist = (const gs_c_param_list *)plist;
432
0
    gs_param_list *target = cplist->target;
433
0
    int code;
434
435
0
    if (!cplist->any_requested)
436
0
        return (target ? param_requested(target, pkey) : -1);
437
0
    if (c_param_find(cplist, pkey, true) != 0)
438
0
        return 1;
439
0
    if (!target)
440
0
        return 0;
441
0
    code = param_requested(target, pkey);
442
0
    return (code < 0 ? 0 : 1);
443
0
}
444
445
/* ---------------- Reading from a list to parameters ---------------- */
446
447
static param_proc_begin_xmit_collection(c_param_begin_read_collection);
448
static param_proc_end_xmit_collection(c_param_end_read_collection);
449
static param_proc_xmit_typed(c_param_read_typed);
450
static param_proc_next_key(c_param_get_next_key);
451
static param_proc_get_policy(c_param_read_get_policy);
452
static param_proc_signal_error(c_param_read_signal_error);
453
static param_proc_commit(c_param_read_commit);
454
static const gs_param_list_procs c_read_procs =
455
{
456
    c_param_read_typed,
457
    c_param_begin_read_collection,
458
    c_param_end_read_collection,
459
    c_param_get_next_key,
460
    NULL,     /* request, N/A */
461
    NULL,     /* requested, N/A */
462
    c_param_read_get_policy,
463
    c_param_read_signal_error,
464
    c_param_read_commit
465
};
466
467
/* Switch a list from writing to reading. */
468
void
469
gs_c_param_list_read(gs_c_param_list * plist)
470
868
{
471
868
    plist->procs = &c_read_procs;
472
868
}
473
474
/* Generic routine for reading a parameter from a list. */
475
476
static int
477
c_param_read_typed(gs_param_list * plist, gs_param_name pkey,
478
                   gs_param_typed_value * pvalue)
479
13.8k
{
480
13.8k
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
481
13.8k
    gs_param_type req_type = pvalue->type;
482
13.8k
    gs_c_param *pparam = c_param_find(cplist, pkey, false);
483
13.8k
    int code;
484
485
13.8k
    if (pparam == 0)
486
11.2k
        return (cplist->target ?
487
11.2k
                param_read_typed(cplist->target, pkey, pvalue) : 1);
488
2.60k
    pvalue->type = pparam->type;
489
2.60k
    switch (pvalue->type) {
490
0
        case gs_param_type_dict:
491
0
        case gs_param_type_dict_int_keys:
492
0
        case gs_param_type_array:
493
0
            gs_c_param_list_read(&pparam->value.d);
494
0
            pvalue->value.d.list = (gs_param_list *) & pparam->value.d;
495
0
            pvalue->value.d.size = pparam->value.d.count;
496
0
            return 0;
497
2.60k
        default:
498
2.60k
            break;
499
2.60k
    }
500
2.60k
    memcpy(&pvalue->value, &pparam->value,
501
2.60k
           gs_param_type_sizes[(int)pparam->type]);
502
2.60k
    code = param_coerce_typed(pvalue, req_type, NULL);
503
/****** SHOULD LET param_coerce_typed DO THIS ******/
504
2.60k
    if (code == gs_error_typecheck &&
505
2.60k
        req_type == gs_param_type_float_array &&
506
2.60k
        pvalue->type == gs_param_type_int_array
507
2.60k
        ) {
508
        /* Convert int array to float dest */
509
0
        gs_param_float_array fa;
510
0
        int element;
511
512
0
        fa.size = pparam->value.ia.size;
513
0
        fa.persistent = false;
514
515
0
        if (pparam->alternate_typed_data == 0) {
516
0
            if ((pparam->alternate_typed_data
517
0
                 = (void *)gs_alloc_bytes_immovable(cplist->memory,
518
0
                                                    fa.size * sizeof(float),
519
0
                             "gs_c_param_read alternate float array")) == 0)
520
0
                      return_error(gs_error_VMerror);
521
522
0
            for (element = 0; element < fa.size; ++element)
523
0
                ((float *)(pparam->alternate_typed_data))[element]
524
0
                    = (float)pparam->value.ia.data[element];
525
0
        }
526
0
        fa.data = (float *)pparam->alternate_typed_data;
527
528
0
        pvalue->value.fa = fa;
529
0
        pvalue->type = req_type;
530
0
        return 0;
531
0
    }
532
2.60k
    return code;
533
2.60k
}
534
535
/* Individual reading routines. */
536
static int
537
c_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey,
538
               gs_param_dict * pvalue, gs_param_collection_type_t coll_type)
539
1.73k
{
540
1.73k
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
541
1.73k
    gs_c_param *pparam = c_param_find(cplist, pkey, false);
542
543
1.73k
    if (pparam == 0)
544
1.73k
        return
545
1.73k
            (cplist->target ?
546
1.73k
             param_begin_read_collection(cplist->target,
547
1.73k
                                         pkey, pvalue, coll_type) :
548
1.73k
             1);
549
0
    switch (pparam->type) {
550
0
        case gs_param_type_dict:
551
0
            if (coll_type != gs_param_collection_dict_any)
552
0
                return_error(gs_error_typecheck);
553
0
            break;
554
0
        case gs_param_type_dict_int_keys:
555
0
            if (coll_type == gs_param_collection_array)
556
0
                return_error(gs_error_typecheck);
557
0
            break;
558
0
        case gs_param_type_array:
559
0
            break;
560
0
        default:
561
0
            return_error(gs_error_typecheck);
562
0
    }
563
0
    gs_c_param_list_read(&pparam->value.d);
564
0
    pvalue->list = (gs_param_list *) & pparam->value.d;
565
0
    pvalue->size = pparam->value.d.count;
566
0
    return 0;
567
0
}
568
static int
569
c_param_end_read_collection(gs_param_list * plist, gs_param_name pkey,
570
                            gs_param_dict * pvalue)
571
0
{
572
0
    return 0;
573
0
}
574
575
/* Other procedures */
576
static int      /* ret 0 ok, 1 if EOF, or -ve err */
577
c_param_get_next_key(gs_param_list * plist, gs_param_enumerator_t * penum,
578
                     gs_param_key_t * key)
579
0
{
580
0
    gs_c_param_list *const cplist = (gs_c_param_list *)plist;
581
0
    gs_c_param *pparam =
582
0
    (penum->pvoid ? ((gs_c_param *) (penum->pvoid))->next :
583
0
     cplist->head);
584
585
0
    if (pparam == 0)
586
0
        return 1;
587
0
    penum->pvoid = pparam;
588
0
    *key = pparam->key;
589
0
    return 0;
590
0
}
591
static int
592
c_param_read_get_policy(gs_param_list * plist, gs_param_name pkey)
593
0
{
594
0
    return gs_param_policy_ignore;
595
0
}
596
static int
597
c_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code)
598
0
{
599
0
    return code;
600
0
}
601
static int
602
c_param_read_commit(gs_param_list * plist)
603
0
{
604
0
    return 0;
605
0
}