~ubuntu-branches/ubuntu/jaunty/ghostscript/jaunty-updates

« back to all changes in this revision

Viewing changes to psi/iparam.c

  • Committer: Bazaar Package Importer
  • Author(s): Till Kamppeter
  • Date: 2009-01-20 16:40:45 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090120164045-lnfhi0n30o5lwhwa
Tags: 8.64.dfsg.1~svn9377-0ubuntu1
* New upstream release (SVN rev 9377)
   o Fixes many bugs concerning PDF rendering, to make the PDF printing
     workflow correctly working.
   o Fixes long-standing bugs in many drivers, like input paper tray and
     duplex options not working for the built-in PCL 4, 5, 5c, 5e, and
     6/XL drivers, PDF input not working for bjc600, bjc800, and cups
     output devices, several options not working and uninitialized
     memory with cups output device.
   o Merged nearly all patches of the Ubuntu and Debian packages upstream.
   o Fixes LP: #317810, LP: #314439, LP: #314018.
* debian/patches/03_libpaper_support.dpatch,
  debian/patches/11_gs-cjk_font_glyph_handling_fix.dpatch,
  debian/patches/12_gs-cjk_vertical_writing_metrics_fix.dpatch,
  debian/patches/13_gs-cjk_cjkps_examples.dpatch,
  debian/patches/20_bbox_segv_fix.dpatch,
  debian/patches/21_brother_7x0_gdi_fix.dpatch,
  debian/patches/22_epsn_margin_workaround.dpatch,
  debian/patches/24_gs_man_fix.dpatch,
  debian/patches/25_toolbin_insecure_tmp_usage_fix.dpatch,
  debian/patches/26_assorted_script_fixes.dpatch,
  debian/patches/29_gs_css_fix.dpatch,
  debian/patches/30_ps2pdf_man_improvement.dpatch,
  debian/patches/31_fix-gc-sigbus.dpatch,
  debian/patches/34_ftbfs-on-hurd-fix.dpatch,
  debian/patches/35_disable_libcairo.dpatch,
  debian/patches/38_pxl-duplex.dpatch,
  debian/patches/39_pxl-resolution.dpatch,
  debian/patches/42_gs-init-ps-delaybind-fix.dpatch,
  debian/patches/45_bjc600-bjc800-pdf-input.dpatch,
  debian/patches/48_cups-output-device-pdf-duplex-uninitialized-memory-fix.dpatch,
  debian/patches/50_lips4-floating-point-exception.dpatch,
  debian/patches/52_cups-device-logging.dpatch,
  debian/patches/55_pcl-input-slot-fix.dpatch,
  debian/patches/57_pxl-input-slot-fix.dpatch,
  debian/patches/60_pxl-cups-driver-pdf.dpatch,
  debian/patches/62_onebitcmyk-pdf.dpatch,
  debian/patches/65_too-big-temp-files-1.dpatch,
  debian/patches/67_too-big-temp-files-2.dpatch,
  debian/patches/70_take-into-account-data-in-stream-buffer-before-refill.dpatch:
  Removed, applied upstream.
* debian/patches/01_docdir_fix_for_debian.dpatch,
  debian/patches/02_gs_man_fix_debian.dpatch,
  debian/patches/01_docdir-fix-for-debian.dpatch,
  debian/patches/02_docdir-fix-for-debian.dpatch: Renamed patches to
  make merging with Debian easier.
* debian/patches/32_improve-handling-of-media-size-changes-from-gv.dpatch, 
  debian/patches/33_bad-params-to-xinitimage-on-large-bitmaps.dpatch:
  regenerated for new source directory structure.
* debian/rules: Corrected paths to remove cidfmap (it is in Resource/Init/
  in GS 8.64) and to install headers (source paths are psi/ and base/ now).
* debian/rules: Remove all fontmaps, as DeFoMa replaces them.
* debian/local/pdftoraster/pdftoraster.c,
  debian/local/pdftoraster/pdftoraster.convs, debian/rules: Removed
  added pdftoraster filter and use the one which comes with Ghostscript.
* debian/ghostscript.links: s/8.63/8.64/

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2001-2006 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, modified
 
8
   or distributed except as expressly authorized under the terms of that
 
9
   license.  Refer to licensing information at http://www.artifex.com/
 
10
   or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
 
11
   San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
 
12
*/
 
13
 
 
14
/* $Id: iparam.c 9043 2008-08-28 22:48:19Z giles $ */
 
15
/* Interpreter implementations of parameter dictionaries */
 
16
#include "memory_.h"
 
17
#include "string_.h"
 
18
#include "ghost.h"
 
19
#include "ierrors.h"
 
20
#include "oper.h"               /* for check_type */
 
21
#include "opcheck.h"
 
22
#include "ialloc.h"
 
23
#include "idict.h"
 
24
#include "imemory.h"            /* for iutil.h */
 
25
#include "iname.h"
 
26
#include "istack.h"
 
27
#include "iparam.h"
 
28
#include "iutil.h"              /* for num_params */
 
29
#include "ivmspace.h"
 
30
#include "store.h"
 
31
#include "gsstruct.h"           /* for st_bytes */
 
32
 
 
33
/* ================ Utilities ================ */
 
34
 
 
35
/* Convert a key to a ref. */
 
36
static int
 
37
ref_param_key(const iparam_list * plist, gs_param_name pkey, ref * pkref)
 
38
{
 
39
    if (plist->int_keys) {
 
40
        long key;
 
41
 
 
42
        if (sscanf(pkey, "%ld", &key) != 1)
 
43
            return_error(e_rangecheck);
 
44
        make_int(pkref, key);
 
45
        return 0;
 
46
    } else
 
47
        return name_ref(plist->memory, (const byte *)pkey, strlen(pkey), pkref, 0);
 
48
}
 
49
 
 
50
/* Fill in a gs_param_key_t from a name or int ref. */
 
51
static int
 
52
ref_to_key(const ref * pref, gs_param_key_t * key, iparam_list *plist)
 
53
{
 
54
    if (r_has_type(pref, t_name)) {
 
55
        ref nref;
 
56
 
 
57
        name_string_ref(plist->memory, pref, &nref);
 
58
        key->data = nref.value.const_bytes;
 
59
        key->size = r_size(&nref);
 
60
        key->persistent = false; /* names may be freed */
 
61
    } else if (r_has_type(pref, t_integer)) {
 
62
        char istr[sizeof(long) * 8 / 3 + 2];
 
63
        int len;
 
64
        byte *buf;
 
65
 
 
66
        sprintf(istr, "%ld", pref->value.intval);
 
67
        len = strlen(istr);
 
68
        /* GC will take care of freeing this: */
 
69
        buf = gs_alloc_string(plist->memory, len, "ref_to_key");
 
70
        if (!buf)
 
71
            return_error(e_VMerror);
 
72
        key->data = buf;
 
73
        key->size = len;
 
74
        key->persistent = true;
 
75
    } else
 
76
        return_error(e_typecheck);
 
77
    return 0;
 
78
}
 
