1
/* Copyright (C) 2001-2006 Artifex Software, Inc.
4
This software is provided AS-IS with no warranty, either express or
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.
14
/* $Id: iparam.c 9043 2008-08-28 22:48:19Z giles $ */
15
/* Interpreter implementations of parameter dictionaries */
20
#include "oper.h" /* for check_type */
24
#include "imemory.h" /* for iutil.h */
28
#include "iutil.h" /* for num_params */
31
#include "gsstruct.h" /* for st_bytes */
33
/* ================ Utilities ================ */
35
/* Convert a key to a ref. */
37
ref_param_key(const iparam_list * plist, gs_param_name pkey, ref * pkref)
39
if (plist->int_keys) {
42
if (sscanf(pkey, "%ld", &key) != 1)
43
return_error(e_rangecheck);
47
return name_ref(plist->memory, (const byte *)pkey, strlen(pkey), pkref, 0);
50
/* Fill in a gs_param_key_t from a name or int ref. */
52
ref_to_key(const ref * pref, gs_param_key_t * key, iparam_list *plist)
54
if (r_has_type(pref, t_name)) {
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];
66
sprintf(istr, "%ld", pref->value.intval);
68
/* GC will take care of freeing this: */
69
buf = gs_alloc_string(plist->memory, len, "ref_to_key");
71
return_error(e_VMerror);
74
key->persistent = true;
76
return_error(e_typecheck);
80
/* ================ Writing parameters to refs ================ */
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);
87
/* ---------------- Generic writing procedures ---------------- */
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 =
96
ref_param_write_typed,
97
ref_param_begin_write_collection,
98
ref_param_end_write_collection,
99
ref_param_get_next_key,
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 *,
108
static int ref_param_write_name_value(const gs_memory_t *mem, ref *, const gs_param_string *);
110
ref_param_make_int(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
112
make_tav(pe, t_integer, imemory_new_mask(imem), intval,
113
((const gs_param_int_array *)pvalue)->data[i]);
117
ref_param_make_float(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
119
make_tav(pe, t_real, imemory_new_mask(imem), realval,
120
((const gs_param_float_array *)pvalue)->data[i]);
124
ref_param_make_string(ref *pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
126
return ref_param_write_string_value(pe,
127
&((const gs_param_string_array *)pvalue)->data[i],
131
ref_param_make_name(ref * pe, const void *pvalue, uint i, gs_ref_memory_t *imem)
133
return ref_param_write_name_value((const gs_memory_t *)imem, pe,
134
&((const gs_param_string_array *)pvalue)->data[i]);
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,
142
iparam_list *const iplist = (iparam_list *) plist;
148
if ((code = ref_array_param_requested(iplist, pkey, &value, count,
149
"ref_param_write_typed_array")) <= 0)
151
for (i = 0, pe = value.value.refs; i < count; ++i, ++pe)
152
if ((code = (*make) (pe, pvalue, i, iplist->ref_memory)) < 0)
154
return ref_param_write(iplist, pkey, &value);
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)
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");
169
return_error(e_VMerror);
170
if (coll_type != gs_param_collection_array) {
173
code = dict_alloc(imem, pvalue->size, &dref);
175
code = dict_param_list_write(dlist, &dref, NULL, imem);
176
dlist->int_keys = coll_type == gs_param_collection_dict_int_keys;
181
code = gs_alloc_ref_array(imem, &aref, a_all, pvalue->size,
182
"ref_param_begin_write_collection");
184
code = array_new_indexed_plist_write(dlist, &aref, NULL, imem);
187
gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
189
pvalue->list = (gs_param_list *) dlist;
193
ref_param_end_write_collection(gs_param_list * plist, gs_param_name pkey,
194
gs_param_dict * pvalue)
196
iparam_list *const iplist = (iparam_list *) plist;
197
int code = ref_param_write(iplist, pkey,
198
&((dict_param_list *) pvalue->list)->dict);
200
gs_free_object(plist->memory, pvalue->list, "ref_param_end_write_collection");
204
ref_param_write_typed(gs_param_list * plist, gs_param_name pkey,
205
gs_param_typed_value * pvalue)
207
iparam_list *const iplist = (iparam_list *) plist;
211
switch (pvalue->type) {
212
case gs_param_type_null:
215
case gs_param_type_bool:
216
make_bool(&value, pvalue->value.b);
218
case gs_param_type_int:
219
make_int(&value, pvalue->value.i);
221
case gs_param_type_long:
222
make_int(&value, pvalue->value.l);
224
case gs_param_type_float:
225
make_real(&value, pvalue->value.f);
227
case gs_param_type_string:
228
if (!ref_param_requested(plist, pkey))
230
code = ref_param_write_string_value(&value, &pvalue->value.s,
233
case gs_param_type_name:
234
if (!ref_param_requested(plist, pkey))
236
code = ref_param_write_name_value(iplist->memory, &value, &pvalue->value.n);
238
case gs_param_type_int_array:
239
return ref_param_write_typed_array(plist, pkey, &pvalue->value.ia,
240
pvalue->value.ia.size,
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,
259
(gs_param_collection_type_t)(pvalue->type - gs_param_type_dict));
261
return_error(e_typecheck);
265
return ref_param_write(iplist, pkey, &value);
268
/* Check whether a given parameter was requested. */
270
ref_param_requested(const gs_param_list * plist, gs_param_name pkey)
272
const iparam_list *const ciplist = (const iparam_list *)plist;
276
if (!r_has_type(&ciplist->u.w.wanted, t_dictionary))
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);
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. */
286
ref_array_param_requested(const iparam_list *iplist, gs_param_name pkey,
287
ref *pvalue, uint size, client_name_t cname)
291
if (!ref_param_requested((const gs_param_list *)iplist, pkey))
293
code = gs_alloc_ref_array(iplist->ref_memory, pvalue, a_all, size, cname);
294
return (code < 0 ? code : 1);
297
/* ---------------- Internal routines ---------------- */
299
/* Prepare to write a string value. */
301
ref_param_write_string_value(ref * pref, const gs_param_string * pvalue,
302
gs_ref_memory_t *imem)
304
const byte *pdata = pvalue->data;
305
uint n = pvalue->size;
307
if (pvalue->persistent)
308
make_const_string(pref, a_readonly | avm_foreign, n, pdata);
310
byte *pstr = gs_alloc_string((gs_memory_t *)imem, n,
311
"ref_param_write_string");
314
return_error(e_VMerror);
315
memcpy(pstr, pdata, n);
316
make_string(pref, a_readonly | imemory_space(imem), n, pstr);
321
/* Prepare to write a name value. */
323
ref_param_write_name_value(const gs_memory_t *mem, ref * pref, const gs_param_string * pvalue)
325
return name_ref(mem, pvalue->data, pvalue->size, pref,
326
(pvalue->persistent ? 0 : 1));
329
/* Generic routine for writing a ref parameter. */
331
ref_param_write(iparam_list * plist, gs_param_name pkey, const ref * pvalue)
336
if (!ref_param_requested((gs_param_list *) plist, pkey))
338
code = ref_param_key(plist, pkey, &kref);
341
return (*plist->u.w.write) (plist, &kref, pvalue);
344
/* ---------------- Implementations ---------------- */
346
/* Initialize for writing parameters. */
348
ref_param_write_init(iparam_list * plist, const ref * pwanted,
349
gs_ref_memory_t *imem)
351
gs_param_list_init((gs_param_list *)plist, &ref_write_procs,
352
(gs_memory_t *)imem);
353
plist->ref_memory = imem;
355
make_null(&plist->u.w.wanted);
357
plist->u.w.wanted = *pwanted;
359
plist->int_keys = false;
362
/* Implementation for getting parameters to a stack. */
364
stack_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue)
366
stack_param_list *const splist = (stack_param_list *) plist;
367
ref_stack_t *pstack = splist->pstack;
370
if (pstack->top - p < 2) {
371
int code = ref_stack_push(pstack, 2);
375
*ref_stack_index(pstack, 1) = *pkey;
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)
392
stack_param_list *const splist = (stack_param_list *) plist;
393
long index = penum->intval;
398
ref_stack_index(splist->pstack, index + 1 + splist->skip);
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;
409
stack_param_list_write(stack_param_list * plist, ref_stack_t * pstack,
410
const ref * pwanted, gs_ref_memory_t *imem)
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;
421
/* Implementation for getting parameters to a dictionary. */
423
dict_param_write(iparam_list * plist, const ref * pkey, const ref * pvalue)
426
dict_put(&((dict_param_list *) plist)->dict, pkey, pvalue, NULL);
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)
438
dict_param_list *const pdlist = (dict_param_list *) plist;
440
(penum->intval != 0 ? penum->intval : dict_first(&pdlist->dict));
442
index = dict_next(&pdlist->dict, index, elt);
445
*type = r_type(&elt[1]);
446
code = ref_to_key(&elt[0], key, plist);
447
penum->intval = index;
452
dict_param_list_write(dict_param_list *plist, ref *pdict, const ref *pwanted,
453
gs_ref_memory_t *imem)
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;
463
/* Implementation for getting parameters to an indexed array. */
464
/* Note that this is now internal, since it only handles "new" arrays. */
466
array_new_indexed_param_write(iparam_list * iplist, const ref * pkey,
469
const ref *const arr = &((dict_param_list *)iplist)->dict;
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));
483
array_new_indexed_plist_write(dict_param_list * plist, ref * parray,
484
const ref * pwanted, gs_ref_memory_t *imem)
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;
495
/* ================ Reading refs to parameters ================ */
497
/* ---------------- Generic reading procedures ---------------- */
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);
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 =
509
ref_param_read_typed,
510
ref_param_begin_read_collection,
511
ref_param_end_read_collection,
512
ref_param_get_next_key,
514
NULL, /* requested */
515
ref_param_read_get_policy,
516
ref_param_read_signal_error,
517
ref_param_read_commit
519
static int ref_param_read(iparam_list *, gs_param_name,
521
static int ref_param_read_string_value(gs_memory_t *mem,
524
static int ref_param_read_array(iparam_list *, gs_param_name,
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)
537
ref_param_read_int_array(gs_param_list * plist, gs_param_name pkey,
538
gs_param_int_array * pvalue)
540
iparam_list *const iplist = (iparam_list *) plist;
542
int code = ref_param_read_array(iplist, pkey, &loc);
549
size = r_size(loc.pvalue);
550
piv = (int *)gs_alloc_byte_array(plist->memory, size, sizeof(int),
551
"ref_param_read_int_array");
554
return_error(e_VMerror);
555
for (i = 0; i < size; i++) {
558
array_get(plist->memory, loc.pvalue, i, &elt);
559
if (!r_has_type(&elt, t_integer)) {
560
code = gs_note_error(e_typecheck);
563
#if arch_sizeof_int < arch_sizeof_long
564
if (elt.value.intval != (int)elt.value.intval) {
565
code = gs_note_error(e_rangecheck);
569
piv[i] = (int)elt.value.intval;
572
gs_free_object(plist->memory, piv, "ref_param_read_int_array");
573
return (*loc.presult = code);
577
pvalue->persistent = true;
581
ref_param_read_float_array(gs_param_list * plist, gs_param_name pkey,
582
gs_param_float_array * pvalue)
584
iparam_list *const iplist = (iparam_list *) plist;
587
int code = ref_param_read_array(iplist, pkey, &loc);
594
size = r_size(loc.pvalue);
595
pfv = (float *)gs_alloc_byte_array(plist->memory, size, sizeof(float),
596
"ref_param_read_float_array");
599
return_error(e_VMerror);
602
for (i = 0; code >= 0 && i < size; i++) {
603
array_get(plist->memory, &aref, i, &elt);
604
code = float_param(&elt, pfv + i);
607
gs_free_object(plist->memory, pfv, "ref_read_float_array_param");
608
return (*loc.presult = code);
612
pvalue->persistent = true;
616
ref_param_read_string_array(gs_param_list * plist, gs_param_name pkey,
617
gs_param_string_array * pvalue)
619
iparam_list *const iplist = (iparam_list *) plist;
622
int code = ref_param_read_array(iplist, pkey, &loc);
623
gs_param_string *psv;
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");
634
return_error(e_VMerror);
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);
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);
651
gs_free_object(plist->memory, psv, "ref_param_read_string_array");
652
return (*loc.presult = code);
656
pvalue->persistent = true;
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)
664
iparam_list *const iplist = (iparam_list *) plist;
666
bool int_keys = coll_type != 0;
667
int code = ref_param_read(iplist, pkey, &loc, -1);
668
dict_param_list *dlist;
672
dlist = (dict_param_list *)
673
gs_alloc_bytes(plist->memory, size_of(dict_param_list),
674
"ref_param_begin_read_collection");
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,
680
dlist->int_keys = int_keys;
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,
687
pvalue->size = r_size(loc.pvalue);
689
code = gs_note_error(e_typecheck);
691
gs_free_object(plist->memory, dlist, "ref_param_begin_write_collection");
692
return iparam_note_error(loc, code);
694
pvalue->list = (gs_param_list *) dlist;
698
ref_param_end_read_collection(gs_param_list * plist, gs_param_name pkey,
699
gs_param_dict * pvalue)
701
iparam_list_release((dict_param_list *) pvalue->list);
702
gs_free_object(plist->memory, pvalue->list,
703
"ref_param_end_read_collection");
707
ref_param_read_typed(gs_param_list * plist, gs_param_name pkey,
708
gs_param_typed_value * pvalue)
710
iparam_list *const iplist = (iparam_list *) plist;
713
int code = ref_param_read(iplist, pkey, &loc, -1);
717
switch (r_type(loc.pvalue)) {
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;
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.
734
array_get(plist->memory, loc.pvalue, 0, &elt);
735
switch (r_type(&elt)) {
737
pvalue->type = gs_param_type_int_array;
738
code = ref_param_read_int_array(plist, pkey,
740
if (code != e_typecheck)
742
/* This might be a float array. Fall through. */
743
*loc.presult = 0; /* reset error */
745
pvalue->type = gs_param_type_float_array;
746
return ref_param_read_float_array(plist, pkey,
749
pvalue->type = gs_param_type_string_array;
750
return ref_param_read_string_array(plist, pkey,
753
pvalue->type = gs_param_type_name_array;
754
return ref_param_read_string_array(plist, pkey,
759
return gs_note_error(e_typecheck);
761
pvalue->type = gs_param_type_bool;
762
pvalue->value.b = loc.pvalue->value.boolval;
765
code = ref_param_begin_read_collection(plist, pkey,
766
&pvalue->value.d, gs_param_collection_dict_any);
769
pvalue->type = gs_param_type_dict;
771
/* fixup new dict's type & int_keys field if contents have int keys */
773
gs_param_enumerator_t enumr;
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;
787
pvalue->type = gs_param_type_long;
788
pvalue->value.l = loc.pvalue->value.intval;
791
pvalue->type = gs_param_type_name;
792
return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.n);
794
pvalue->type = gs_param_type_null;
797
pvalue->value.f = loc.pvalue->value.realval;
798
pvalue->type = gs_param_type_float;
802
pvalue->type = gs_param_type_string;
803
return ref_param_read_string_value(plist->memory, &loc, &pvalue->value.s);
807
return gs_note_error(e_typecheck);
811
ref_param_read_get_policy(gs_param_list * plist, gs_param_name pkey)
813
iparam_list *const iplist = (iparam_list *) plist;
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))
820
return gs_param_policy_ignore;
821
return (int)pvalue->value.intval;
824
ref_param_read_signal_error(gs_param_list * plist, gs_param_name pkey, int code)
826
iparam_list *const iplist = (iparam_list *) plist;
829
ref_param_read(iplist, pkey, &loc, -1); /* can't fail */
831
switch (ref_param_read_get_policy(plist, pkey)) {
832
case gs_param_policy_ignore:
834
case gs_param_policy_consult_user:
835
return_error(e_configurationerror);
841
ref_param_read_commit(gs_param_list * plist)
843
iparam_list *const iplist = (iparam_list *) plist;
847
if (!iplist->u.r.require_all)
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);
856
ref_param_get_next_key(gs_param_list * plist, gs_param_enumerator_t * penum,
857
gs_param_key_t * key)
859
ref_type keytype; /* result not needed here */
860
iparam_list *const pilist = (iparam_list *) plist;
862
return (*pilist->enumerate) (pilist, penum, key, &keytype);
865
/* ---------------- Internal routines ---------------- */
867
/* Read a string value. */
869
ref_param_read_string_value(gs_memory_t *mem, const iparam_loc * ploc, gs_param_string * pvalue)
871
const ref *pref = ploc->pvalue;
873
switch (r_type(pref)) {
877
name_string_ref(mem, pref, &nref);
878
pvalue->data = nref.value.const_bytes;
879
pvalue->size = r_size(&nref);
880
pvalue->persistent = true;
884
iparam_check_read(*ploc);
885
pvalue->data = pref->value.const_bytes;
886
pvalue->size = r_size(pref);
887
pvalue->persistent = false;
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;
901
return iparam_note_error(*ploc, e_typecheck);
906
/* Read an array (or packed array) parameter. */
908
ref_param_read_array(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc)
910
int code = ref_param_read(plist, pkey, ploc, -1);
914
if (!r_is_array(ploc->pvalue))
915
return iparam_note_error(*ploc, e_typecheck);
916
iparam_check_read(*ploc);
920
/* Generic routine for reading a ref parameter. */
922
ref_param_read(iparam_list * plist, gs_param_name pkey, iparam_loc * ploc,
925
iparam_list *const iplist = (iparam_list *) plist;
927
int code = ref_param_key(plist, pkey, &kref);
931
code = (*plist->u.r.read) (iplist, &kref, ploc);
935
iparam_check_type(*ploc, type);
939
/* ---------------- Implementations ---------------- */
941
/* Implementation for putting parameters from an empty collection. */
943
empty_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
948
/* Initialize for reading parameters. */
950
ref_param_read_init(iparam_list * plist, uint count, const ref * ppolicies,
951
bool require_all, gs_ref_memory_t *imem)
953
gs_param_list_init((gs_param_list *)plist, &ref_read_procs,
954
(gs_memory_t *)imem);
955
plist->ref_memory = imem;
957
make_null(&plist->u.r.policies);
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");
966
if (plist->results == 0)
967
return_error(e_VMerror);
968
memset(plist->results, 0, count * sizeof(int));
970
plist->int_keys = false;
974
/* Implementation for putting parameters from an indexed array. */
976
array_indexed_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
978
ref *const arr = &((dict_param_list *) plist)->dict;
980
check_type(*pkey, t_integer);
981
if (pkey->value.intval < 0 || pkey->value.intval >= r_size(arr))
983
ploc->pvalue = arr->value.refs + pkey->value.intval;
984
ploc->presult = &plist->results[pkey->value.intval];
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)
993
iparam_list *const iplist = (iparam_list *) plist;
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;
1005
/* Implementation for putting parameters from an array. */
1007
array_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
1009
ref *bot = ((array_param_list *) plist)->bot;
1011
ref *top = ((array_param_list *) plist)->top;
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];
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)
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;
1034
for (; ptr < top; ptr += 2) {
1037
if (r_has_type(ptr, t_name)) {
1038
int code = ref_to_key(ptr, key, plist);
1040
*type = r_type(ptr);
1041
penum->intval = index;
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)
1053
iparam_list *const iplist = (iparam_list *) plist;
1056
return_error(e_rangecheck);
1057
plist->u.r.read = array_param_read;
1058
plist->enumerate = array_param_enumerate;
1060
plist->top = bot + count;
1061
return ref_param_read_init(iplist, count, ppolicies, require_all, imem);
1064
/* Implementation for putting parameters from a stack. */
1066
stack_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
1068
stack_param_list *const splist = (stack_param_list *) plist;
1069
ref_stack_t *pstack = splist->pstack;
1071
/* This implementation is slow, but it probably doesn't matter. */
1072
uint index = splist->skip + 1;
1073
uint count = splist->count;
1075
for (; count; count--, index += 2) {
1076
const ref *p = ref_stack_index(pstack, index);
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];
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)
1092
iparam_list *const iplist = (iparam_list *) plist;
1093
uint count = ref_stack_counttomark(pstack);
1096
return_error(e_unmatchedmark);
1099
return_error(e_rangecheck);
1100
plist->u.r.read = stack_param_read;
1101
plist->enumerate = stack_param_enumerate;
1102
plist->pstack = pstack;
1104
return ref_param_read_init(iplist, count >> 1, ppolicies, require_all, imem);
1107
/* Implementation for putting parameters from a dictionary. */
1109
dict_param_read(iparam_list * plist, const ref * pkey, iparam_loc * ploc)
1111
ref const *spdict = &((dict_param_list *) plist)->dict;
1112
int code = dict_find(spdict, pkey, &ploc->pvalue);
1117
&plist->results[dict_value_index(spdict, ploc->pvalue)];
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)
1126
iparam_list *const iplist = (iparam_list *) plist;
1130
plist->u.r.read = empty_param_read;
1133
check_dict_read(*pdict);
1134
plist->u.r.read = dict_param_read;
1135
plist->dict = *pdict;
1136
count = dict_max_index(pdict) + 1;
1138
plist->enumerate = dict_param_enumerate;
1139
return ref_param_read_init(iplist, count, ppolicies, require_all, imem);