xref: /plan9/sys/src/cmd/gs/src/opdef.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
13ff48bf5SDavid du Colombier /* Copyright (C) 1991, 1995, 1998, 1999 artofcode LLC.  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: opdef.h,v 1.6 2002/06/16 04:47:10 lpd Exp $ */
187dd7cddfSDavid du Colombier /* Operator definition interface for Ghostscript */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier #ifndef opdef_INCLUDED
217dd7cddfSDavid du Colombier #  define opdef_INCLUDED
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier /*
247dd7cddfSDavid du Colombier  * Define the structure for initializing the operator table.  Each operator
257dd7cddfSDavid du Colombier  * file zxxx.c declares an array of these as follows:
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier    const op_def * const zxxx_op_defs[] = {
287dd7cddfSDavid du Colombier       {"1name", zname},
297dd7cddfSDavid du Colombier       ...
307dd7cddfSDavid du Colombier       op_def_end(iproc)
317dd7cddfSDavid du Colombier    };
327dd7cddfSDavid du Colombier 
333ff48bf5SDavid du Colombier  * where iproc is an initialization procedure for the file or 0, and, for
343ff48bf5SDavid du Colombier  * each operator defined, the initial digit of the name string indicates
353ff48bf5SDavid du Colombier  * the number of arguments and zname is the address of the associated C
363ff48bf5SDavid du Colombier  * function to invoke.
373ff48bf5SDavid du Colombier  *
383ff48bf5SDavid du Colombier  * The array definition always appears at the END of the file, to avoid
393ff48bf5SDavid du Colombier  * the need for forward declarations for all the operator procedures.
403ff48bf5SDavid du Colombier  *
417dd7cddfSDavid du Colombier  * Operators may be stored in dictionaries other than systemdict.
427dd7cddfSDavid du Colombier  * We support this with op_def entries of a special form:
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier    op_def_begin_dict("dictname"),
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier  */
477dd7cddfSDavid du Colombier typedef struct {
487dd7cddfSDavid du Colombier     const char *oname;
497dd7cddfSDavid du Colombier     op_proc_t proc;
507dd7cddfSDavid du Colombier } op_def;
517dd7cddfSDavid du Colombier 
527dd7cddfSDavid du Colombier #define op_def_begin_dict(dname) {dname, 0}
537dd7cddfSDavid du Colombier #define op_def_begin_filter() op_def_begin_dict("filterdict")
547dd7cddfSDavid du Colombier #define op_def_begin_level2() op_def_begin_dict("level2dict")
557dd7cddfSDavid du Colombier #define op_def_begin_ll3() op_def_begin_dict("ll3dict")
567dd7cddfSDavid du Colombier #define op_def_is_begin_dict(def) ((def)->proc == 0)
577dd7cddfSDavid du Colombier #define op_def_end(iproc) {0, iproc}
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier /*
607dd7cddfSDavid du Colombier  * NOTE: for implementation reasons, a single table of operator definitions
617dd7cddfSDavid du Colombier  * is limited to 16 entries, including op_def_begin_xxx entries.  If a file
627dd7cddfSDavid du Colombier  * defines more operators than this, it must split them into multiple
637dd7cddfSDavid du Colombier  * tables and have multiple -oper entries in the makefile.  Currently,
647dd7cddfSDavid du Colombier  * only 4 out of 85 operator files require this.
657dd7cddfSDavid du Colombier  */
667dd7cddfSDavid du Colombier #define OP_DEFS_LOG2_MAX_SIZE 4
677dd7cddfSDavid du Colombier #define OP_DEFS_MAX_SIZE (1 << OP_DEFS_LOG2_MAX_SIZE)
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier /*
707dd7cddfSDavid du Colombier  * Define the table of pointers to all operator definition tables.
717dd7cddfSDavid du Colombier  */
727dd7cddfSDavid du Colombier extern const op_def *const op_defs_all[];
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier /*
757dd7cddfSDavid du Colombier  * Internal operators whose names begin with %, such as continuation
767dd7cddfSDavid du Colombier  * operators, do not appear in systemdict.  Ghostscript assumes
777dd7cddfSDavid du Colombier  * that these operators cannot appear anywhere (in executable form)
787dd7cddfSDavid du Colombier  * except on the e-stack; to maintain this invariant, the execstack
797dd7cddfSDavid du Colombier  * operator converts them to literal form, and cvx refuses to convert
807dd7cddfSDavid du Colombier  * them back.  As a result of this invariant, they do not need to
817dd7cddfSDavid du Colombier  * push themselves back on the e-stack when executed, since the only
827dd7cddfSDavid du Colombier  * place they could have come from was the e-stack.
837dd7cddfSDavid du Colombier  */
847dd7cddfSDavid du Colombier #define op_def_is_internal(def) ((def)->oname[1] == '%')
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier /*
877dd7cddfSDavid du Colombier  * All operators are catalogued in a table; this is necessary because
887dd7cddfSDavid du Colombier  * they must have a short packed representation for the sake of 'bind'.
897dd7cddfSDavid du Colombier  * The `size' of an operator is normally its index in this table;
907dd7cddfSDavid du Colombier  * however, internal operators have a `size' of 0, and their true index
917dd7cddfSDavid du Colombier  * must be found by searching the table for their procedure address.
927dd7cddfSDavid du Colombier  */
93*593dc095SDavid du Colombier ushort op_find_index(const ref *);
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier #define op_index(opref)\
967dd7cddfSDavid du Colombier   (r_size(opref) == 0 ? op_find_index(opref) : r_size(opref))
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier /*
997dd7cddfSDavid du Colombier  * There are actually two kinds of operators: the real ones (t_operator),
1007dd7cddfSDavid du Colombier  * and ones defined by procedures (t_oparray).  The catalog for t_operators
1017dd7cddfSDavid du Colombier  * is (indirectly) op_defs_all, and their index is in the range
1027dd7cddfSDavid du Colombier  * [1..op_def_count-1].
1037dd7cddfSDavid du Colombier  */
1047dd7cddfSDavid du Colombier #define op_index_is_operator(index) ((index) < op_def_count)
1057dd7cddfSDavid du Colombier extern const uint op_def_count;
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier #define op_index_def(index)\
1087dd7cddfSDavid du Colombier   (&op_defs_all[(index) >> OP_DEFS_LOG2_MAX_SIZE]\
1097dd7cddfSDavid du Colombier     [(index) & (OP_DEFS_MAX_SIZE - 1)])
1107dd7cddfSDavid du Colombier #define op_num_args(opref) (op_index_def(op_index(opref))->oname[0] - '0')
1117dd7cddfSDavid du Colombier #define op_index_proc(index) (op_index_def(index)->proc)
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier /*
1147dd7cddfSDavid du Colombier  * There are two catalogs for t_oparrays, one global and one local.
1157dd7cddfSDavid du Colombier  * Operator indices for the global table are in the range
1167dd7cddfSDavid du Colombier  *      [op_def_count..op_def_count+op_array_global.count-1]
1177dd7cddfSDavid du Colombier  * Operator indices for the local table are in the range
1187dd7cddfSDavid du Colombier  *      [op_def_count+r_size(&op_array_global.table)..
1197dd7cddfSDavid du Colombier  *        op_def_count+r_size(&op_array_global.table)+op_array_local.count-1]
1207dd7cddfSDavid du Colombier  */
1217dd7cddfSDavid du Colombier typedef struct op_array_table_s {
1227dd7cddfSDavid du Colombier     ref table;			/* t_array */
1237dd7cddfSDavid du Colombier     ushort *nx_table;		/* name indices */
1247dd7cddfSDavid du Colombier     uint count;			/* # of occupied entries */
1257dd7cddfSDavid du Colombier     uint base_index;		/* operator index of first entry */
1267dd7cddfSDavid du Colombier     uint attrs;			/* ref attrs of ops in this table */
1277dd7cddfSDavid du Colombier     ref *root_p;		/* self-pointer for GC root */
1287dd7cddfSDavid du Colombier } op_array_table;
1297dd7cddfSDavid du Colombier extern op_array_table
1307dd7cddfSDavid du Colombier        op_array_table_global, op_array_table_local;
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier #define op_index_op_array_table(index)\
1337dd7cddfSDavid du Colombier   ((index) < op_array_table_local.base_index ?\
1347dd7cddfSDavid du Colombier    &op_array_table_global : &op_array_table_local)
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier /*
1377dd7cddfSDavid du Colombier  * Convert an operator index to an operator or oparray ref.
1387dd7cddfSDavid du Colombier  * This is only used for debugging and for 'get' from packed arrays,
1397dd7cddfSDavid du Colombier  * so it doesn't have to be very fast.
1407dd7cddfSDavid du Colombier  */
141*593dc095SDavid du Colombier void op_index_ref(uint, ref *);
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier #endif /* opdef_INCLUDED */
144