79
 
 
80
/* ================ Writing parameters to refs ================ */
 
81
 
 
82
/* Forward references */
 
83
static int array_new_indexed_plist_write(dict_param_list *plist,
 
84
                                          ref *parray, const ref *pwanted,
 
85
                                          gs_ref_memory_t *imem);
 
86
 
 
87
/* ---------------- Generic writing procedures ---------------- */
 
88
 
 
89
static param_proc_begin_xmit_collection(ref_param_begin_write_collection);
 
90
static param_proc_end_xmit_collection(ref_param_end_write_collection);
 
91
static param_proc_xmit_typed(ref_param_write_typed);
 
92
static param_proc_next_key(ref_param_get_next_key);
 
93
static param_proc_requested(ref_param_requested);
 
94
static const gs_param_list_procs ref_write_procs =
 
95
{
 
96
    ref_param_write_typed,
 
97
    ref_param_begin_write_collection,
 
98
    ref_param_end_write_collection,
 
99
    ref_param_get_next_key,
 
100
    NULL,                       /* request */
 
101
    ref_param_requested
 
102
};
 
103
static int ref_array_param_requested(const iparam_list *, gs_param_name,
 
104
                                      ref *, uint, client_name_t);
 
105
static int ref_param_write(iparam_list *, gs_param_name, const ref *);
 
106
static int ref_param_write_string_value(ref *, const gs_param_string *,
 
107
                                         gs_ref_memory_t *);
 
108
static int ref_param_write_name_value(const gs_memory_t *mem, ref *, const gs_param_string *);
 
109
static int
 
