xref: /plan9-contrib/sys/src/cmd/gs/src/gsparam.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
13ff48bf5SDavid du Colombier /* Copyright (C) 1993, 2000 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gsparam.h,v 1.13 2005/09/05 13:58:55 leonardo Exp $ */
187dd7cddfSDavid du Colombier /* Client interface to parameter dictionaries */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier #ifndef gsparam_INCLUDED
217dd7cddfSDavid du Colombier #  define gsparam_INCLUDED
227dd7cddfSDavid du Colombier 
233ff48bf5SDavid du Colombier #include "gsstype.h"
243ff48bf5SDavid du Colombier 
257dd7cddfSDavid du Colombier /*
267dd7cddfSDavid du Colombier  * Several interfaces use parameter dictionaries to communicate sets of
277dd7cddfSDavid du Colombier  * (key, value) pairs between a client and an object with complex state.
287dd7cddfSDavid du Colombier  * (Several of these correspond directly to similar interfaces in the
297dd7cddfSDavid du Colombier  * PostScript language.) This file defines the API for parameter dictionaries.
307dd7cddfSDavid du Colombier  */
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier /* ---------------- Generic interfaces ---------------- */
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier /* Define the abstract type for a parameter list. */
357dd7cddfSDavid du Colombier #ifndef gs_param_list_DEFINED
367dd7cddfSDavid du Colombier #  define gs_param_list_DEFINED
377dd7cddfSDavid du Colombier typedef struct gs_param_list_s gs_param_list;
387dd7cddfSDavid du Colombier #endif
397dd7cddfSDavid du Colombier 
407dd7cddfSDavid du Colombier /* Define the type for a parameter key name. */
417dd7cddfSDavid du Colombier typedef const char *gs_param_name;
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier /*
447dd7cddfSDavid du Colombier  * Parameter values fall into three categories:
457dd7cddfSDavid du Colombier  *      - Scalar (null, Boolean, int, long, float);
467dd7cddfSDavid du Colombier  *      - Homogenous collection (string/name, int array, float array,
477dd7cddfSDavid du Colombier  *      string/name array);
487dd7cddfSDavid du Colombier  *      - Heterogenous collection (dictionary, int-keyed dictionary, array).
497dd7cddfSDavid du Colombier  * Each category has its own representation and memory management issues.
507dd7cddfSDavid du Colombier  */
517dd7cddfSDavid du Colombier typedef enum {
527dd7cddfSDavid du Colombier     /* Scalar */
537dd7cddfSDavid du Colombier     gs_param_type_null, gs_param_type_bool, gs_param_type_int,
547dd7cddfSDavid du Colombier     gs_param_type_long, gs_param_type_float,
557dd7cddfSDavid du Colombier     /* Homogenous collection */
567dd7cddfSDavid du Colombier     gs_param_type_string, gs_param_type_name,
577dd7cddfSDavid du Colombier     gs_param_type_int_array, gs_param_type_float_array,
587dd7cddfSDavid du Colombier     gs_param_type_string_array, gs_param_type_name_array,
597dd7cddfSDavid du Colombier     /* Heterogenous collection */
607dd7cddfSDavid du Colombier     gs_param_type_dict, gs_param_type_dict_int_keys, gs_param_type_array
617dd7cddfSDavid du Colombier } gs_param_type;
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier /* Define a "don't care" type for reading typed values. */
647dd7cddfSDavid du Colombier #define gs_param_type_any ((gs_param_type)-1)
657dd7cddfSDavid du Colombier 
667dd7cddfSDavid du Colombier /*
677dd7cddfSDavid du Colombier  * Define the structures for homogenous collection values
687dd7cddfSDavid du Colombier  * (string/name, integer array, or floating point array).
697dd7cddfSDavid du Colombier  * The size is the number of elements, not the size in bytes.
707dd7cddfSDavid du Colombier  * A value is persistent if it is defined as static const,
717dd7cddfSDavid du Colombier  * or if it is allocated in garbage-collectable space and never freed.
727dd7cddfSDavid du Colombier  */
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier #define _param_array_struct(sname,etype)\
757dd7cddfSDavid du Colombier   struct sname { const etype *data; uint size; bool persistent; }
767dd7cddfSDavid du Colombier typedef _param_array_struct(gs_param_int_array_s, int) gs_param_int_array;
777dd7cddfSDavid du Colombier typedef _param_array_struct(gs_param_float_array_s, float) gs_param_float_array;
787dd7cddfSDavid du Colombier typedef _param_array_struct(gs_param_string_array_s, gs_param_string) gs_param_string_array;
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier #define param_string_from_string(ps, str)\
817dd7cddfSDavid du Colombier   ((ps).data = (const byte *)(str),\
827dd7cddfSDavid du Colombier    (ps).size = strlen((const char *)(ps).data),\
837dd7cddfSDavid du Colombier    (ps).persistent = true)
847dd7cddfSDavid du Colombier 
853ff48bf5SDavid du Colombier #define param_string_from_transient_string(ps, str)\
863ff48bf5SDavid du Colombier   ((ps).data = (const byte *)(str),\
873ff48bf5SDavid du Colombier    (ps).size = strlen((const char *)(ps).data),\
883ff48bf5SDavid du Colombier    (ps).persistent = false)
893ff48bf5SDavid du Colombier 
907dd7cddfSDavid du Colombier /*
917dd7cddfSDavid du Colombier  * Define the structure for heterogenous collection values (dictionaries
927dd7cddfSDavid du Colombier  * and heterogenous arrays).
937dd7cddfSDavid du Colombier  */
947dd7cddfSDavid du Colombier typedef struct gs_param_collection_s {
957dd7cddfSDavid du Colombier     gs_param_list *list;
967dd7cddfSDavid du Colombier     uint size;
977dd7cddfSDavid du Colombier } gs_param_collection;
987dd7cddfSDavid du Colombier typedef gs_param_collection gs_param_dict;
997dd7cddfSDavid du Colombier typedef gs_param_collection gs_param_array;
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier /*
1027dd7cddfSDavid du Colombier  * Define the sizes of the various parameter value types, indexed by type.
1037dd7cddfSDavid du Colombier  */
1047dd7cddfSDavid du Colombier #define GS_PARAM_TYPE_SIZES(dict_size)\
1057dd7cddfSDavid du Colombier   0, sizeof(bool), sizeof(int), sizeof(long), sizeof(float),\
1067dd7cddfSDavid du Colombier   sizeof(gs_param_string), sizeof(gs_param_string),\
1077dd7cddfSDavid du Colombier   sizeof(gs_param_int_array), sizeof(gs_param_float_array),\
1087dd7cddfSDavid du Colombier   sizeof(gs_param_string_array), sizeof(gs_param_string_array),\
1097dd7cddfSDavid du Colombier   (dict_size), (dict_size), (dict_size)
1107dd7cddfSDavid du Colombier /*
1117dd7cddfSDavid du Colombier  * Define the sizes of the underlying data types contained in or pointed
1127dd7cddfSDavid du Colombier  * to by the various value types.
1137dd7cddfSDavid du Colombier  */
1147dd7cddfSDavid du Colombier #define GS_PARAM_TYPE_BASE_SIZES(dict_elt_size)\
1157dd7cddfSDavid du Colombier   0, sizeof(bool), sizeof(int), sizeof(long), sizeof(float),\
1167dd7cddfSDavid du Colombier   1, 1, sizeof(int), sizeof(float),\
1177dd7cddfSDavid du Colombier   sizeof(gs_param_string), sizeof(gs_param_string),\
1187dd7cddfSDavid du Colombier   (dict_elt_size), (dict_elt_size), (dict_elt_size)
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier /* Define tables with 0 for the sizes of the heterogenous collections. */
1217dd7cddfSDavid du Colombier extern const byte gs_param_type_sizes[];
1227dd7cddfSDavid du Colombier extern const byte gs_param_type_base_sizes[];
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier /* Define a union capable of holding any parameter value. */
1257dd7cddfSDavid du Colombier #define GS_PARAM_VALUE_UNION(dict_type)\
1267dd7cddfSDavid du Colombier 	bool b;\
1277dd7cddfSDavid du Colombier 	int i;\
1287dd7cddfSDavid du Colombier 	long l;\
1297dd7cddfSDavid du Colombier 	float f;\
1307dd7cddfSDavid du Colombier 	gs_param_string s;\
1317dd7cddfSDavid du Colombier 	gs_param_string n;\
1327dd7cddfSDavid du Colombier 	gs_param_int_array ia;\
1337dd7cddfSDavid du Colombier 	gs_param_float_array fa;\
1347dd7cddfSDavid du Colombier 	gs_param_string_array sa;\
1357dd7cddfSDavid du Colombier 	gs_param_string_array na;\
1367dd7cddfSDavid du Colombier 	dict_type d
1377dd7cddfSDavid du Colombier typedef union gs_param_value_s {
1387dd7cddfSDavid du Colombier     GS_PARAM_VALUE_UNION(gs_param_collection);
1397dd7cddfSDavid du Colombier } gs_param_value;
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier /*
1427dd7cddfSDavid du Colombier  * Define a structure containing a dynamically typed value (a value along
1433ff48bf5SDavid du Colombier  * with its type).
1447dd7cddfSDavid du Colombier  */
1457dd7cddfSDavid du Colombier typedef struct gs_param_typed_value_s {
1467dd7cddfSDavid du Colombier     gs_param_value value;
1477dd7cddfSDavid du Colombier     gs_param_type type;
1487dd7cddfSDavid du Colombier } gs_param_typed_value;
1493ff48bf5SDavid du Colombier /*
1503ff48bf5SDavid du Colombier  * Garbage collection of gs_param_values depends on the value type and on
1513ff48bf5SDavid du Colombier  * the 'd' member of the union.  We provide enum_ptrs and reloc_ptrs
1523ff48bf5SDavid du Colombier  * procedures that handle all the other cases -- i.e., cases other than
1533ff48bf5SDavid du Colombier  * heterogenous collections.
1543ff48bf5SDavid du Colombier  */
1553ff48bf5SDavid du Colombier struct_proc_enum_ptrs(gs_param_typed_value_enum_ptrs);
1563ff48bf5SDavid du Colombier struct_proc_reloc_ptrs(gs_param_typed_value_reloc_ptrs);
1573ff48bf5SDavid du Colombier #define gs_param_typed_value_max_ptrs 1
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier /*
1607dd7cddfSDavid du Colombier  * Define the representation alternatives for heterogenous collections.
1617dd7cddfSDavid du Colombier  * _any must be 0, for Boolean testing.
1627dd7cddfSDavid du Colombier  */
1637dd7cddfSDavid du Colombier typedef enum {
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier     /* Create or accept a general dictionary. */
1667dd7cddfSDavid du Colombier 
1677dd7cddfSDavid du Colombier     gs_param_collection_dict_any = 0,
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier     /* Create a dictionary with integer string keys ("0", "1", ...); */
1707dd7cddfSDavid du Colombier     /* accept a dictionary with integer string keys, or a heterogenous */
1717dd7cddfSDavid du Colombier     /* array. */
1727dd7cddfSDavid du Colombier 
1737dd7cddfSDavid du Colombier     gs_param_collection_dict_int_keys = 1,
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier     /* Create an array if possible, otherwise a dictionary with integer */
1767dd7cddfSDavid du Colombier     /* string keys; accept the same types as dict_int_keys. */
1777dd7cddfSDavid du Colombier 
1787dd7cddfSDavid du Colombier     gs_param_collection_array = 2
1797dd7cddfSDavid du Colombier 
1807dd7cddfSDavid du Colombier } gs_param_collection_type_t;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier /*
1837dd7cddfSDavid du Colombier  * Define the 'policies' for handling out-of-range parameter values.
1847dd7cddfSDavid du Colombier  * This is not an enum, because some parameters may recognize other values.
1857dd7cddfSDavid du Colombier  */
1867dd7cddfSDavid du Colombier #define gs_param_policy_signal_error 0
1877dd7cddfSDavid du Colombier #define gs_param_policy_ignore 1
1887dd7cddfSDavid du Colombier #define gs_param_policy_consult_user 2
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier /*
1917dd7cddfSDavid du Colombier  * Define an enumerator used to iterate through the keys in a list.
1927dd7cddfSDavid du Colombier  *
1937dd7cddfSDavid du Colombier  * All the members of the union must be used such that memset(0) entire
1947dd7cddfSDavid du Colombier  * union means 'beginning of enumeration'.
1957dd7cddfSDavid du Colombier  */
1967dd7cddfSDavid du Colombier typedef union gs_param_enumerator_s {
1977dd7cddfSDavid du Colombier     int intval;
1987dd7cddfSDavid du Colombier     long longval;
1997dd7cddfSDavid du Colombier     void *pvoid;
2007dd7cddfSDavid du Colombier     char *pchar;
2017dd7cddfSDavid du Colombier } gs_param_enumerator_t;
2023ff48bf5SDavid du Colombier typedef gs_param_string gs_param_key_t;
2037dd7cddfSDavid du Colombier 
2047dd7cddfSDavid du Colombier /*
2057dd7cddfSDavid du Colombier  * Define the object procedures.  Note that the same interface is used
2067dd7cddfSDavid du Colombier  * both for getting and for setting parameter values.  (This is a bit
2077dd7cddfSDavid du Colombier  * of a hack, and we might change it someday.)  The procedures return
2087dd7cddfSDavid du Colombier  * as follows:
2097dd7cddfSDavid du Colombier  *      - 'reading' procedures ('put' operations from the client's viewpoint)
2107dd7cddfSDavid du Colombier  * return 1 for a missing parameter, 0 for a valid parameter, <0 on error.
2117dd7cddfSDavid du Colombier  *      - 'writing' procedures ('get' operations from the client's viewpoint)
2127dd7cddfSDavid du Colombier  * return 0 or 1 if successful, <0 on error.
2137dd7cddfSDavid du Colombier  *
2147dd7cddfSDavid du Colombier  * A lazy implementation can use the default procedures for scalar and
2157dd7cddfSDavid du Colombier  * homogenous collection types: these just called xmit_typed.
2167dd7cddfSDavid du Colombier  */
2177dd7cddfSDavid du Colombier 
2187dd7cddfSDavid du Colombier /*
2197dd7cddfSDavid du Colombier  * Transmitting variable-size objects requires some extra care.
2207dd7cddfSDavid du Colombier  *      - When writing an array, string, name, or dictionary, the
2217dd7cddfSDavid du Colombier  * implementation (not the client) sets all the fields of the value.
2227dd7cddfSDavid du Colombier  *      - When reading an array, string, or name, the client must set
2237dd7cddfSDavid du Colombier  * all the fields of the value.
2247dd7cddfSDavid du Colombier  *      - When reading a dictionary, the client must set the size field
2257dd7cddfSDavid du Colombier  * before calling begin_write_dict; the implementation of begin_write_dict
2267dd7cddfSDavid du Colombier  * allocates the list.
2277dd7cddfSDavid du Colombier  */
2287dd7cddfSDavid du Colombier 
2297dd7cddfSDavid du Colombier /*
2307dd7cddfSDavid du Colombier  * Setting parameters must use a "two-phase commit" policy.  Specifically,
2317dd7cddfSDavid du Colombier  * any put_params procedure must observe the following discipline:
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier  1. For each parameter known to the device, ask the parameter list if
2347dd7cddfSDavid du Colombier  there is a new value, and if so, make all necessary validity checks.  If any
2357dd7cddfSDavid du Colombier  check fails, call param_signal_error for that parameter, but continue to
2367dd7cddfSDavid du Colombier  check further parameters.  Normally, this step should not alter the state of
2377dd7cddfSDavid du Colombier  the device; however, if the device allows changing any parameters that are
2387dd7cddfSDavid du Colombier  read-only by default (for example, BitsPerPixel or ProcessColorModel), or if
2397dd7cddfSDavid du Colombier  it replaces the default put_params behavior for any parameter (for example,
2407dd7cddfSDavid du Colombier  if it handles MediaSize or Resolution itself to forestall the normal closing
2417dd7cddfSDavid du Colombier  of the device when these are set), step 1 of put_params must change the
2427dd7cddfSDavid du Colombier  parameters in the device state, and step 2 must undo the changes if
2437dd7cddfSDavid du Colombier  returning an error.
2447dd7cddfSDavid du Colombier 
2457dd7cddfSDavid du Colombier  2. Call the "superclass" put_params routine.  For printer devices,
2467dd7cddfSDavid du Colombier  this is gdev_prn_put_params; for other devices, it is gx_default_put_params.
2477dd7cddfSDavid du Colombier  Note that this must be done even if errors were detected in step 1.  If this
2487dd7cddfSDavid du Colombier  routine returns an error code, or if step 1 detected an error, undo any
2497dd7cddfSDavid du Colombier  changes that step 1 made in the device state, and return the error code.
2507dd7cddfSDavid du Colombier 
2517dd7cddfSDavid du Colombier  3. Install the new parameter values in the device.  If necessary,
2527dd7cddfSDavid du Colombier  close the device first; a higher-level routine (gs_putdeviceparams) will
2537dd7cddfSDavid du Colombier  reopen the device if necessary.
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier  */
2567dd7cddfSDavid du Colombier 
2577dd7cddfSDavid du Colombier typedef struct gs_param_list_procs_s {
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier     /* Transmit a typed value. */
2607dd7cddfSDavid du Colombier     /*
2617dd7cddfSDavid du Colombier      * Note that read/write_typed do a begin_read/write_collection
2627dd7cddfSDavid du Colombier      * if the type is one of the heterogenous collection types.
2637dd7cddfSDavid du Colombier      * Note also that even for reading, the caller must set pvalue->type
2647dd7cddfSDavid du Colombier      * to the desired type or to gs_param_type_any.
2657dd7cddfSDavid du Colombier      */
2667dd7cddfSDavid du Colombier 
2677dd7cddfSDavid du Colombier #define param_proc_xmit_typed(proc)\
268*593dc095SDavid du Colombier     int proc(gs_param_list *, gs_param_name, gs_param_typed_value *)
2697dd7cddfSDavid du Colombier 	 param_proc_xmit_typed((*xmit_typed));
2707dd7cddfSDavid du Colombier 	 /* See below for param_read_[requested_]typed */
2717dd7cddfSDavid du Colombier #define param_write_typed(plist, pkey, pvalue)\
2727dd7cddfSDavid du Colombier 	 (*(plist)->procs->xmit_typed)(plist, pkey, pvalue)
2737dd7cddfSDavid du Colombier 
2747dd7cddfSDavid du Colombier 	 /* Start transmitting a dictionary or heterogenous value. */
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier #define param_proc_begin_xmit_collection(proc)\
277*593dc095SDavid du Colombier 	 int proc(gs_param_list *, gs_param_name, gs_param_dict *,\
278*593dc095SDavid du Colombier 		     gs_param_collection_type_t)
2797dd7cddfSDavid du Colombier 	 param_proc_begin_xmit_collection((*begin_xmit_collection));
2807dd7cddfSDavid du Colombier #define param_begin_read_collection(plist, pkey, pvalue, coll_type)\
2817dd7cddfSDavid du Colombier 	 (*(plist)->procs->begin_xmit_collection)(plist, pkey, pvalue, coll_type)
2827dd7cddfSDavid du Colombier #define param_begin_read_dict(l, k, v, int_keys)\
2837dd7cddfSDavid du Colombier 	 param_begin_read_collection(l, k, v,\
2847dd7cddfSDavid du Colombier 				     (int_keys ? gs_param_collection_dict_int_keys :\
2857dd7cddfSDavid du Colombier 				      gs_param_collection_dict_any))
2867dd7cddfSDavid du Colombier #define param_begin_write_collection(plist, pkey, pvalue, coll_type)\
2877dd7cddfSDavid du Colombier 	 (*(plist)->procs->begin_xmit_collection)(plist, pkey, pvalue, coll_type)
2887dd7cddfSDavid du Colombier #define param_begin_write_dict(l, k, v, int_keys)\
2897dd7cddfSDavid du Colombier 	 param_begin_write_collection(l, k, v,\
2907dd7cddfSDavid du Colombier 				      (int_keys ? gs_param_collection_dict_int_keys :\
2917dd7cddfSDavid du Colombier 				       gs_param_collection_dict_any))
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier 	 /* Finish transmitting a collection value. */
2947dd7cddfSDavid du Colombier 
2957dd7cddfSDavid du Colombier #define param_proc_end_xmit_collection(proc)\
296*593dc095SDavid du Colombier 	 int proc(gs_param_list *, gs_param_name, gs_param_dict *)
2977dd7cddfSDavid du Colombier 	 param_proc_end_xmit_collection((*end_xmit_collection));
2987dd7cddfSDavid du Colombier #define param_end_read_collection(plist, pkey, pvalue)\
2997dd7cddfSDavid du Colombier 	 (*(plist)->procs->end_xmit_collection)(plist, pkey, pvalue)
3007dd7cddfSDavid du Colombier #define param_end_read_dict(l, k, v) param_end_read_collection(l, k, v)
3017dd7cddfSDavid du Colombier #define param_end_write_collection(plist, pkey, pvalue)\
3027dd7cddfSDavid du Colombier 	 (*(plist)->procs->end_xmit_collection)(plist, pkey, pvalue)
3037dd7cddfSDavid du Colombier #define param_end_write_dict(l, k, v) param_end_write_collection(l, k, v)
3047dd7cddfSDavid du Colombier 
3057dd7cddfSDavid du Colombier 	 /*
3067dd7cddfSDavid du Colombier 	  * Get the next key in sequence.
3077dd7cddfSDavid du Colombier 	  * (Only used when reading.)
3087dd7cddfSDavid du Colombier 	  * Use param_init_enumerator(...) to reset to first key.
3097dd7cddfSDavid du Colombier 	  */
3107dd7cddfSDavid du Colombier 
3117dd7cddfSDavid du Colombier #define param_proc_next_key(proc)\
312*593dc095SDavid du Colombier 	 int proc(gs_param_list *, gs_param_enumerator_t *, gs_param_key_t *)
3137dd7cddfSDavid du Colombier 	 param_proc_next_key((*next_key));
3147dd7cddfSDavid du Colombier #define param_get_next_key(plist, penum, pkey)\
3157dd7cddfSDavid du Colombier 	 (*(plist)->procs->next_key)(plist, penum, pkey)
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	 /*
3187dd7cddfSDavid du Colombier 	  * Request a specific parameter. (Only used when writing, before
3197dd7cddfSDavid du Colombier 	  * writing any values.)  If no specific parameters are requested,
3207dd7cddfSDavid du Colombier 	  * param_requested always returns -1; if specific parameters
3217dd7cddfSDavid du Colombier 	  * are requested, param_requested will return 1 for those,
3227dd7cddfSDavid du Colombier 	  * and may return either 0 or 1 for others.
3237dd7cddfSDavid du Colombier 	  */
3247dd7cddfSDavid du Colombier 
3257dd7cddfSDavid du Colombier #define param_proc_request(proc)\
326*593dc095SDavid du Colombier   int proc(gs_param_list *, gs_param_name)
3277dd7cddfSDavid du Colombier 	 param_proc_request((*request));
3287dd7cddfSDavid du Colombier 
3297dd7cddfSDavid du Colombier #define param_request(plist, pkey)\
3307dd7cddfSDavid du Colombier   ((plist)->procs->request(plist, pkey))
3317dd7cddfSDavid du Colombier 
3327dd7cddfSDavid du Colombier 	 /*
3337dd7cddfSDavid du Colombier 	  * Determine whether a given key has been requested.  (Only used
3347dd7cddfSDavid du Colombier 	  * when writing.)  A return value of -1 means that no specific
3357dd7cddfSDavid du Colombier 	  * parameters have been requested; 0 means specific parameters have
3367dd7cddfSDavid du Colombier 	  * been requested, but not this one; 1 means this parameter has
3377dd7cddfSDavid du Colombier 	  * been requested specifically.
3387dd7cddfSDavid du Colombier 	  */
3397dd7cddfSDavid du Colombier 
3407dd7cddfSDavid du Colombier #define param_proc_requested(proc)\
341*593dc095SDavid du Colombier 	 int proc(const gs_param_list *, gs_param_name)
3427dd7cddfSDavid du Colombier 	 param_proc_requested((*requested));
3437dd7cddfSDavid du Colombier #define param_requested(plist, pkey)\
3447dd7cddfSDavid du Colombier 	 (*(plist)->procs->requested)(plist, pkey)
3457dd7cddfSDavid du Colombier 
3467dd7cddfSDavid du Colombier 	 /* Get the 'policy' associated with an out-of-range parameter value. */
3477dd7cddfSDavid du Colombier 	 /* (Only used when reading.) */
3487dd7cddfSDavid du Colombier 
3497dd7cddfSDavid du Colombier #define param_proc_get_policy(proc)\
350*593dc095SDavid du Colombier 	 int proc(gs_param_list *, gs_param_name)
3517dd7cddfSDavid du Colombier 	 param_proc_get_policy((*get_policy));
3527dd7cddfSDavid du Colombier #define param_get_policy(plist, pkey)\
3537dd7cddfSDavid du Colombier 	 (*(plist)->procs->get_policy)(plist, pkey)
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier 	 /*
3567dd7cddfSDavid du Colombier 	  * Signal an error.  (Only used when reading.)
3577dd7cddfSDavid du Colombier 	  * The procedure may return a different error code,
3587dd7cddfSDavid du Colombier 	  * or may return 0 indicating that the error is to be ignored.
3597dd7cddfSDavid du Colombier 	  */
3607dd7cddfSDavid du Colombier 
3617dd7cddfSDavid du Colombier #define param_proc_signal_error(proc)\
362*593dc095SDavid du Colombier 	 int proc(gs_param_list *, gs_param_name, int)
3637dd7cddfSDavid du Colombier 	 param_proc_signal_error((*signal_error));
3647dd7cddfSDavid du Colombier #define param_signal_error(plist, pkey, code)\
3657dd7cddfSDavid du Colombier 	 (*(plist)->procs->signal_error)(plist, pkey, code)
3667dd7cddfSDavid du Colombier #define param_return_error(plist, pkey, code)\
3677dd7cddfSDavid du Colombier 	 return_error(param_signal_error(plist, pkey, code))
3687dd7cddfSDavid du Colombier 
3697dd7cddfSDavid du Colombier 	 /*
3707dd7cddfSDavid du Colombier 	  * "Commit" a set of changes.  (Only used when reading.)
3717dd7cddfSDavid du Colombier 	  * This is called at the end of the first phase.
3727dd7cddfSDavid du Colombier 	  */
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier #define param_proc_commit(proc)\
375*593dc095SDavid du Colombier 	 int proc(gs_param_list *)
3767dd7cddfSDavid du Colombier 	 param_proc_commit((*commit));
3777dd7cddfSDavid du Colombier #define param_commit(plist)\
3787dd7cddfSDavid du Colombier 	 (*(plist)->procs->commit)(plist)
3797dd7cddfSDavid du Colombier 
3807dd7cddfSDavid du Colombier } gs_param_list_procs;
3817dd7cddfSDavid du Colombier 
3827dd7cddfSDavid du Colombier /* Transmit typed parameters. */
383*593dc095SDavid du Colombier int param_read_requested_typed(gs_param_list *, gs_param_name,
384*593dc095SDavid du Colombier 				  gs_param_typed_value *);
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier #define param_read_typed(plist, pkey, pvalue)\
3877dd7cddfSDavid du Colombier   ((pvalue)->type = gs_param_type_any,\
3887dd7cddfSDavid du Colombier    param_read_requested_typed(plist, pkey, pvalue))
3897dd7cddfSDavid du Colombier 
3907dd7cddfSDavid du Colombier /* Transmit parameters of specific types. */
391*593dc095SDavid du Colombier int param_read_null(gs_param_list *, gs_param_name);
392*593dc095SDavid du Colombier int param_write_null(gs_param_list *, gs_param_name);
393*593dc095SDavid du Colombier int param_read_bool(gs_param_list *, gs_param_name, bool *);
394*593dc095SDavid du Colombier int param_write_bool(gs_param_list *, gs_param_name, const bool *);
395*593dc095SDavid du Colombier int param_read_int(gs_param_list *, gs_param_name, int *);
396*593dc095SDavid du Colombier int param_write_int(gs_param_list *, gs_param_name, const int *);
397*593dc095SDavid du Colombier int param_read_long(gs_param_list *, gs_param_name, long *);
398*593dc095SDavid du Colombier int param_write_long(gs_param_list *, gs_param_name, const long *);
399*593dc095SDavid du Colombier int param_read_float(gs_param_list *, gs_param_name, float *);
400*593dc095SDavid du Colombier int param_write_float(gs_param_list *, gs_param_name, const float *);
401*593dc095SDavid du Colombier int param_read_string(gs_param_list *, gs_param_name, gs_param_string *);
402*593dc095SDavid du Colombier int param_write_string(gs_param_list *, gs_param_name,
403*593dc095SDavid du Colombier 		       const gs_param_string *);
404*593dc095SDavid du Colombier int param_read_name(gs_param_list *, gs_param_name, gs_param_string *);
405*593dc095SDavid du Colombier int param_write_name(gs_param_list *, gs_param_name,
406*593dc095SDavid du Colombier 		     const gs_param_string *);
407*593dc095SDavid du Colombier int param_read_int_array(gs_param_list *, gs_param_name,
408*593dc095SDavid du Colombier 			 gs_param_int_array *);
409*593dc095SDavid du Colombier int param_write_int_array(gs_param_list *, gs_param_name,
410*593dc095SDavid du Colombier 			  const gs_param_int_array *);
411*593dc095SDavid du Colombier int param_write_int_values(gs_param_list *, gs_param_name,
412*593dc095SDavid du Colombier 			   const int *, uint, bool);
413*593dc095SDavid du Colombier int param_read_float_array(gs_param_list *, gs_param_name,
414*593dc095SDavid du Colombier 			   gs_param_float_array *);
415*593dc095SDavid du Colombier int param_write_float_array(gs_param_list *, gs_param_name,
416*593dc095SDavid du Colombier 			    const gs_param_float_array *);
417*593dc095SDavid du Colombier int param_write_float_values(gs_param_list *, gs_param_name,
418*593dc095SDavid du Colombier 			     const float *, uint, bool);
419*593dc095SDavid du Colombier int param_read_string_array(gs_param_list *, gs_param_name,
420*593dc095SDavid du Colombier 			    gs_param_string_array *);
421*593dc095SDavid du Colombier int param_write_string_array(gs_param_list *, gs_param_name,
422*593dc095SDavid du Colombier 			     const gs_param_string_array *);
423*593dc095SDavid du Colombier int param_read_name_array(gs_param_list *, gs_param_name,
424*593dc095SDavid du Colombier 			  gs_param_string_array *);
425*593dc095SDavid du Colombier int param_write_name_array(gs_param_list *, gs_param_name,
426*593dc095SDavid du Colombier 			   const gs_param_string_array *);
4277dd7cddfSDavid du Colombier 
4283ff48bf5SDavid du Colombier /*
4293ff48bf5SDavid du Colombier  * Define an abstract parameter list.  Implementations are concrete
4303ff48bf5SDavid du Colombier  * subclasses.
4313ff48bf5SDavid du Colombier  *
4323ff48bf5SDavid du Colombier  * The persisent_keys flag allows for both statically and dynamically
4333ff48bf5SDavid du Colombier  * allocated keys.  The default is static (the keys are normally C string
4343ff48bf5SDavid du Colombier  * literals).
4353ff48bf5SDavid du Colombier  */
4367dd7cddfSDavid du Colombier #define gs_param_list_common\
4377dd7cddfSDavid du Colombier     const gs_param_list_procs *procs;\
4383ff48bf5SDavid du Colombier     gs_memory_t *memory;	/* for allocating coerced arrays */\
4393ff48bf5SDavid du Colombier     bool persistent_keys
4407dd7cddfSDavid du Colombier struct gs_param_list_s {
4417dd7cddfSDavid du Colombier     gs_param_list_common;
4427dd7cddfSDavid du Colombier };
4437dd7cddfSDavid du Colombier 
4443ff48bf5SDavid du Colombier /* Set whether the keys for param_write_XXX are persistent. */
4453ff48bf5SDavid du Colombier /* VMS limits procedure names to 31 characters. */
4463ff48bf5SDavid du Colombier #define gs_param_list_set_persistent_keys gs_param_list_set_persist_keys
447*593dc095SDavid du Colombier void gs_param_list_set_persistent_keys(gs_param_list *, bool);
4483ff48bf5SDavid du Colombier 
4497dd7cddfSDavid du Colombier /* Initialize a parameter list key enumerator. */
450*593dc095SDavid du Colombier void param_init_enumerator(gs_param_enumerator_t * penum);
4517dd7cddfSDavid du Colombier 
4527dd7cddfSDavid du Colombier /*
4537dd7cddfSDavid du Colombier  * The following interface provides a convenient way to read and set
4547dd7cddfSDavid du Colombier  * collections of parameters of any type other than dictionaries.
4557dd7cddfSDavid du Colombier  */
4567dd7cddfSDavid du Colombier 
4577dd7cddfSDavid du Colombier typedef struct gs_param_item_s {
4587dd7cddfSDavid du Colombier     const char *key;
4597dd7cddfSDavid du Colombier     byte /*gs_param_type */ type;
4607dd7cddfSDavid du Colombier     short offset;		/* offset of value in structure */
4617dd7cddfSDavid du Colombier } gs_param_item_t;
4627dd7cddfSDavid du Colombier #define gs_param_item_end { 0 }	/* list terminator */
4637dd7cddfSDavid du Colombier /*
4647dd7cddfSDavid du Colombier  * Transfer a collection of parameters.
4657dd7cddfSDavid du Colombier  * For param_write_items, if a parameter value is equal to the value in
4667dd7cddfSDavid du Colombier  * the optional default_obj, the item isn't transferred.
4677dd7cddfSDavid du Colombier  */
468*593dc095SDavid du Colombier int gs_param_read_items(gs_param_list * plist, void *obj,
469*593dc095SDavid du Colombier 			const gs_param_item_t * items);
470*593dc095SDavid du Colombier int gs_param_write_items(gs_param_list * plist, const void *obj,
4717dd7cddfSDavid du Colombier 			 const void *default_obj,
472*593dc095SDavid du Colombier 			 const gs_param_item_t * items);
4737dd7cddfSDavid du Colombier 
4743ff48bf5SDavid du Colombier /* Internal procedure to initialize the common part of a parameter list. */
475*593dc095SDavid du Colombier void gs_param_list_init(gs_param_list *, const gs_param_list_procs *,
476*593dc095SDavid du Colombier 			gs_memory_t *);
4773ff48bf5SDavid du Colombier 
4783ff48bf5SDavid du Colombier /*
4793ff48bf5SDavid du Colombier  * Internal procedure to read a value, with coercion if requested, needed,
4803ff48bf5SDavid du Colombier  * and possible.  If mem != 0, we can coerce int arrays to float arrays, and
4813ff48bf5SDavid du Colombier  * possibly do other coercions later.
4823ff48bf5SDavid du Colombier  */
483*593dc095SDavid du Colombier int param_coerce_typed(gs_param_typed_value * pvalue,
484*593dc095SDavid du Colombier 		       gs_param_type req_type, gs_memory_t * mem);
4853ff48bf5SDavid du Colombier 
4867dd7cddfSDavid du Colombier /* ---------------- Default implementation ---------------- */
4877dd7cddfSDavid du Colombier 
4887dd7cddfSDavid du Colombier /*
4897dd7cddfSDavid du Colombier  * Provide default generic implementations of param_request and
4907dd7cddfSDavid du Colombier  * param_requested.
4917dd7cddfSDavid du Colombier  */
4927dd7cddfSDavid du Colombier param_proc_request(gs_param_request_default);  /* does nothing */
4937dd7cddfSDavid du Colombier param_proc_requested(gs_param_requested_default);  /* always returns true */
4947dd7cddfSDavid du Colombier 
4957dd7cddfSDavid du Colombier /*
4967dd7cddfSDavid du Colombier  * Define a default implementation, intended to be usable easily
4977dd7cddfSDavid du Colombier  * from C code.  The intended usage pattern is:
4987dd7cddfSDavid du Colombier 	gs_c_param_list list;
4997dd7cddfSDavid du Colombier 	[... other code here ...]
5007dd7cddfSDavid du Colombier 	gs_c_param_list_write(&list, mem);
5017dd7cddfSDavid du Colombier 	[As many as needed:]
5027dd7cddfSDavid du Colombier 	code = param_write_XXX(&list, "ParamName", &param_value);
5037dd7cddfSDavid du Colombier 	[Check code for <0]
5047dd7cddfSDavid du Colombier 	gs_c_param_list_read(&list);
5057dd7cddfSDavid du Colombier 	code = gs_putdeviceparams(dev, &list);
5067dd7cddfSDavid du Colombier 	gs_c_param_list_release(&list);
5077dd7cddfSDavid du Colombier 	[Check code for <0]
5087dd7cddfSDavid du Colombier 	if ( code == 1 )
5097dd7cddfSDavid du Colombier 	{
5107dd7cddfSDavid du Colombier 	    code = (*dev_proc(dev, open_device))(dev);
5117dd7cddfSDavid du Colombier 	    [Check code for <0]
5127dd7cddfSDavid du Colombier 	}
5137dd7cddfSDavid du Colombier  *
5143ff48bf5SDavid du Colombier  * This implementation also has the special property that it can forward
5153ff48bf5SDavid du Colombier  * unrecognized param_read_ calls to another parameter list, called the
5163ff48bf5SDavid du Colombier  * target.  This allows constructing incrementally modified parameter lists.
5173ff48bf5SDavid du Colombier  * Note that this is only relevant for put_params (reading from the
5183ff48bf5SDavid du Colombier  * parameter list).
5197dd7cddfSDavid du Colombier  */
5207dd7cddfSDavid du Colombier 
5217dd7cddfSDavid du Colombier typedef struct gs_c_param_s gs_c_param;	/* opaque here */
5227dd7cddfSDavid du Colombier typedef struct gs_c_param_list_s {
5237dd7cddfSDavid du Colombier     gs_param_list_common;
5247dd7cddfSDavid du Colombier     gs_c_param *head;
5257dd7cddfSDavid du Colombier     gs_param_list *target;
5267dd7cddfSDavid du Colombier     uint count;
5277dd7cddfSDavid du Colombier     bool any_requested;
5287dd7cddfSDavid du Colombier     gs_param_collection_type_t coll_type;
5297dd7cddfSDavid du Colombier } gs_c_param_list;
5307dd7cddfSDavid du Colombier #define private_st_c_param_list()	/* in gsparam.c */\
5317dd7cddfSDavid du Colombier   gs_private_st_ptrs2(st_c_param_list, gs_c_param_list, "c_param_list",\
5327dd7cddfSDavid du Colombier     c_param_list_enum_ptrs, c_param_list_reloc_ptrs, head, target)
5337dd7cddfSDavid du Colombier 
534*593dc095SDavid du Colombier /* Define a GC descriptor for gs_param_string. */
535*593dc095SDavid du Colombier /* This structure descriptor is only for non persistent gs_param_strings. */
536*593dc095SDavid du Colombier #define private_st_gs_param_string()	/* in gdevdevn.c */\
537*593dc095SDavid du Colombier   gs_private_st_composite(st_gs_param_string, gs_param_string, "gs_param_string",\
538*593dc095SDavid du Colombier 			param_string_enum_ptrs, param_string_reloc_ptrs)
539*593dc095SDavid du Colombier 
5407dd7cddfSDavid du Colombier /* Set the target of a C parameter list. */
541*593dc095SDavid du Colombier void gs_c_param_list_set_target(gs_c_param_list *, gs_param_list *);
5427dd7cddfSDavid du Colombier 
5433ff48bf5SDavid du Colombier /*
5443ff48bf5SDavid du Colombier  * Clients normally allocate the gs_c_param_list on the stack, but we
5453ff48bf5SDavid du Colombier  * provide a procedure for allocating one in memory.
5463ff48bf5SDavid du Colombier  */
547*593dc095SDavid du Colombier gs_c_param_list *gs_c_param_list_alloc(gs_memory_t *, client_name_t);
548*593dc095SDavid du Colombier void gs_c_param_list_write(gs_c_param_list *, gs_memory_t *);
549*593dc095SDavid du Colombier void gs_c_param_list_write_more(gs_c_param_list *); /* switch back to writing, no init */
550*593dc095SDavid du Colombier void gs_c_param_list_read(gs_c_param_list *);	/* switch to reading */
551*593dc095SDavid du Colombier void gs_c_param_list_release(gs_c_param_list *);
5527dd7cddfSDavid du Colombier 
5537dd7cddfSDavid du Colombier #endif /* gsparam_INCLUDED */
554