xref: /plan9/sys/src/cmd/gs/src/gsparamx.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gsparamx.c,v 1.6 2002/02/21 22:24:52 giles Exp $ */
18 /* Extended parameter dictionary utilities */
19 #include "string_.h"
20 #include "gserror.h"
21 #include "gserrors.h"
22 #include "gstypes.h"
23 #include "gsmemory.h"
24 #include "gsparam.h"
25 #include "gsparamx.h"
26 
27 /* Compare a C string and a gs_param_string. */
28 bool
gs_param_string_eq(const gs_param_string * pcs,const char * str)29 gs_param_string_eq(const gs_param_string * pcs, const char *str)
30 {
31     return (strlen(str) == pcs->size &&
32 	    !strncmp(str, (const char *)pcs->data, pcs->size));
33 }
34 
35 /* Put an enumerated value. */
36 int
param_put_enum(gs_param_list * plist,gs_param_name param_name,int * pvalue,const char * const pnames[],int ecode)37 param_put_enum(gs_param_list * plist, gs_param_name param_name,
38 	       int *pvalue, const char *const pnames[], int ecode)
39 {
40     gs_param_string ens;
41     int code = param_read_name(plist, param_name, &ens);
42 
43     switch (code) {
44 	case 1:
45 	    return ecode;
46 	case 0:
47 	    {
48 		int i;
49 
50 		for (i = 0; pnames[i] != 0; ++i)
51 		    if (gs_param_string_eq(&ens, pnames[i])) {
52 			*pvalue = i;
53 			return 0;
54 		    }
55 	    }
56 	    code = gs_error_rangecheck;
57 	default:
58 	    ecode = code;
59 	    param_signal_error(plist, param_name, code);
60     }
61     return code;
62 }
63 
64 /* Put a Boolean value. */
65 int
param_put_bool(gs_param_list * plist,gs_param_name param_name,bool * pval,int ecode)66 param_put_bool(gs_param_list * plist, gs_param_name param_name,
67 	       bool * pval, int ecode)
68 {
69     int code;
70 
71     switch (code = param_read_bool(plist, param_name, pval)) {
72 	default:
73 	    ecode = code;
74 	    param_signal_error(plist, param_name, ecode);
75 	case 0:
76 	case 1:
77 	    break;
78     }
79     return ecode;
80 }
81 
82 /* Put an integer value. */
83 int
param_put_int(gs_param_list * plist,gs_param_name param_name,int * pval,int ecode)84 param_put_int(gs_param_list * plist, gs_param_name param_name,
85 	      int *pval, int ecode)
86 {
87     int code;
88 
89     switch (code = param_read_int(plist, param_name, pval)) {
90 	default:
91 	    ecode = code;
92 	    param_signal_error(plist, param_name, ecode);
93 	case 0:
94 	case 1:
95 	    break;
96     }
97     return ecode;
98 }
99 
100 /* Put a long value. */
101 int
param_put_long(gs_param_list * plist,gs_param_name param_name,long * pval,int ecode)102 param_put_long(gs_param_list * plist, gs_param_name param_name,
103 	       long *pval, int ecode)
104 {
105     int code;
106 
107     switch (code = param_read_long(plist, param_name, pval)) {
108 	default:
109 	    ecode = code;
110 	    param_signal_error(plist, param_name, ecode);
111 	case 0:
112 	case 1:
113 	    break;
114     }
115     return ecode;
116 }
117 
118 /* Copy one parameter list to another, recursively if necessary. */
119 int
param_list_copy(gs_param_list * plto,gs_param_list * plfrom)120 param_list_copy(gs_param_list *plto, gs_param_list *plfrom)
121 {
122     gs_param_enumerator_t key_enum;
123     gs_param_key_t key;
124     /*
125      * If plfrom and plto use different allocators, we must copy
126      * aggregate values even if they are "persistent".
127      */
128     bool copy_persists = plto->memory == plfrom->memory;
129     int code;
130 
131     param_init_enumerator(&key_enum);
132     while ((code = param_get_next_key(plfrom, &key_enum, &key)) == 0) {
133 	char string_key[256];	/* big enough for any reasonable key */
134 	gs_param_typed_value value;
135 	gs_param_collection_type_t coll_type;
136 	gs_param_typed_value copy;
137 
138 	if (key.size > sizeof(string_key) - 1) {
139 	    code = gs_note_error(gs_error_rangecheck);
140 	    break;
141 	}
142 	memcpy(string_key, key.data, key.size);
143 	string_key[key.size] = 0;
144 	if ((code = param_read_typed(plfrom, string_key, &value)) != 0) {
145 	    code = (code > 0 ? gs_note_error(gs_error_unknownerror) : code);
146 	    break;
147 	}
148 	gs_param_list_set_persistent_keys(plto, key.persistent);
149 	switch (value.type) {
150 	case gs_param_type_dict:
151 	    coll_type = gs_param_collection_dict_any;
152 	    goto cc;
153 	case gs_param_type_dict_int_keys:
154 	    coll_type = gs_param_collection_dict_int_keys;
155 	    goto cc;
156 	case gs_param_type_array:
157 	    coll_type = gs_param_collection_array;
158 	cc:
159 	    copy.value.d.size = value.value.d.size;
160 	    if ((code = param_begin_write_collection(plto, string_key,
161 						     &copy.value.d,
162 						     coll_type)) < 0 ||
163 		(code = param_list_copy(copy.value.d.list,
164 					value.value.d.list)) < 0 ||
165 		(code = param_end_write_collection(plto, string_key,
166 						   &copy.value.d)) < 0)
167 		break;
168 	    code = param_end_read_collection(plfrom, string_key,
169 					     &value.value.d);
170 	    break;
171 	case gs_param_type_string:
172 	    value.value.s.persistent &= copy_persists; goto ca;
173 	case gs_param_type_name:
174 	    value.value.n.persistent &= copy_persists; goto ca;
175 	case gs_param_type_int_array:
176 	    value.value.ia.persistent &= copy_persists; goto ca;
177 	case gs_param_type_float_array:
178 	    value.value.fa.persistent &= copy_persists; goto ca;
179 	case gs_param_type_string_array:
180 	    value.value.sa.persistent &= copy_persists;
181 	ca:
182 	default:
183 	    code = param_write_typed(plto, string_key, &value);
184 	}
185 	if (code < 0)
186 	    break;
187     }
188     return code;
189 }
190