110
ref_param_make_int(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
 
111
{
 
112
    make_tav(pe, t_integer, imemory_new_mask(imem), intval,
 
113
             ((const gs_param_int_array *)pvalue)->data[i]);
 
114
    return 0;
 
115
}
 
116
static int
 
117
ref_param_make_float(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
 
118
{
 
119
    make_tav(pe, t_real, imemory_new_mask(imem), realval,
 
120
             ((const gs_param_float_array *)pvalue)->data[i]);
 
121
    return 0;
 
122
}
 
123
static int
 
124
ref_param_make_string(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
 
125
{
 
126
    return ref_param_write_string_value(pe,
 
127
                         &((const gs_param_string_array *)pvalue)->data[i],
 
128
                                        imem);
 
129
}
 
130
static int
 
131
ref_param_make_name(ref * pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
 
132
{
 
133
    return ref_param_write_name_value((const gs_memory_t *)imem, pe,
 
134
                         &((const gs_param_string_array *)pvalue)->data[i]);
 
135
}
 
136
static int
 
137
ref_param_write_typed_array(gs_param_list * plist, gs_param_name pkey,
 
138
                            void *pvalue, uint count,
 
139
                            int (*make)(ref *, const void *, uint,
 
140
                                        gs_ref_memory_t *))
 
141
{
 
142
    iparam_list *const iplist = (iparam_list *) plist;
 
143
    ref value;
 
144
    uint i;
 
145
    ref *pe;
 
146
    int code;
 
147
 
 
148
    if ((code = ref_array_param_requested(iplist, pkey, &value, count,
 
149
                                       "ref_param_write_typed_array")) <= 0)
 
150
        return code;
 
151
    for (i = 0, pe = value.value.refs; i < count; ++i, ++pe)
 
152
        if ((code = (*make) (pe, pvalue, i, iplist->ref_memory)) < 0)
 
153
            return code;
 
154
    return ref_param_write(iplist, pkey, &value);
 
155
}
 
156
static int
 
157
ref_param_begin_write_collection(gs_param_list * plist, gs_param_name pkey,
 
158
                                 gs_param_dict * pvalue,
 
159
                                 gs_param_collection_type_t coll_type)
 
160
{
 
161
    iparam_list *const iplist = (iparam_list *) plist;
 
162
    gs_ref_memory_t *imem = iplist->ref_memory;
 
163
    dict_param_list *dlist = (dict_param_list *)
 
164
        gs_alloc_bytes(plist->memory, size_of(dict_param_list),
 
165
                       "ref_param_begin_write_collection");
 
166
    int code;
 
167
 
 
168
    if (dlist == 0)
 
169
        return_error(e_VMerror);
 
170
    if (coll_type != gs_param_collection_array) {
 
171
        ref dref;
 
172
 
 
173
        code = dict_alloc(imem, pvalue->size, &dref);
 
174
        if (code >= 0) {
 
175
            code = dict_param_list_write(dlist, &dref, NULL, imem);
 
176
            dlist->int_keys = coll_type == gs_param_collection_dict_int_keys;
 
177
        }
 
178
    } else {
 
179
        ref aref;
 
180
 
 
181
        code = gs_alloc_ref_array(imem, &aref, a_all, pvalue->size,
 
182
                                  "ref_param_begin_write_collection");
 
183
        if (code >= 0)
 
184
            code = array_new_indexed_plist_write(dlist, &aref, NULL, imem);
 
185
    }
 
186
    if (code < 0)
 
187
        gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
 
188
    else
 
189
        pvalue->list = (gs_param_list *) dlist;
 
190
    return code;
 
191
}
 
192
static int
 
193
ref_param_end_write_collection(gs_param_list * plist, gs_param_name pkey,
 
194
                               gs_param_dict * pvalue)
 
195
{
 
196
    iparam_list *const iplist = (iparam_list *) plist;
 
197
    int code = ref_param_write(iplist, pkey,
 
198
                               &((dict_param_list *) pvalue->list)->dict);
 
199
 
 
200
    gs_free_object(plist->memory, pvalue->list, "ref_param_end_write_collection");
 
201
    return code;
 
202
}
 
203
static int
 
204
ref_param_write_typed(gs_param_list * plist, gs_param_name pkey,
 
205
                      gs_param_typed_value * pvalue)
 
206
{
 
207
    iparam_list *const iplist = (iparam_list *) plist;
 
208
    ref value;
 
209
    int code = 0;
 
210
 
 
211
    switch (pvalue->type) {
 
212
        case gs_param_type_null:
 
213
            make_null(&value);
 
214
            break;
 
215
        case gs_param_type_bool:
 
216
            make_bool(&value, pvalue->value.b);
 
217
            break;
 
218
        case gs_param_type_int:
 
219
            make_int(&value, pvalue->value.i);
 
220
            break;
 
221
        case gs_param_type_long:
 
222
            make_int(&value, pvalue->value.l);
 
223
            break;
 
224
        case gs_param_type_float:
 
225
            make_real(&value, pvalue->value.f);
 
226
            break;
 
227
        case gs_param_type_string:
 
228
            if (!ref_param_requested(plist, pkey))
 
229
                return 0;
 
230
            code = ref_param_write_string_value(&value, &pvalue->value.s,
 
231
                                                iplist->ref_memory);
 
232
            break;
 
233
        case gs_param_type_name:
 
234
            if (!ref_param_requested(plist, pkey))
 
235
                return 0;
 
236
            code = ref_param_write_name_value(iplist->memory, &value, &pvalue->value.n);
 
237
            break;
 
238
        case gs_param_type_int_array:
 
239
            return ref_param_write_typed_array(plist, pkey, &pvalue->value.ia,
 
240
                                               pvalue->value.ia.size,
 
241
                                               ref_param_make_int);
 
242
        case gs_param_type_float_array:
 
243
            return ref_param_write_typed_array(plist, pkey, &pvalue->value.fa,
 
244
                                               pvalue->value.fa.size,
 
245
                                               ref_param_make_float);
 
246
        case gs_param_type_string_array:
 
247
            return ref_param_write_typed_array(plist, pkey, &pvalue->value.sa,
 
248
                                               pvalue->value.sa.size,
 
249
                                               ref_param_make_string);
 
250
        case gs_param_type_name_array:
 
251
            return ref_param_write_typed_array(plist, pkey, &pvalue->value.na,
 
252
                                               pvalue->value.na.size,
 
253
                                               ref_param_make_name);
 
254
        case gs_param_type_dict:
 
255
        case gs_param_type_dict_int_keys:
 
256
        case gs_param_type_array:
 
257
            return ref_param_begin_write_collection(plist, pkey,
 
258
                                                    &pvalue->value.d,
 
259
              (gs_param_collection_type_t)(pvalue->type - gs_param_type_dict));
 
260
        default:
 
261
            return_error(e_typecheck);
 
262
    }
 
263
    if (code < 0)
 
264
        return code;
 
265
    return ref_param_write(iplist, pkey, &value);
 
266
}
 
267
 
 
268
/* Check whether a given parameter was requested. */
 
269
static int
 
270
ref_param_requested(const gs_param_list * plist, gs_param_name pkey)
 
271
{
 
272
    const iparam_list *const ciplist = (const iparam_list *)plist;
 
273
    ref kref;
 
274
    ref *ignore_value;
 
275
 
 
276
    if (!r_has_type(&ciplist->u.w.wanted, t_dictionary))
 
277
        return -1;
 
278
    if (ref_param_key(ciplist, pkey, &kref) < 0)
 
279
        return -1;              /* catch it later */
 
280
    return (dict_find(&ciplist->u.w.wanted, &kref, &ignore_value) > 0);
 
281
}
 
282
 
 
283
/* Check whether an array parameter is wanted, and allocate it if so. */
 
284
/* Return <0 on error, 0 if not wanted, 1 if wanted. */
 
285
static int
 
286
ref_array_param_requested(const iparam_list *iplist, gs_param_name pkey,
 
287
                          ref *pvalue, uint size, client_name_t cname)
 
288
{
 
289
    int code;
 
290
 
 
291
    if (!ref_param_requested((const gs_param_list *)iplist, pkey))
 
292
        return 0;
 
293
    code = gs_alloc_ref_array(iplist->ref_memory, pvalue, a_all, size, cname);
 
294
    return (code < 0 ? code : 1);
 
295
}
 
296
 
 
297
/* ---------------- Internal routines ---------------- */
 
298
 
 
299
/* Prepare to write a string value. */
 
300
static int
 
301
ref_param_write_string_value(ref * pref, const gs_param_string * pvalue,
 
302
                             gs_ref_memory_t *imem)
 
303
{
 
304
    const byte *pdata = pvalue->data;
 
305
    uint n = pvalue->size;
 
306
 
 
307
    if (pvalue->persistent)
 
308
        make_const_string(pref, a_readonly | avm_foreign, n, pdata);
 
309
    else {
 
310
        byte *pstr = gs_alloc_string((gs_memory_t *)imem, n,
 
311
                                     "ref_param_write_string");
 
312
 
 
313
        if (pstr == 0)
 
314
            return_error(e_VMerror);
 
315
        memcpy(pstr, pdata, n);
 
316
        make_string(pref, a_readonly | imemory_space(imem), n, pstr);
 
317
    }
 
318
    return 0;
 
319
}
 
320
 
 
321
/* Prepare to write a name value. */
 
322
static int
 
323
ref_param_write_name_value(const gs_memory_t *mem, ref * pref, const gs_param_string * pvalue)
 
324
{
 
325
    return name_ref(mem, pvalue->data, pvalue->size, pref,
 
326
                    (pvalue->persistent ? 0 : 1));
 
327
}
 
328
 
 
329
/* Generic routine for writing a ref parameter. */
 
330
static int
 
331
ref_param_write(iparam_list * plist, gs_param_name pkey, const ref * pvalue)
 
332
{
 
333
    ref kref;
 
334
    int code;
 
335
 
 
336
    if (!ref_param_requested((gs_param_list *) plist, pkey))
 
337
        return 0;
 
338
    code = ref_param_key(plist, pkey, &kref);
 
339
    if (code < 0)
 
340
        return code;
 
341
    return (*plist->u.w.write) (plist, &kref, pvalue);
 
342
}
 
343
 
 
344
/* ---------------- Implementations ---------------- */
 
345
 
 
346
/* Initialize for writing parameters. */
 
347
static void
 
348
ref_param_write_init(iparam_list * plist, const ref * pwanted,
 
349
                     gs_ref_memory_t *imem)
 
350
{
 
351
    gs_param_list_init((gs_param_list *)plist, &ref_write_procs,
 
352
                       (gs_memory_t *)imem);
 
353
    plist->ref_memory = imem;
 
354
    if (pwanted == 0)
 
355
        make_null(&plist->u.w.wanted);
 
356
    else
 
357
        plist->u.w.wanted = *pwanted;
 
358
    plist->results = 0;
 
359
    plist->int_keys = false;
 
360
}
 
361
 
 
362
/* Implementation for getting parameters to a stack. */
 
363
static int
 
364
stack_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue)
 
365
{
 
366
    stack_param_list *const splist = (stack_param_list *) plist;
 
367
    ref_stack_t *pstack = splist->pstack;
 
368
    s_ptr p = pstack->p;
 
369
 
 
370
    if (pstack->top - p < 2) {
 
371
        int code = ref_stack_push(pstack, 2);
 
372
 
 
373
        if (code < 0)
 
374
            return code;
 
375
        *ref_stack_index(pstack, 1) = *pkey;
 
376
        p = pstack->p;
 
377
    } else {
 
378
        pstack->p = p += 2;
 
379
        p[-1] = *pkey;
 
380
    }
 
381
    *p = *pvalue;
 
382
    splist->count++;
 
383
    return 0;
 
384
}
 
385
 
 
386
/* Implementation for enumerating parameters on a stack */
 
387
static int                      /* ret 0 ok, 1 if EOF, or -ve err */
 
388
stack_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
 
389
                      gs_param_key_t * key, ref_type * type)
 
390
{
 
391
    int code;
 
392
    stack_param_list *const splist = (stack_param_list *) plist;
 
393
    long index = penum->intval;
 
394
    ref *stack_element;
 
395
 
 
396
    do {
 
397
        stack_element =
 
398
            ref_stack_index(splist->pstack, index + 1 + splist->skip);
 
399
        if (!stack_element)
 
400
            return 1;
 
401
    } while (index += 2, !r_has_type(stack_element, t_name));
 
402
    *type = r_type(stack_element);
 
403
    code = ref_to_key(stack_element, key, plist);
 
404
    penum->intval = index;
 
405
    return code;
 
406
}
 
407
 
 
408
int
 
409
stack_param_list_write(stack_param_list * plist, ref_stack_t * pstack,
 
410
                       const ref * pwanted, gs_ref_memory_t *imem)
 
411
{
 
412
    plist->u.w.write = stack_param_write;
 
413
    ref_param_write_init((iparam_list *) plist, pwanted, imem);
 
414
    plist->enumerate = stack_param_enumerate;
 
415
    plist->pstack = pstack;
 
416
    plist->skip = 0;
 
417
    plist->count = 0;
 
418
    return 0;
 
419
}
 
420
 
 
421
/* Implementation for getting parameters to a dictionary. */
 
422
static int
 
423
dict_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue)
 
424
{
 
425
    int code =
 
426
        dict_put(&((dict_param_list *) plist)->dict, pkey, pvalue, NULL);
 
427
 
 
428
    return min(code, 0);
 
429
}
 
430
 
 
431
/* Implementation for enumerating parameters in a dictionary */
 
432
static int                      /* ret 0 ok, 1 if EOF, or -ve err */
 
433
dict_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
 
434
                     gs_param_key_t * key, ref_type * type)
 
