xref: /plan9/sys/src/cmd/gs/src/zusparam.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 
2 /* Copyright (C) 1996, 2000 Aladdin Enterprises.  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   For more information about licensing, please refer to
12   http://www.ghostscript.com/licensing/. For information on
13   commercial licensing, go to http://www.artifex.com/licensing/ or
14   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
15   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
16 */
17 
18 /* $Id: zusparam.c,v 1.13 2004/08/04 19:36:13 stefan Exp $ */
19 /* User and system parameter operators */
20 #include "memory_.h"
21 #include "string_.h"
22 #include "ghost.h"
23 #include "oper.h"
24 #include "gscdefs.h"
25 #include "gsstruct.h"		/* for gxht.h */
26 #include "gsfont.h"		/* for user params */
27 #include "gxht.h"		/* for user params */
28 #include "gsutil.h"
29 #include "estack.h"
30 #include "ialloc.h"		/* for imemory for status */
31 #include "icontext.h"		/* for set_user_params prototype */
32 #include "idict.h"
33 #include "idparam.h"
34 #include "iparam.h"
35 #include "dstack.h"
36 #include "iname.h"
37 #include "itoken.h"
38 #include "iutil2.h"
39 #include "ivmem2.h"
40 #include "store.h"
41 
42 /* The (global) font directory */
43 extern gs_font_dir *ifont_dir;	/* in zfont.c */
44 
45 /* Define an individual user or system parameter. */
46 /* Eventually this will be made public. */
47 #define param_def_common\
48     const char *pname
49 
50 typedef struct param_def_s {
51     param_def_common;
52 } param_def_t;
53 
54 typedef struct long_param_def_s {
55     param_def_common;
56     long min_value, max_value;
57     long (*current)(i_ctx_t *);
58     int (*set)(i_ctx_t *, long);
59 } long_param_def_t;
60 
61 #if arch_sizeof_long > arch_sizeof_int
62 #  define MAX_UINT_PARAM max_uint
63 #else
64 #  define MAX_UINT_PARAM max_long
65 #endif
66 
67 typedef struct bool_param_def_s {
68     param_def_common;
69     bool (*current)(i_ctx_t *);
70     int (*set)(i_ctx_t *, bool);
71 } bool_param_def_t;
72 
73 typedef struct string_param_def_s {
74     param_def_common;
75     void (*current)(i_ctx_t *, gs_param_string *);
76     int (*set)(i_ctx_t *, gs_param_string *);
77 } string_param_def_t;
78 
79 /* Define a parameter set (user or system). */
80 typedef struct param_set_s {
81     const long_param_def_t *long_defs;
82     uint long_count;
83     const bool_param_def_t *bool_defs;
84     uint bool_count;
85     const string_param_def_t *string_defs;
86     uint string_count;
87 } param_set;
88 
89 /* Forward references */
90 private int setparams(i_ctx_t *, gs_param_list *, const param_set *);
91 private int currentparams(i_ctx_t *, const param_set *);
92 private int currentparam1(i_ctx_t *, const param_set *);
93 
94 /* ------ Passwords ------ */
95 
96 /* <string|int> .checkpassword <0|1|2> */
97 private int
zcheckpassword(i_ctx_t * i_ctx_p)98 zcheckpassword(i_ctx_t *i_ctx_p)
99 {
100     os_ptr op = osp;
101     ref params[2];
102     array_param_list list;
103     gs_param_list *const plist = (gs_param_list *)&list;
104     int result = 0;
105     int code = name_ref(imemory, (const byte *)"Password", 8, &params[0], 0);
106     password pass;
107 
108     if (code < 0)
109 	return code;
110     params[1] = *op;
111     array_param_list_read(&list, params, 2, NULL, false, iimemory);
112     if (dict_read_password(&pass, systemdict, "StartJobPassword") >= 0 &&
113 	param_check_password(plist, &pass) == 0
114 	)
115 	result = 1;
116     if (dict_read_password(&pass, systemdict, "SystemParamsPassword") >= 0 &&
117 	param_check_password(plist, &pass) == 0
118 	)
119 	result = 2;
120     iparam_list_release(&list);
121     make_int(op, result);
122     return 0;
123 }
124 
125 /* ------ System parameters ------ */
126 
127 /* Integer values */
128 private long
current_BuildTime(i_ctx_t * i_ctx_p)129 current_BuildTime(i_ctx_t *i_ctx_p)
130 {
131     return gs_buildtime;
132 }
133 private long
current_MaxFontCache(i_ctx_t * i_ctx_p)134 current_MaxFontCache(i_ctx_t *i_ctx_p)
135 {
136     return gs_currentcachesize(ifont_dir);
137 }
138 private int
set_MaxFontCache(i_ctx_t * i_ctx_p,long val)139 set_MaxFontCache(i_ctx_t *i_ctx_p, long val)
140 {
141     return gs_setcachesize(ifont_dir,
142 			   (uint)(val < 0 ? 0 : val > max_uint ? max_uint :
143 				   val));
144 }
145 private long
current_CurFontCache(i_ctx_t * i_ctx_p)146 current_CurFontCache(i_ctx_t *i_ctx_p)
147 {
148     uint cstat[7];
149 
150     gs_cachestatus(ifont_dir, cstat);
151     return cstat[0];
152 }
153 private long
current_MaxGlobalVM(i_ctx_t * i_ctx_p)154 current_MaxGlobalVM(i_ctx_t *i_ctx_p)
155 {
156     gs_memory_gc_status_t stat;
157 
158     gs_memory_gc_status(iimemory_global, &stat);
159     return stat.max_vm;
160 }
161 private int
set_MaxGlobalVM(i_ctx_t * i_ctx_p,long val)162 set_MaxGlobalVM(i_ctx_t *i_ctx_p, long val)
163 {
164     gs_memory_gc_status_t stat;
165 
166     gs_memory_gc_status(iimemory_global, &stat);
167     stat.max_vm = max(val, 0);
168     gs_memory_set_gc_status(iimemory_global, &stat);
169     return 0;
170 }
171 private long
current_Revision(i_ctx_t * i_ctx_p)172 current_Revision(i_ctx_t *i_ctx_p)
173 {
174     return gs_revision;
175 }
176 private const long_param_def_t system_long_params[] =
177 {
178     {"BuildTime", min_long, max_long, current_BuildTime, NULL},
179 {"MaxFontCache", 0, MAX_UINT_PARAM, current_MaxFontCache, set_MaxFontCache},
180     {"CurFontCache", 0, MAX_UINT_PARAM, current_CurFontCache, NULL},
181     {"Revision", min_long, max_long, current_Revision, NULL},
182     /* Extensions */
183     {"MaxGlobalVM", 0, max_long, current_MaxGlobalVM, set_MaxGlobalVM}
184 };
185 
186 /* Boolean values */
187 private bool
current_ByteOrder(i_ctx_t * i_ctx_p)188 current_ByteOrder(i_ctx_t *i_ctx_p)
189 {
190     return !arch_is_big_endian;
191 }
192 private const bool_param_def_t system_bool_params[] =
193 {
194     {"ByteOrder", current_ByteOrder, NULL}
195 };
196 
197 /* String values */
198 private void
current_RealFormat(i_ctx_t * i_ctx_p,gs_param_string * pval)199 current_RealFormat(i_ctx_t *i_ctx_p, gs_param_string * pval)
200 {
201 #if arch_floats_are_IEEE
202     static const char *const rfs = "IEEE";
203 #else
204     static const char *const rfs = "not IEEE";
205 #endif
206 
207     pval->data = (const byte *)rfs;
208     pval->size = strlen(rfs);
209     pval->persistent = true;
210 }
211 private const string_param_def_t system_string_params[] =
212 {
213     {"RealFormat", current_RealFormat, NULL}
214 };
215 
216 /* The system parameter set */
217 private const param_set system_param_set =
218 {
219     system_long_params, countof(system_long_params),
220     system_bool_params, countof(system_bool_params),
221     system_string_params, countof(system_string_params)
222 };
223 
224 /* <dict> .setsystemparams - */
225 private int
zsetsystemparams(i_ctx_t * i_ctx_p)226 zsetsystemparams(i_ctx_t *i_ctx_p)
227 {
228     os_ptr op = osp;
229     int code;
230     dict_param_list list;
231     gs_param_list *const plist = (gs_param_list *)&list;
232     password pass;
233 
234     check_type(*op, t_dictionary);
235     code = dict_param_list_read(&list, op, NULL, false, iimemory);
236     if (code < 0)
237 	return code;
238     code = dict_read_password(&pass, systemdict, "SystemParamsPassword");
239     if (code < 0)
240 	return code;
241     code = param_check_password(plist, &pass);
242     if (code != 0) {
243 	if (code > 0)
244 	    code = gs_note_error(e_invalidaccess);
245 	goto out;
246     }
247     code = param_read_password(plist, "StartJobPassword", &pass);
248     switch (code) {
249 	default:		/* invalid */
250 	    goto out;
251 	case 1:		/* missing */
252 	    break;
253 	case 0:
254 	    code = dict_write_password(&pass, systemdict,
255 				       "StartJobPassword",
256 				       ! i_ctx_p->LockFilePermissions);
257 	    if (code < 0)
258 		goto out;
259     }
260     code = param_read_password(plist, "SystemParamsPassword", &pass);
261     switch (code) {
262 	default:		/* invalid */
263 	    goto out;
264 	case 1:		/* missing */
265 	    break;
266 	case 0:
267 	    code = dict_write_password(&pass, systemdict,
268 				       "SystemParamsPassword",
269 				       ! i_ctx_p->LockFilePermissions);
270 	    if (code < 0)
271 		goto out;
272     }
273     code = setparams(i_ctx_p, plist, &system_param_set);
274   out:
275     iparam_list_release(&list);
276     if (code < 0)
277 	return code;
278     pop(1);
279     return 0;
280 }
281 
282 /* - .currentsystemparams <name1> <value1> ... */
283 private int
zcurrentsystemparams(i_ctx_t * i_ctx_p)284 zcurrentsystemparams(i_ctx_t *i_ctx_p)
285 {
286     return currentparams(i_ctx_p, &system_param_set);
287 }
288 
289 /* <name> .getsystemparam <value> */
290 private int
zgetsystemparam(i_ctx_t * i_ctx_p)291 zgetsystemparam(i_ctx_t *i_ctx_p)
292 {
293     return currentparam1(i_ctx_p, &system_param_set);
294 }
295 
296 /* ------ User parameters ------ */
297 
298 /* Integer values */
299 private long
current_JobTimeout(i_ctx_t * i_ctx_p)300 current_JobTimeout(i_ctx_t *i_ctx_p)
301 {
302     return 0;
303 }
304 private int
set_JobTimeout(i_ctx_t * i_ctx_p,long val)305 set_JobTimeout(i_ctx_t *i_ctx_p, long val)
306 {
307     return 0;
308 }
309 private long
current_MaxFontItem(i_ctx_t * i_ctx_p)310 current_MaxFontItem(i_ctx_t *i_ctx_p)
311 {
312     return gs_currentcacheupper(ifont_dir);
313 }
314 private int
set_MaxFontItem(i_ctx_t * i_ctx_p,long val)315 set_MaxFontItem(i_ctx_t *i_ctx_p, long val)
316 {
317     return gs_setcacheupper(ifont_dir, val);
318 }
319 private long
current_MinFontCompress(i_ctx_t * i_ctx_p)320 current_MinFontCompress(i_ctx_t *i_ctx_p)
321 {
322     return gs_currentcachelower(ifont_dir);
323 }
324 private int
set_MinFontCompress(i_ctx_t * i_ctx_p,long val)325 set_MinFontCompress(i_ctx_t *i_ctx_p, long val)
326 {
327     return gs_setcachelower(ifont_dir, val);
328 }
329 private long
current_MaxOpStack(i_ctx_t * i_ctx_p)330 current_MaxOpStack(i_ctx_t *i_ctx_p)
331 {
332     return ref_stack_max_count(&o_stack);
333 }
334 private int
set_MaxOpStack(i_ctx_t * i_ctx_p,long val)335 set_MaxOpStack(i_ctx_t *i_ctx_p, long val)
336 {
337     return ref_stack_set_max_count(&o_stack, val);
338 }
339 private long
current_MaxDictStack(i_ctx_t * i_ctx_p)340 current_MaxDictStack(i_ctx_t *i_ctx_p)
341 {
342     return ref_stack_max_count(&d_stack);
343 }
344 private int
set_MaxDictStack(i_ctx_t * i_ctx_p,long val)345 set_MaxDictStack(i_ctx_t *i_ctx_p, long val)
346 {
347     return ref_stack_set_max_count(&d_stack, val);
348 }
349 private long
current_MaxExecStack(i_ctx_t * i_ctx_p)350 current_MaxExecStack(i_ctx_t *i_ctx_p)
351 {
352     return ref_stack_max_count(&e_stack);
353 }
354 private int
set_MaxExecStack(i_ctx_t * i_ctx_p,long val)355 set_MaxExecStack(i_ctx_t *i_ctx_p, long val)
356 {
357     return ref_stack_set_max_count(&e_stack, val);
358 }
359 private long
current_MaxLocalVM(i_ctx_t * i_ctx_p)360 current_MaxLocalVM(i_ctx_t *i_ctx_p)
361 {
362     gs_memory_gc_status_t stat;
363 
364     gs_memory_gc_status(iimemory_local, &stat);
365     return stat.max_vm;
366 }
367 private int
set_MaxLocalVM(i_ctx_t * i_ctx_p,long val)368 set_MaxLocalVM(i_ctx_t *i_ctx_p, long val)
369 {
370     gs_memory_gc_status_t stat;
371 
372     gs_memory_gc_status(iimemory_local, &stat);
373     stat.max_vm = max(val, 0);
374     gs_memory_set_gc_status(iimemory_local, &stat);
375     return 0;
376 }
377 private long
current_VMReclaim(i_ctx_t * i_ctx_p)378 current_VMReclaim(i_ctx_t *i_ctx_p)
379 {
380     gs_memory_gc_status_t gstat, lstat;
381 
382     gs_memory_gc_status(iimemory_global, &gstat);
383     gs_memory_gc_status(iimemory_local, &lstat);
384     return (!gstat.enabled ? -2 : !lstat.enabled ? -1 : 0);
385 }
386 private long
current_VMThreshold(i_ctx_t * i_ctx_p)387 current_VMThreshold(i_ctx_t *i_ctx_p)
388 {
389     gs_memory_gc_status_t stat;
390 
391     gs_memory_gc_status(iimemory_local, &stat);
392     return stat.vm_threshold;
393 }
394 private long
current_WaitTimeout(i_ctx_t * i_ctx_p)395 current_WaitTimeout(i_ctx_t *i_ctx_p)
396 {
397     return 0;
398 }
399 private int
set_WaitTimeout(i_ctx_t * i_ctx_p,long val)400 set_WaitTimeout(i_ctx_t *i_ctx_p, long val)
401 {
402     return 0;
403 }
404 private long
current_MinScreenLevels(i_ctx_t * i_ctx_p)405 current_MinScreenLevels(i_ctx_t *i_ctx_p)
406 {
407     return gs_currentminscreenlevels();
408 }
409 private int
set_MinScreenLevels(i_ctx_t * i_ctx_p,long val)410 set_MinScreenLevels(i_ctx_t *i_ctx_p, long val)
411 {
412     gs_setminscreenlevels((uint) val);
413     return 0;
414 }
415 private long
current_AlignToPixels(i_ctx_t * i_ctx_p)416 current_AlignToPixels(i_ctx_t *i_ctx_p)
417 {
418     return gs_currentaligntopixels(ifont_dir);
419 }
420 private int
set_AlignToPixels(i_ctx_t * i_ctx_p,long val)421 set_AlignToPixels(i_ctx_t *i_ctx_p, long val)
422 {
423     gs_setaligntopixels(ifont_dir, (uint)val);
424     return 0;
425 }
426 private long
current_GridFitTT(i_ctx_t * i_ctx_p)427 current_GridFitTT(i_ctx_t *i_ctx_p)
428 {
429     return gs_currentgridfittt(ifont_dir);
430 }
431 private int
set_GridFitTT(i_ctx_t * i_ctx_p,long val)432 set_GridFitTT(i_ctx_t *i_ctx_p, long val)
433 {
434     gs_setgridfittt(ifont_dir, (uint)val);
435     return 0;
436 }
437 private const long_param_def_t user_long_params[] =
438 {
439     {"JobTimeout", 0, MAX_UINT_PARAM,
440      current_JobTimeout, set_JobTimeout},
441     {"MaxFontItem", 0, MAX_UINT_PARAM,
442      current_MaxFontItem, set_MaxFontItem},
443     {"MinFontCompress", 0, MAX_UINT_PARAM,
444      current_MinFontCompress, set_MinFontCompress},
445     {"MaxOpStack", 0, MAX_UINT_PARAM,
446      current_MaxOpStack, set_MaxOpStack},
447     {"MaxDictStack", 0, MAX_UINT_PARAM,
448      current_MaxDictStack, set_MaxDictStack},
449     {"MaxExecStack", 0, MAX_UINT_PARAM,
450      current_MaxExecStack, set_MaxExecStack},
451     {"MaxLocalVM", 0, max_long,
452      current_MaxLocalVM, set_MaxLocalVM},
453     {"VMReclaim", -2, 0,
454      current_VMReclaim, set_vm_reclaim},
455     {"VMThreshold", -1, max_long,
456      current_VMThreshold, set_vm_threshold},
457     {"WaitTimeout", 0, MAX_UINT_PARAM,
458      current_WaitTimeout, set_WaitTimeout},
459     /* Extensions */
460     {"MinScreenLevels", 0, MAX_UINT_PARAM,
461      current_MinScreenLevels, set_MinScreenLevels},
462     {"AlignToPixels", 0, 1,
463      current_AlignToPixels, set_AlignToPixels},
464     {"GridFitTT", 0, 3,
465      current_GridFitTT, set_GridFitTT}
466 };
467 
468 /* Boolean values */
469 private bool
current_AccurateScreens(i_ctx_t * i_ctx_p)470 current_AccurateScreens(i_ctx_t *i_ctx_p)
471 {
472     return gs_currentaccuratescreens();
473 }
474 private int
set_AccurateScreens(i_ctx_t * i_ctx_p,bool val)475 set_AccurateScreens(i_ctx_t *i_ctx_p, bool val)
476 {
477     gs_setaccuratescreens(val);
478     return 0;
479 }
480 /* Boolean values */
481 private bool
current_UseWTS(i_ctx_t * i_ctx_p)482 current_UseWTS(i_ctx_t *i_ctx_p)
483 {
484     return gs_currentusewts();
485 }
486 private int
set_UseWTS(i_ctx_t * i_ctx_p,bool val)487 set_UseWTS(i_ctx_t *i_ctx_p, bool val)
488 {
489     gs_setusewts(val);
490     return 0;
491 }
492 private bool
current_LockFilePermissions(i_ctx_t * i_ctx_p)493 current_LockFilePermissions(i_ctx_t *i_ctx_p)
494 {
495     return i_ctx_p->LockFilePermissions;
496 }
497 private int
set_LockFilePermissions(i_ctx_t * i_ctx_p,bool val)498 set_LockFilePermissions(i_ctx_t *i_ctx_p, bool val)
499 {
500     /* allow locking even if already locked */
501     if (i_ctx_p->LockFilePermissions && !val)
502 	return_error(e_invalidaccess);
503     i_ctx_p->LockFilePermissions = val;
504     return 0;
505 }
506 private const bool_param_def_t user_bool_params[] =
507 {
508     {"AccurateScreens", current_AccurateScreens, set_AccurateScreens},
509     {"UseWTS", current_UseWTS, set_UseWTS},
510     {"LockFilePermissions", current_LockFilePermissions, set_LockFilePermissions}
511 };
512 
513 /* The user parameter set */
514 private const param_set user_param_set =
515 {
516     user_long_params, countof(user_long_params),
517     user_bool_params, countof(user_bool_params),
518     0, 0
519 };
520 
521 /* <dict> .setuserparams - */
522 /* We break this out for use when switching contexts. */
523 int
set_user_params(i_ctx_t * i_ctx_p,const ref * paramdict)524 set_user_params(i_ctx_t *i_ctx_p, const ref *paramdict)
525 {
526     dict_param_list list;
527     int code;
528 
529     check_type(*paramdict, t_dictionary);
530     code = dict_param_list_read(&list, paramdict, NULL, false, iimemory);
531     if (code < 0)
532 	return code;
533     code = setparams(i_ctx_p, (gs_param_list *)&list, &user_param_set);
534     iparam_list_release(&list);
535     return code;
536 }
537 private int
zsetuserparams(i_ctx_t * i_ctx_p)538 zsetuserparams(i_ctx_t *i_ctx_p)
539 {
540     os_ptr op = osp;
541     int code = set_user_params(i_ctx_p, op);
542 
543     if (code >= 0) {
544 	/* Update cached scanner options. */
545 	i_ctx_p->scanner_options =
546 	    ztoken_scanner_options(op, i_ctx_p->scanner_options);
547 	pop(1);
548     }
549     return code;
550 }
551 
552 /* - .currentuserparams <name1> <value1> ... */
553 private int
zcurrentuserparams(i_ctx_t * i_ctx_p)554 zcurrentuserparams(i_ctx_t *i_ctx_p)
555 {
556     return currentparams(i_ctx_p, &user_param_set);
557 }
558 
559 /* <name> .getuserparam <value> */
560 private int
zgetuserparam(i_ctx_t * i_ctx_p)561 zgetuserparam(i_ctx_t *i_ctx_p)
562 {
563     return currentparam1(i_ctx_p, &user_param_set);
564 }
565 
566 /* ------ Initialization procedure ------ */
567 
568 const op_def zusparam_op_defs[] =
569 {
570 	/* User and system parameters are accessible even in Level 1 */
571 	/* (if this is a Level 2 system). */
572     {"0.currentsystemparams", zcurrentsystemparams},
573     {"0.currentuserparams", zcurrentuserparams},
574     {"1.getsystemparam", zgetsystemparam},
575     {"1.getuserparam", zgetuserparam},
576     {"1.setsystemparams", zsetsystemparams},
577     {"1.setuserparams", zsetuserparams},
578 	/* The rest of the operators are defined only in Level 2. */
579     op_def_begin_level2(),
580     {"1.checkpassword", zcheckpassword},
581     op_def_end(0)
582 };
583 
584 /* ------ Internal procedures ------ */
585 
586 /* Set the values of a parameter set from a parameter list. */
587 /* We don't attempt to back out if anything fails. */
588 private int
setparams(i_ctx_t * i_ctx_p,gs_param_list * plist,const param_set * pset)589 setparams(i_ctx_t *i_ctx_p, gs_param_list * plist, const param_set * pset)
590 {
591     int i, code;
592 
593     for (i = 0; i < pset->long_count; i++) {
594 	const long_param_def_t *pdef = &pset->long_defs[i];
595 	long val;
596 
597 	if (pdef->set == NULL)
598 	    continue;
599 	code = param_read_long(plist, pdef->pname, &val);
600 	switch (code) {
601 	    default:		/* invalid */
602 		return code;
603 	    case 1:		/* missing */
604 		break;
605 	    case 0:
606 		if (val < pdef->min_value || val > pdef->max_value)
607 		    return_error(e_rangecheck);
608 		code = (*pdef->set)(i_ctx_p, val);
609 		if (code < 0)
610 		    return code;
611 	}
612     }
613     for (i = 0; i < pset->bool_count; i++) {
614 	const bool_param_def_t *pdef = &pset->bool_defs[i];
615 	bool val;
616 
617 	if (pdef->set == NULL)
618 	    continue;
619 	code = param_read_bool(plist, pdef->pname, &val);
620 	if (code == 0)
621 	    code = (*pdef->set)(i_ctx_p, val);
622 	if (code < 0)
623 	    return code;
624     }
625 /****** WE SHOULD DO STRINGS AND STRING ARRAYS, BUT WE DON'T YET ******/
626     return 0;
627 }
628 
629 /* Get the current values of a parameter set to the stack. */
630 private bool
pname_matches(const char * pname,const ref * psref)631 pname_matches(const char *pname, const ref * psref)
632 {
633     return
634 	(psref == 0 ||
635 	 !bytes_compare((const byte *)pname, strlen(pname),
636 			psref->value.const_bytes, r_size(psref)));
637 }
638 private int
current_param_list(i_ctx_t * i_ctx_p,const param_set * pset,const ref * psref)639 current_param_list(i_ctx_t *i_ctx_p, const param_set * pset,
640 		   const ref * psref /*t_string */ )
641 {
642     stack_param_list list;
643     gs_param_list *const plist = (gs_param_list *)&list;
644     int i;
645 
646     stack_param_list_write(&list, &o_stack, NULL, iimemory);
647     for (i = 0; i < pset->long_count; i++) {
648 	const char *pname = pset->long_defs[i].pname;
649 
650 	if (pname_matches(pname, psref)) {
651 	    long val = (*pset->long_defs[i].current)(i_ctx_p);
652 	    int code = param_write_long(plist, pname, &val);
653 
654 	    if (code < 0)
655 		return code;
656 	}
657     }
658     for (i = 0; i < pset->bool_count; i++) {
659 	const char *pname = pset->bool_defs[i].pname;
660 
661 	if (pname_matches(pname, psref)) {
662 	    bool val = (*pset->bool_defs[i].current)(i_ctx_p);
663 	    int code = param_write_bool(plist, pname, &val);
664 
665 	    if (code < 0)
666 		return code;
667 	}
668     }
669     for (i = 0; i < pset->string_count; i++) {
670 	const char *pname = pset->string_defs[i].pname;
671 
672 	if (pname_matches(pname, psref)) {
673 	    gs_param_string val;
674 	    int code;
675 
676 	    (*pset->string_defs[i].current)(i_ctx_p, &val);
677 	    code = param_write_string(plist, pname, &val);
678 	    if (code < 0)
679 		return code;
680 	}
681     }
682     return 0;
683 }
684 
685 /* Get the current values of a parameter set to the stack. */
686 private int
currentparams(i_ctx_t * i_ctx_p,const param_set * pset)687 currentparams(i_ctx_t *i_ctx_p, const param_set * pset)
688 {
689     return current_param_list(i_ctx_p, pset, NULL);
690 }
691 
692 /* Get the value of a single parameter to the stack, or signal an error. */
693 private int
currentparam1(i_ctx_t * i_ctx_p,const param_set * pset)694 currentparam1(i_ctx_t *i_ctx_p, const param_set * pset)
695 {
696     os_ptr op = osp;
697     ref sref;
698     int code;
699 
700     check_type(*op, t_name);
701     check_ostack(2);
702     name_string_ref(imemory, (const ref *)op, &sref);
703     code = current_param_list(i_ctx_p, pset, &sref);
704     if (code < 0)
705 	return code;
706     if (osp == op)
707 	return_error(e_undefined);
708     /* We know osp == op + 2. */
709     ref_assign(op, op + 2);
710     pop(2);
711     return code;
712 }
713