435
{
 
436
    ref elt[2];
 
437
    int code;
 
438
    dict_param_list *const pdlist = (dict_param_list *) plist;
 
439
    int index =
 
440
    (penum->intval != 0 ? penum->intval : dict_first(&pdlist->dict));
 
441
 
 
442
    index = dict_next(&pdlist->dict, index, elt);
 
443
    if (index < 0)
 
444
        return 1;
 
445
    *type = r_type(&elt[1]);
 
446
    code = ref_to_key(&elt[0], key, plist);
 
447
    penum->intval = index;
 
448
    return code;
 
449
}
 
450
 
 
451
int
 
452
dict_param_list_write(dict_param_list *plist, ref *pdict, const ref *pwanted,
 
453
                      gs_ref_memory_t *imem)
 
454
{
 
455
    check_dict_write(*pdict);
 
456
    plist->u.w.write = dict_param_write;
 
457
    plist->enumerate = dict_param_enumerate;
 
458
    ref_param_write_init((iparam_list *) plist, pwanted, imem);
 
459
    plist->dict = *pdict;
 
460
    return 0;
 
461
}
 
462
 
 
463
/* Implementation for getting parameters to an indexed array. */
 
464
/* Note that this is now internal, since it only handles "new" arrays. */
 
465
static int
 
466
array_new_indexed_param_write(iparam_list * iplist, const ref * pkey,
 
467
                          const ref * pvalue)
 
468
{
 
469
    const ref *const arr = &((dict_param_list *)iplist)->dict;
 
470
    ref *eltp;
 
471
 
 
472
    if (!r_has_type(pkey, t_integer))
 
473
        return_error(e_typecheck);
 
474
    check_int_ltu(*pkey, r_size(arr));
 
475
    store_check_dest(arr, pvalue);
 
476
    eltp = arr->value.refs + pkey->value.intval;
 
477
    /* ref_assign_new(eltp, pvalue); */
 
478
    ref_assign(eltp, pvalue);
 
479
    r_set_attrs(eltp, imemory_new_mask(iplist->ref_memory));
 
480
    return 0;
 
481
}
 
482
static int
 
483
array_new_indexed_plist_write(dict_param_list * plist, ref * parray,
 
484
                              const ref * pwanted, gs_ref_memory_t *imem)
 
485
{
 
486
    check_array(*parray);
 
487
    check_write(*parray);
 
488
    plist->u.w.write = array_new_indexed_param_write;
 
489
    ref_param_write_init((iparam_list *) plist, pwanted, imem);
 
490
    plist->dict = *parray;
 
491
    plist->int_keys = true;
 
492
    return 0;
 
493
}
 
494
 
 
495
/* ================ Reading refs to parameters ================ */
 
496
 
 
497
/* ---------------- Generic reading procedures ---------------- */
 
498
 
 
499
static param_proc_begin_xmit_collection(ref_param_begin_read_collection);
 
500
static param_proc_end_xmit_collection(ref_param_end_read_collection);
 
501
static param_proc_xmit_typed(ref_param_read_typed);
 
502
 
 
503
/*static param_proc_next_key(ref_param_get_next_key); already dec'ld above */
 
504
static param_proc_get_policy(ref_param_read_get_policy);
 
505
static param_proc_signal_error(ref_param_read_signal_error);
 
506
static param_proc_commit(ref_param_read_commit);
 
507
static const gs_param_list_procs ref_read_procs =
 
508
{
 
509
    ref_param_read_typed,
 
510
    ref_param_begin_read_collection,
 
511
    ref_param_end_read_collection,
 
512
    ref_param_get_next_key,
 
513
    NULL,                       /* request */
 
514
    NULL,                       /* requested */
 
515
    ref_param_read_get_policy,
 
516
    ref_param_read_signal_error,
 
517
    ref_param_read_commit
 
518
};
 
519
static int ref_param_read(iparam_list *, gs_param_name,
 
520
                           iparam_loc *, int);
 
521
static int ref_param_read_string_value(gs_memory_t *mem,
 
522
                                        const iparam_loc *,
 
523
                                        gs_param_string *);
 
524
static int ref_param_read_array(iparam_list *, gs_param_name,
 
525
                                 iparam_loc *);
 
526
 
 
527
#define iparam_note_error(loc, code)\
 
528
  gs_note_error(*(loc).presult = code)
 
529
#define iparam_check_type(loc, typ)\
 
530
  if ( !r_has_type((loc).pvalue, typ) )\
 
531
    return iparam_note_error(loc, e_typecheck)
 
532
#define iparam_check_read(loc)\
 
533
  if ( !r_has_attr((loc).pvalue, a_read) )\
 
534
    return iparam_note_error(loc, e_invalidaccess)
 
535
 
 
536
static int
 
537
ref_param_read_int_array(gs_param_list * plist, gs_param_name pkey,
 
538
                         gs_param_int_array * pvalue)
 
539
{
 
540
    iparam_list *const iplist = (iparam_list *) plist;
 
541
    iparam_loc loc;
 
542
    int code = ref_param_read_array(iplist, pkey, &loc);
 
543
    int *piv;
 
544
    uint size;
 
545
    long i;
 
546
 
 
547
    if (code != 0)
 
548
        return code;
 
549
    size = r_size(loc.pvalue);
 
550
    piv = (int *)gs_alloc_byte_array(plist->memory, size, sizeof(int),
 
551
                                     "ref_param_read_int_array");
 
552
 
 
553
    if (piv == 0)
 
554
        return_error(e_VMerror);
 
555
    for (i = 0; i < size; i++) {
 
556
        ref elt;
 
557
 
 
558
        array_get(plist->memory, loc.pvalue, i, &elt);
 
559
        if (!r_has_type(&elt, t_integer)) {
 
560
            code = gs_note_error(e_typecheck);
 
561
            break;
 
562
        }
 
563
#if arch_sizeof_int < arch_sizeof_long
 
564
        if (elt.value.intval != (int)elt.value.intval) {
 
565
            code = gs_note_error(e_rangecheck);
 
566
            break;
 
567
        }
 
568
#endif
 
569
        piv[i] = (int)elt.value.intval;
 
570
    }
 
571
    if (code < 0) {
 
572
        gs_free_object(plist->memory, piv, "ref_param_read_int_array");
 
573
        return (*loc.presult = code);
 
574
    }
 
575
    pvalue->data = piv;
 
576
    pvalue->size = size;
 
577
    pvalue->persistent = true;
 
578
    return 0;
 
579
}
 
580
static int
 
581
ref_param_read_float_array(gs_param_list * plist, gs_param_name pkey,
 
582
                           gs_param_float_array * pvalue)
 
583
{
 
584
    iparam_list *const iplist = (iparam_list *) plist;
 
585
    iparam_loc loc;
 
586
    ref aref, elt;
 
587
    int code = ref_param_read_array(iplist, pkey, &loc);
 
588
    float *pfv;
 
589
    uint size;
 
590
    long i;
 
591
 
 
592
    if (code != 0)
 
593
        return code;
 
594
    size = r_size(loc.pvalue);
 
595
    pfv = (float *)gs_alloc_byte_array(plist->memory, size, sizeof(float),
 
596
                                       "ref_param_read_float_array");
 
597
 
 
598
    if (pfv == 0)
 
599
        return_error(e_VMerror);
 
600
    aref = *loc.pvalue;
 
601
    loc.pvalue = &elt;
 
602
    for (i = 0; code >= 0 && i < size; i++) {
 
603
        array_get(plist->memory, &aref, i, &elt);
 
604
        code = float_param(&elt, pfv + i);
 
605
    }
 
606
    if (code < 0) {
 
607
        gs_free_object(plist->memory, pfv, "ref_read_float_array_param");
 
608
        return (*loc.presult = code);
 
609
    }
 
610
    pvalue->data = pfv;
 
611
    pvalue->size = size;
 
612
    pvalue->persistent = true;
 
613
    return 0;
 
614
}
 
615
static int
 
616
ref_param_read_string_array(gs_param_list * plist, gs_param_name pkey,
 
617
                            gs_param_string_array * pvalue)
 
618
{
 
619
    iparam_list *const iplist = (iparam_list *) plist;
 
620
    iparam_loc loc;
 
621
    ref aref;
 
622
    int code = ref_param_read_array(iplist, pkey, &loc);
 
623
    gs_param_string *psv;
 
624
    uint size;
 
625
    long i;
 
626
 
 
627
    if (code != 0)
 
628
        return code;
 
629
    size = r_size(loc.pvalue);
 
630
    psv = (gs_param_string *)
 
631
        gs_alloc_byte_array(plist->memory, size, sizeof(gs_param_string),
 
632
                            "ref_param_read_string_array");
 
633
    if (psv == 0)
 
634
        return_error(e_VMerror);
 
635
    aref = *loc.pvalue;
 
636
    if (r_has_type(&aref, t_array)) {
 
637
        for (i = 0; code >= 0 && i < size; i++) {
 
638
            loc.pvalue = aref.value.refs + i;
 
639
            code = ref_param_read_string_value(plist->memory, &loc, psv + i);
 
640
        }
 
641
    } else {
 
642
        ref elt;
 
643
 
 
644
        loc.pvalue = &elt;
 
645
        for (i = 0; code >= 0 && i < size; i++) {
 
646
            array_get(plist->memory, &aref, i, &elt);
 
647
            code = ref_param_read_string_value(plist->memory, &loc, psv + i);
 
648
        }
 
649
    }
 
650
    if (code < 0) {
 
651
        gs_free_object(plist->memory, psv, "ref_param_read_string_array");
 
652
        return (*loc.presult = code);
 
653
    }
 
654
    pvalue->data = psv;
 
655
    pvalue->size = size;
 
656
    pvalue->persistent = true;
 
657
    return 0;
 
658
}
 
659
static int
 
660
ref_param_begin_read_collection(gs_param_list * plist, gs_param_name pkey,
 
661
                                gs_param_dict * pvalue,
 
662
                                gs_param_collection_type_t coll_type)
 
663
{
 
664
    iparam_list *const iplist = (iparam_list *) plist;
 
665
    iparam_loc loc;
 
666
    bool int_keys = coll_type != 0;
 
667
    int code = ref_param_read(iplist, pkey, &loc, -1);
 
668
    dict_param_list *dlist;
 
669
 
 
670
    if (code != 0)
 
671
        return code;
 
672
    dlist = (dict_param_list *)
 
673
        gs_alloc_bytes(plist->memory, size_of(dict_param_list),
 
674
                       "ref_param_begin_read_collection");
 
675
    if (dlist == 0)
 
676
        return_error(e_VMerror);
 
677
    if (r_has_type(loc.pvalue, t_dictionary)) {
 
678
        code = dict_param_list_read(dlist, loc.pvalue, NULL, false,
 
679
                                    iplist->ref_memory);
 
680
        dlist->int_keys = int_keys;
 
681
        if (code >= 0)
 
682
            pvalue->size = dict_length(loc.pvalue);
 
683
    } else if (int_keys && r_is_array(loc.pvalue)) {
 
684
        code = array_indexed_param_list_read(dlist, loc.pvalue, NULL, false,
 
685
                                             iplist->ref_memory);
 
686
        if (code >= 0)
 
687
            pvalue->size = r_size(loc.pvalue);
 
688
    } else
 
689
        code = gs_note_error(e_typecheck);
 
690
    if (code < 0) {
 
691
        gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
 
692
        return iparam_note_error(loc, code);
 
693
    }
 
694
    pvalue->list = (gs_param_list *) dlist;
 
695
    return 0;
 
696
}
 
697
static int
 
698
ref_param_end_read_collection(gs_param_list * plist, gs_param_name pkey,
 
699
                              gs_param_dict * pvalue)
 
700
{
 
701
    iparam_list_release((dict_param_list *) pvalue->list);
 
702
    gs_free_object(plist->memory, pvalue->list,
 
703
                   "ref_param_end_read_collection");
 
704
    return 0;
 
705
}
 
706
static int
 
707
ref_param_read_typed(gs_param_list * plist, gs_param_name pkey,
 
708
                     gs_param_typed_value * pvalue)
 
709
{
 
710
    iparam_list *const iplist = (iparam_list *) plist;
 
711
    iparam_loc loc;
 
712
    ref elt;
 
713
    int code = ref_param_read(iplist, pkey, &loc, -1);
 
714
 
 
715
    if (code != 0)
 
716
        return code;
 
717
    switch (r_type(loc.pvalue)) {
 
718
        case t_array:
 
719
        case t_mixedarray:
 
720
        case t_shortarray:
 
721
            iparam_check_read(loc);
 
722
            if (r_size(loc.pvalue) <= 0) {
 
723
                /* 0-length array; can't get type info */
 
724
                pvalue->type = gs_param_type_array;
 
725
                pvalue->value.d.list = 0;
 
726
                pvalue->value.d.size = 0;
 
727
                return 0;
 
728
            }
 
729
            /*
 
730
             * We have to guess at the array type.  First we guess based
 
731
             * on the type of the first element of the array.  If that
 
732
             * fails, we try again with more general types.
 
733
             */
 
734
            array_get(plist->memory, loc.pvalue, 0, &elt);
 
735
            switch (r_type(&elt)) {
 
736
                case t_integer:
 
737
                    pvalue->type = gs_param_type_int_array;
 
738
                    code = ref_param_read_int_array(plist, pkey,
 
739
                                                    &pvalue->value.ia);
 
740
                    if (code != e_typecheck)
 
741
                        return code;
 
742
                    /* This might be a float array.  Fall through. */
 
743
                    *loc.presult = 0;  /* reset error */
 
744
                case t_real:
 
745
                    pvalue->type = gs_param_type_float_array;
 
746
                    return ref_param_read_float_array(plist, pkey,
 
747
                                                      &pvalue->value.fa);
 
748
                case t_string:
 
749
                    pvalue->type = gs_param_type_string_array;
 
750
                    return ref_param_read_string_array(plist, pkey,
 
751
                                                       &pvalue->value.sa);
 
752
                case t_name:
 
753
                    pvalue->type = gs_param_type_name_array;
 
754
                    return ref_param_read_string_array(plist, pkey,
 
755
                                                       &pvalue->value.na);
 
756
                default:
 
757
                    break;
 
758
            }
 
759
            return gs_note_error(e_typecheck);
 
760
        case t_boolean:
 
761
            pvalue->type = gs_param_type_bool;
 
762
            pvalue->value.b = loc.pvalue->value.boolval;
 
763
            return 0;
 
764
        case t_dictionary:
 
765
            code = ref_param_begin_read_collection(plist, pkey,
 
766
                            &pvalue->value.d, gs_param_collection_dict_any);
 
767
            if (code < 0)
 
768
                return code;
 
769
            pvalue->type = gs_param_type_dict;
 
770
 
 
771
            /* fixup new dict's type & int_keys field if contents have int keys */
 
772
            {
 
773
                gs_param_enumerator_t enumr;
 
774
                gs_param_key_t key;
 
775
                ref_type keytype;
 
776
 
 
777
                param_init_enumerator(&enumr);
 
778
                if (!(*((iparam_list *) plist)->enumerate)
 
779
                    ((iparam_list *) pvalue->value.d.list, &enumr, &key, &keytype)
 
780
                    && keytype == t_integer) {
 
781
                    ((dict_param_list *) pvalue->value.d.list)->int_keys = 1;
 
782
                    pvalue->type = gs_param_type_dict_int_keys;
 
783
                }
 
784
            }
 
785
            return 0;
 
786
        case t_integer:
 
787
            pvalue->type = gs_param_type_long;
 
788
            pvalue->value.l = loc.pvalue->value.intval;
 
789
            return 0;
 
790
        case t_name:
 
791
            pvalue->type = gs_param_type_name;
 
792
            return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.n);
 
793
        case t_null:
 
794
            pvalue->type = gs_param_type_null;
 
795
            return 0;
 
796
        case t_real:
 
797
            pvalue->value.f = loc.pvalue->value.realval;
 
798
            pvalue->type = gs_param_type_float;
 
799
            return 0;
 
800
        case t_string:
 
801
        case t_astruct:
 
802
            pvalue->type = gs_param_type_string;
 
803
            return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.s);
 
804
        default:
 
805
            break;
 
806
    }
 
807
    return gs_note_error(e_typecheck);
 
808
}
 
809
 
 
810
static int
 
811
ref_param_read_get_policy(gs_param_list * plist, gs_param_name pkey)
 
812
{
 
813
    iparam_list *const iplist = (iparam_list *) plist;
 
814
    ref *pvalue;
 
815
 
 
816
    if (!(r_has_type(&iplist->u.r.policies, t_dictionary) &&
 
817
          dict_find_string(&iplist->u.r.policies, pkey, &pvalue) > 0 &&
 
818
          r_has_type(pvalue, t_integer))
 
819
        )
 
820
        return gs_param_policy_ignore;
 
821
    return (int)pvalue->value.intval;
 
822
}
 
823
static int
 
824
ref_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code)
 
825
{
 
826
    iparam_list *const iplist = (iparam_list *) plist;
 
827
    iparam_loc loc;
 
828
 
 
829
    ref_param_read(iplist, pkey, &loc, -1);     /* can't fail */
 
830
    *loc.presult = code;
 
831
    switch (ref_param_read_get_policy(plist, pkey)) {
 
832
        case gs_param_policy_ignore:
 
833
            return 0;
 
834
        case gs_param_policy_consult_user:
 
835
            return_error(e_configurationerror);
 
836
        default:
 
837
            return code;
 
838
    }
 
839
}
 
840
static int
 
841
ref_param_read_commit(gs_param_list * plist)
 
842
{
 
843
    iparam_list *const iplist = (iparam_list *) plist;
 
844
    int i;
 
845
    int ecode = 0;
 
846
 
 
847
    if (!iplist->u.r.require_all)
 
848
        return 0;
 
849
    /* Check to make sure that all parameters were actually read. */
 
850
    for (i = 0; i < iplist->count; ++i)
 
851
        if (iplist->results[i] == 0)
 
852
            iplist->results[i] = ecode = gs_note_error(e_undefined);
 
853
    return ecode;
 
854
}
 
855
static int
 
856
ref_param_get_next_key(gs_param_list * plist, gs_param_enumerator_t * penum,
 
857
                       gs_param_key_t * key)
 
858
{
 
859
    ref_type keytype;           /* result not needed here */
 
860
    iparam_list *const pilist = (iparam_list *) plist;
 
861
 
 
862
    return (*pilist->enumerate) (pilist, penum, key, &keytype);
 
863
}
 
864
 
 
865
/* ---------------- Internal routines ---------------- */
 
866
 
 
867
/* Read a string value. */
 
868
static int
 
869
ref_param_read_string_value(gs_memory_t *mem, const iparam_loc * ploc, gs_param_string * pvalue)
 
870
{
 
871
    const ref *pref = ploc->pvalue;
 
872
 
 
873
    switch (r_type(pref)) {
 
874
        case t_name: {
 
875
            ref nref;
 
876
 
 
877
            name_string_ref(mem, pref, &nref);
 
878
            pvalue->data = nref.value.const_bytes;
 
879
            pvalue->size = r_size(&nref);
 
880
            pvalue->persistent = true;
 
881
        }
 
882
            break;
 
883
        case t_string:
 
884
            iparam_check_read(*ploc);
 
885
            pvalue->data = pref->value.const_bytes;
 
886
            pvalue->size = r_size(pref);
 
887
            pvalue->persistent = false;
 
888
            break;
 
889
        case t_astruct:
 
890
            /* Note: technically, instead of the "mem" argument, we
 
891
               should be using the plists's ref_memory. However, in a
 
892
               simple call to .putdeviceparams, they are identical. */
 
893
            iparam_check_read(*ploc);
 
894
            if (gs_object_type(mem, pref->value.pstruct) != &st_bytes) 
 
895
                return iparam_note_error(*ploc, e_typecheck);
 
896
            pvalue->data = r_ptr(pref, byte);
 
897
            pvalue->size = gs_object_size(mem, pref->value.pstruct);
 
898
            pvalue->persistent = false;
 
899
            break;
 
900
        default:
 
901
            return iparam_note_error(*ploc, e_typecheck);
 
902
    }
 
903
    return 0;
 
904
}
 
905
 
 
906
/* Read an array (or packed array) parameter. */
 
907
static int
 
908
ref_param_read_array(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc)
 
909
{
 
910
    int code = ref_param_read(plist, pkey, ploc, -1);
 
911
 
 
912
    if (code != 0)
 
913
        return code;
 
914
    if (!r_is_array(ploc->pvalue))
 
915
        return iparam_note_error(*ploc, e_typecheck);
 
916
    iparam_check_read(*ploc);
 
917
    return 0;
 
918
}
 
919
 
 
920
/* Generic routine for reading a ref parameter. */
 
921
static int
 
922
ref_param_read(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc,
 
923
               int type)
 
924
{
 
925
    iparam_list *const iplist = (iparam_list *) plist;
 
926
    ref kref;
 
927
    int code = ref_param_key(plist, pkey, &kref);
 
928
 
 
929
    if (code < 0)
 
930
        return code;
 
931
    code = (*plist->u.r.read) (iplist, &kref, ploc);
 
932
    if (code != 0)
 
933
        return code;
 
934
    if (type >= 0)
 
935
        iparam_check_type(*ploc, type);
 
936
    return 0;
 
937
}
 
938
 
 
939
/* ---------------- Implementations ---------------- */
 
940
 
 
941
/* Implementation for putting parameters from an empty collection. */
 
942
static int
 
943
empty_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
 
944
{
 
945
    return 1;
 
946
}
 
947
 
 
948
/* Initialize for reading parameters. */
 
949
static int
 
950
ref_param_read_init(iparam_list * plist, uint count, const ref * ppolicies,
 
951
                    bool require_all, gs_ref_memory_t *imem)
 
952
{
 
953
    gs_param_list_init((gs_param_list *)plist, &ref_read_procs,
 
954
                       (gs_memory_t *)imem);
 
955
    plist->ref_memory = imem;
 
956
    if (ppolicies == 0)
 
957
        make_null(&plist->u.r.policies);
 
958
    else
 
959
        plist->u.r.policies = *ppolicies;
 
960
    plist->u.r.require_all = require_all;
 
961
    plist->count = count;
 
962
    plist->results = (int *)
 
963
        gs_alloc_byte_array(plist->memory, count, sizeof(int),
 
964
                            "ref_param_read_init");
 
965
 
 
966
    if (plist->results == 0)
 
967
        return_error(e_VMerror);
 
968
    memset(plist->results, 0, count * sizeof(int));
 
969
 
 
970
    plist->int_keys = false;
 
971
    return 0;
 
972
}
 
973
 
 
974
/* Implementation for putting parameters from an indexed array. */
 
975
static int
 
976
array_indexed_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
 
977
{
 
978
    ref *const arr = &((dict_param_list *) plist)->dict;
 
979
 
 
980
    check_type(*pkey, t_integer);
 
981
    if (pkey->value.intval < 0 || pkey->value.intval >= r_size(arr))
 
982
        return 1;
 
983
    ploc->pvalue = arr->value.refs + pkey->value.intval;
 
984
    ploc->presult = &plist->results[pkey->value.intval];
 
985
    *ploc->presult = 1;
 
986
    return 0;
 
987
}
 
988
int
 
989
array_indexed_param_list_read(dict_param_list * plist, const ref * parray,
 
990
                              const ref * ppolicies, bool require_all,
 
991
                              gs_ref_memory_t *ref_memory)
 
992
{
 
993
    iparam_list *const iplist = (iparam_list *) plist;
 
994
    int code;
 
995
 
 
996
    check_read_type(*parray, t_array);
 
997
    plist->u.r.read = array_indexed_param_read;
 
998
    plist->dict = *parray;
 
999
    code = ref_param_read_init(iplist, r_size(parray), ppolicies,
 
1000
                               require_all, ref_memory);
 
1001
    plist->int_keys = true;
 
1002
    return code;
 
1003
}
 
1004
 
 
1005
/* Implementation for putting parameters from an array. */
 
1006
static int
 
1007
array_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
 
1008
{
 
1009
    ref *bot = ((array_param_list *) plist)->bot;
 
1010
    ref *ptr = bot;
 
1011
    ref *top = ((array_param_list *) plist)->top;
 
1012
 
 
1013
    for (; ptr < top; ptr += 2) {
 
1014
        if (r_has_type(ptr, t_name) && name_eq(ptr, pkey)) {
 
1015
            ploc->pvalue = ptr + 1;
 
1016
            ploc->presult = &plist->results[ptr - bot];
 
1017
            *ploc->presult = 1;
 
1018
            return 0;
 
1019
        }
 
1020
    }
 
1021
    return 1;
 
1022
}
 
1023
 
 
1024
/* Implementation for enumerating parameters in an array */
 
1025
static int                      /* ret 0 ok, 1 if EOF, or -ve err */
 
1026
array_param_enumerate(iparam_list * plist, gs_param_enumerator_t * penum,
 
1027
                      gs_param_key_t * key, ref_type * type)
 
1028
{
 
1029
    int index = penum->intval;
 
1030
    ref *bot = ((array_param_list *) plist)->bot;
 
1031
    ref *ptr = bot + index;
 
1032
    ref *top = ((array_param_list *) plist)->top;
 
1033
 
 
1034
    for (; ptr < top; ptr += 2) {
 
1035
        index += 2;
 
1036
 
 
1037
        if (r_has_type(ptr, t_name)) {
 
1038
            int code = ref_to_key(ptr, key, plist);
 
1039
 
 
1040
            *type = r_type(ptr);
 
1041
            penum->intval = index;
 
1042
            return code;
 
1043
        }
 
1044
    }
 
1045
    return 1;
 
1046
}
 
1047
 
 
1048
int
 
1049
array_param_list_read(array_param_list * plist, ref * bot, uint count,
 
1050
                      const ref * ppolicies, bool require_all,
 
1051
                      gs_ref_memory_t *imem)
 
1052
{
 
1053
    iparam_list *const iplist = (iparam_list *) plist;
 
1054
 
 
1055
    if (count & 1)
 
1056
        return_error(e_rangecheck);
 
1057
    plist->u.r.read = array_param_read;
 
1058
    plist->enumerate = array_param_enumerate;
 
1059
    plist->bot = bot;
 
1060
    plist->top = bot + count;
 
1061
    return ref_param_read_init(iplist, count, ppolicies, require_all, imem);
 
1062
}
 
1063
 
 
1064
/* Implementation for putting parameters from a stack. */
 
1065
static int
 
1066
stack_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
 
1067
{
 
1068
    stack_param_list *const splist = (stack_param_list *) plist;
 
1069
    ref_stack_t *pstack = splist->pstack;
 
1070
 
 
1071
    /* This implementation is slow, but it probably doesn't matter. */
 
1072
    uint index = splist->skip + 1;
 
1073
    uint count = splist->count;
 
1074
 
 
1075
    for (; count; count--, index += 2) {
 
1076
        const ref *p = ref_stack_index(pstack, index);
 
1077
 
 
1078
        if (r_has_type(p, t_name) && name_eq(p, pkey)) {
 
1079
            ploc->pvalue = ref_stack_index(pstack, index - 1);
 
1080
            ploc->presult = &plist->results[count - 1];
 
1081
            *ploc->presult = 1;
 
1082
            return 0;
 
1083
        }
 
1084
    }
 
1085
    return 1;
 
1086
}
 
1087
int
 
1088
stack_param_list_read(stack_param_list * plist, ref_stack_t * pstack,
 
1089
                      uint skip, const ref * ppolicies, bool require_all,
 
1090
                      gs_ref_memory_t *imem)
 
1091
{
 
1092
    iparam_list *const iplist = (iparam_list *) plist;
 
1093
    uint count = ref_stack_counttomark(pstack);
 
1094
 
 
1095
    if (count == 0)
 
1096
        return_error(e_unmatchedmark);
 
1097
    count -= skip + 1;
 
1098
    if (count & 1)
 
1099
        return_error(e_rangecheck);
 
1100
    plist->u.r.read = stack_param_read;
 
1101
    plist->enumerate = stack_param_enumerate;
 
1102
    plist->pstack = pstack;
 
1103
    plist->skip = skip;
 
1104
    return ref_param_read_init(iplist, count >> 1, ppolicies, require_all, imem);
 
1105
}
 
1106
 
 
1107
/* Implementation for putting parameters from a dictionary. */
 
1108
static int
 
1109
dict_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
 
1110
{
 
1111
    ref const *spdict = &((dict_param_list *) plist)->dict;
 
1112
    int code = dict_find(spdict, pkey, &ploc->pvalue);
 
1113
 
 
1114
    if (code != 1)
 
1115
        return 1;
 
1116
    ploc->presult =
 
1117
        &plist->results[dict_value_index(spdict, ploc->pvalue)];
 
1118
    *ploc->presult = 1;
 
1119
    return 0;
 
1120
}
 
1121
int
 
1122
dict_param_list_read(dict_param_list * plist, const ref * pdict,
 
1123
                     const ref * ppolicies, bool require_all,
 
1124
                     gs_ref_memory_t *imem)
 
1125
{
 
1126
    iparam_list *const iplist = (iparam_list *) plist;
 
1127
    uint count;
 
1128
 
 
1129
    if (pdict == 0) {
 
1130
        plist->u.r.read = empty_param_read;
 
1131
        count = 0;
 
1132
    } else {
 
1133
        check_dict_read(*pdict);
 
1134
        plist->u.r.read = dict_param_read;
 
1135
        plist->dict = *pdict;
 
1136
        count = dict_max_index(pdict) + 1;
 
1137
    }
 
1138
    plist->enumerate = dict_param_enumerate;
 
1139
    return ref_param_read_init(iplist, count, ppolicies, require_all, imem);
 
1140
}