xref: /plan9-contrib/sys/src/cmd/gs/src/iref.h (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
13ff48bf5SDavid du Colombier /* Copyright (C) 1989, 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: iref.h,v 1.9 2002/06/16 04:47:10 lpd Exp $ */
187dd7cddfSDavid du Colombier /* Object structure and type definitions for Ghostscript */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier #ifndef iref_INCLUDED
217dd7cddfSDavid du Colombier #  define iref_INCLUDED
227dd7cddfSDavid du Colombier 
23*593dc095SDavid du Colombier /*
24*593dc095SDavid du Colombier  * Note: this file defines a large number of macros.  Many of these are
25*593dc095SDavid du Colombier  * only used for internal purposes within this file, to help in the
26*593dc095SDavid du Colombier  * definition of other macros or data structures, and should never be
27*593dc095SDavid du Colombier  * referenced outside this file.  It is intended that all such internal
28*593dc095SDavid du Colombier  * macros have names beginning with an underscore (_).
29*593dc095SDavid du Colombier  */
30*593dc095SDavid du Colombier 
317dd7cddfSDavid du Colombier /* The typedef for object references */
323ff48bf5SDavid du Colombier #ifndef ref_DEFINED
337dd7cddfSDavid du Colombier typedef struct ref_s ref;
343ff48bf5SDavid du Colombier #  define ref_DEFINED
353ff48bf5SDavid du Colombier #endif
367dd7cddfSDavid du Colombier 
373ff48bf5SDavid du Colombier /*
383ff48bf5SDavid du Colombier  * Define the type for packed object references.  This is opaque here:
393ff48bf5SDavid du Colombier  * the details are in ipacked.h.
403ff48bf5SDavid du Colombier  */
417dd7cddfSDavid du Colombier typedef ushort ref_packed;
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier #define log2_sizeof_ref_packed arch_log2_sizeof_short
447dd7cddfSDavid du Colombier #define sizeof_ref_packed (1 << log2_sizeof_ref_packed)
457dd7cddfSDavid du Colombier 
467dd7cddfSDavid du Colombier /*
477dd7cddfSDavid du Colombier  * Define the object types.
487dd7cddfSDavid du Colombier  * The types marked with @ are composite and hence use the a_space field;
497dd7cddfSDavid du Colombier  * objects of all other types must have a_space cleared.
507dd7cddfSDavid du Colombier  * The types marked with ! behave differently in the interpreter
517dd7cddfSDavid du Colombier  * depending on whether they are executable or literal.
527dd7cddfSDavid du Colombier  * The types marked with + use the read/write/execute
537dd7cddfSDavid du Colombier  * attributes; the rest only use the executable attribute.
547dd7cddfSDavid du Colombier  * The types marked with # use the size field.
553ff48bf5SDavid du Colombier  *
563ff48bf5SDavid du Colombier  * Note that for the object types that support getinterval (array and
573ff48bf5SDavid du Colombier  * string types), there is no way to tell whether a given reference
583ff48bf5SDavid du Colombier  * designates an original object or a sub-interval.  This is a deliberate
593ff48bf5SDavid du Colombier  * design decision.
607dd7cddfSDavid du Colombier  */
617dd7cddfSDavid du Colombier typedef enum {
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier /*
647dd7cddfSDavid du Colombier  * Type 0 must be left unassigned, so that the type (and type_attrs)
657dd7cddfSDavid du Colombier  * of a valid ref will never be zero.  This speeds up simultaneous
667dd7cddfSDavid du Colombier  * type/space checking in def (see dstack.h for details) and a similar
677dd7cddfSDavid du Colombier  * check in ref_save (see store.h for details).  We may as well use
687dd7cddfSDavid du Colombier  * type 0 for t__invalid, which will never appear in a real ref.
697dd7cddfSDavid du Colombier  *
707dd7cddfSDavid du Colombier  * The "invalid" type is only used in a few special places: the guard
713ff48bf5SDavid du Colombier  * entries at the bottom of the o-stack that detect stack underflow, and
723ff48bf5SDavid du Colombier  * (perhaps eventually) the ref that the cached value pointer in names
733ff48bf5SDavid du Colombier  * points to if the binding isn't known.  It never appears on a stack or in
743ff48bf5SDavid du Colombier  * a program-visible data structure.
757dd7cddfSDavid du Colombier  */
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier     t__invalid,			/*      (no value) */
787dd7cddfSDavid du Colombier     t_boolean,			/*      value.boolval */
797dd7cddfSDavid du Colombier     t_dictionary,		/* @ +  value.pdict */
807dd7cddfSDavid du Colombier     t_file,			/* @!+# value.pfile, uses size for id */
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier /*
837dd7cddfSDavid du Colombier  * The 4 array types must be kept together, and must start at
847dd7cddfSDavid du Colombier  * a multiple of 4, for the sake of r_is_array and r_is_proc (see below).
857dd7cddfSDavid du Colombier  */
867dd7cddfSDavid du Colombier 
87*593dc095SDavid du Colombier #define _REF_T_ARRAY_SPAN 4
887dd7cddfSDavid du Colombier     t_array,			/* @!+# value.refs */
893ff48bf5SDavid du Colombier     /*
903ff48bf5SDavid du Colombier      * The following are the two implementations of packed arrays.
913ff48bf5SDavid du Colombier      * See ipacked.h for details.
923ff48bf5SDavid du Colombier      */
937dd7cddfSDavid du Colombier     t_mixedarray,		/* @!+# value.packed */
947dd7cddfSDavid du Colombier     t_shortarray,		/* @!+# value.packed */
957dd7cddfSDavid du Colombier     t_unused_array_,		/*      (an unused array type) */
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier /*
987dd7cddfSDavid du Colombier  * t_[a]struct is an "umbrella" for other types that are represented by
997dd7cddfSDavid du Colombier  * allocated objects (structures).  Objects of these types are composite
1007dd7cddfSDavid du Colombier  * and hence use the a_local attribute.  The type name is taken from
1017dd7cddfSDavid du Colombier  * the allocator template for the structure.  t_astruct objects use the
1027dd7cddfSDavid du Colombier  * access attributes; t_struct objects do not.  Neither t_struct nor
1037dd7cddfSDavid du Colombier  * t_astruct objects use the size.
1047dd7cddfSDavid du Colombier  *
1057dd7cddfSDavid du Colombier  * t_struct is currently used for the following PostScript types:
1067dd7cddfSDavid du Colombier  *      condition, lock.
1077dd7cddfSDavid du Colombier  * We could use it for fontIDs, except that they may have subclasses.
1087dd7cddfSDavid du Colombier  * Eventually it will also be used for the new 'device' type.
1097dd7cddfSDavid du Colombier  * t_astruct is currently used for the following PostScript types:
1107dd7cddfSDavid du Colombier  *      gstate.
1117dd7cddfSDavid du Colombier  *
1127dd7cddfSDavid du Colombier  * The 2 structure types must be kept together, and must start at
1137dd7cddfSDavid du Colombier  * a multiple of 2, for the sake of r_has_stype (see below).
1147dd7cddfSDavid du Colombier  */
1157dd7cddfSDavid du Colombier 
116*593dc095SDavid du Colombier #define _REF_T_STRUCT_SPAN 2
1177dd7cddfSDavid du Colombier     t_struct,			/* @    value.pstruct */
1187dd7cddfSDavid du Colombier     t_astruct,			/* @ +  value.pstruct */
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier /*
1217dd7cddfSDavid du Colombier  * We now continue with individual types.
1227dd7cddfSDavid du Colombier  */
1237dd7cddfSDavid du Colombier     t_fontID,			/* @    value.pstruct */
1247dd7cddfSDavid du Colombier     t_integer,			/*      value.intval */
1257dd7cddfSDavid du Colombier     t_mark,			/*        (no value) */
1267dd7cddfSDavid du Colombier /*
1277dd7cddfSDavid du Colombier  * Name objects use the a_space field because they really are composite
1287dd7cddfSDavid du Colombier  * objects internally.
1297dd7cddfSDavid du Colombier  */
1307dd7cddfSDavid du Colombier     t_name,			/* @! # value.pname, uses size for index */
1317dd7cddfSDavid du Colombier     t_null,			/*  ! # (value.opproc, uses size for mark */
1327dd7cddfSDavid du Colombier 				/*        type, on e-stack only) */
1337dd7cddfSDavid du Colombier /*
1347dd7cddfSDavid du Colombier  * Operator objects use the a_space field because they may actually be
1357dd7cddfSDavid du Colombier  * disguised procedures.  (Real operators always have a_space = 0.)
1367dd7cddfSDavid du Colombier  */
1377dd7cddfSDavid du Colombier     t_operator,			/* @! # value.opproc, uses size for index */
1387dd7cddfSDavid du Colombier     t_real,			/*      value.realval */
1397dd7cddfSDavid du Colombier     t_save,			/*      value.saveid, see isave.h for why */
1407dd7cddfSDavid du Colombier 				/*        this isn't a t_struct */
1417dd7cddfSDavid du Colombier     t_string,			/* @!+# value.bytes */
1427dd7cddfSDavid du Colombier /*
1437dd7cddfSDavid du Colombier  * The following are extensions to the PostScript type set.
1447dd7cddfSDavid du Colombier  * If you add new types, be sure to edit:
1457dd7cddfSDavid du Colombier  *      - REF_TYPE_*STRINGS* and REF_TYPE_PROPERTIES_DATA below;
1467dd7cddfSDavid du Colombier  *      - the table in gs_init.ps (==only operator);
1477dd7cddfSDavid du Colombier  *      - the printing routine in idebug.c;
1487dd7cddfSDavid du Colombier  *      - the dispatches in igc.c, igcref.c, and interp.c;
1497dd7cddfSDavid du Colombier  *      - obj_cvs, obj_cvp, and obj_eq in iutil.c;
1507dd7cddfSDavid du Colombier  *      - restore_check_stack in zvmem.c.
1517dd7cddfSDavid du Colombier  */
1527dd7cddfSDavid du Colombier     t_device,			/* @ +   value.pdevice */
1537dd7cddfSDavid du Colombier     t_oparray,			/* @! #  value.const_refs, uses size */
1547dd7cddfSDavid du Colombier 				/*         for index */
1557dd7cddfSDavid du Colombier     t_next_index		/*** first available index ***/
1567dd7cddfSDavid du Colombier } ref_type;
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier /*
1597dd7cddfSDavid du Colombier  * The interpreter uses types starting at t_next_index for representing
1607dd7cddfSDavid du Colombier  * a few high-frequency operators.
1617dd7cddfSDavid du Colombier  * Since there are no operations specifically on operators,
1627dd7cddfSDavid du Colombier  * there is no need for any operators to check specifically for these
1637dd7cddfSDavid du Colombier  * types.  The r_btype macro takes care of the conversion when required.
1647dd7cddfSDavid du Colombier  */
1657dd7cddfSDavid du Colombier /*extern const int tx_next_index; *//* in interp.c */
1667dd7cddfSDavid du Colombier /*
1677dd7cddfSDavid du Colombier  * Define a table giving properties of types, similar to the table used
1687dd7cddfSDavid du Colombier  * by the isxxx functions (macros) in <ctype.h>.
1697dd7cddfSDavid du Colombier  */
170*593dc095SDavid du Colombier #define _REF_TYPE_USES_ACCESS 1	/* type uses w/r/x attributes ("+" above) */
171*593dc095SDavid du Colombier #define _REF_TYPE_USES_SIZE 2	/* type uses size attribute ("#" above) */
172*593dc095SDavid du Colombier #define _REF_TYPE_IS_NULL 4	/* type is t_null */
173*593dc095SDavid du Colombier #define _REF_TYPE_IS_DICTIONARY 8 /* type is t_dictionary */
1747dd7cddfSDavid du Colombier extern const byte ref_type_properties[1 << 6];	/* r_type_bits */
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier #define REF_TYPE_PROPERTIES_DATA\
1777dd7cddfSDavid du Colombier   0,				/* t__invalid */\
1787dd7cddfSDavid du Colombier   0,				/* t_boolean */\
179*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_IS_DICTIONARY, /* t_dictionary */\
180*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_USES_SIZE, /* t_file */\
181*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_USES_SIZE, /* t_array */\
182*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_USES_SIZE, /* t_mixedarray */\
183*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_USES_SIZE, /* t_shortarray */\
184*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_USES_SIZE, /* (unused array type) */\
1857dd7cddfSDavid du Colombier   0,				/* t_struct */\
186*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS,		/* t_astruct */\
1877dd7cddfSDavid du Colombier   0,				/* t_fontID */\
1887dd7cddfSDavid du Colombier   0,				/* t_integer */\
1897dd7cddfSDavid du Colombier   0,				/* t_mark */\
190*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,		/* t_name */\
191*593dc095SDavid du Colombier   _REF_TYPE_IS_NULL,		/* t_null, uses size only on e-stack */\
192*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,		/* t_operator */\
1937dd7cddfSDavid du Colombier   0,				/* t_real */\
1947dd7cddfSDavid du Colombier   0,				/* t_save */\
195*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS | _REF_TYPE_USES_SIZE, /* t_string */\
196*593dc095SDavid du Colombier   _REF_TYPE_USES_ACCESS,		/* t_device */\
197*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,		/* t_oparray */\
1987dd7cddfSDavid du Colombier     /*\
1997dd7cddfSDavid du Colombier      * The remaining types are the extended pseudo-types used by the\
2007dd7cddfSDavid du Colombier      * interpreter for operators.  We need to fill up the table.\
2017dd7cddfSDavid du Colombier      */\
202*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*24*/\
203*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*28*/\
204*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*32*/\
205*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*36*/\
206*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*40*/\
207*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*44*/\
208*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*48*/\
209*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*52*/\
210*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*56*/\
211*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE, /*60*/\
212*593dc095SDavid du Colombier   _REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE,_REF_TYPE_USES_SIZE	/*64 */
213*593dc095SDavid du Colombier #define _REF_TYPE_HAS(rtype,props)\
2147dd7cddfSDavid du Colombier   ((ref_type_properties[rtype] & (props)) != 0)
2157dd7cddfSDavid du Colombier #define ref_type_uses_access(rtype)\
216*593dc095SDavid du Colombier  _REF_TYPE_HAS(rtype, _REF_TYPE_USES_ACCESS)
2177dd7cddfSDavid du Colombier #define ref_type_uses_size(rtype)\
218*593dc095SDavid du Colombier  _REF_TYPE_HAS(rtype, _REF_TYPE_USES_SIZE)
2197dd7cddfSDavid du Colombier #define ref_type_uses_size_or_null(rtype)\
220*593dc095SDavid du Colombier  _REF_TYPE_HAS(rtype, _REF_TYPE_USES_SIZE | _REF_TYPE_IS_NULL)
2217dd7cddfSDavid du Colombier /*
2227dd7cddfSDavid du Colombier  * Define the type names for debugging printout.
2237dd7cddfSDavid du Colombier  * All names must be the same length, so that columns will line up.
2247dd7cddfSDavid du Colombier  */
2257dd7cddfSDavid du Colombier #define REF_TYPE_DEBUG_PRINT_STRINGS\
2267dd7cddfSDavid du Colombier   "INVL","bool","dict","file",\
2277dd7cddfSDavid du Colombier   "arry","mpry","spry","u?ry",\
2287dd7cddfSDavid du Colombier   "STRC","ASTR",\
2297dd7cddfSDavid du Colombier   "font","int ","mark","name","null",\
2307dd7cddfSDavid du Colombier   "oper","real","save","str ",\
2317dd7cddfSDavid du Colombier   "devc","opry"
2327dd7cddfSDavid du Colombier /*
2337dd7cddfSDavid du Colombier  * Define the type names for the type operator.
2347dd7cddfSDavid du Colombier  */
2357dd7cddfSDavid du Colombier #define REF_TYPE_NAME_STRINGS\
2367dd7cddfSDavid du Colombier   0,"booleantype","dicttype","filetype",\
2377dd7cddfSDavid du Colombier   "arraytype","packedarraytype","packedarraytype","arraytype",\
2387dd7cddfSDavid du Colombier   0,0,\
2397dd7cddfSDavid du Colombier   "fonttype","integertype","marktype","nametype","nulltype",\
2407dd7cddfSDavid du Colombier   "operatortype","realtype","savetype","stringtype",\
2417dd7cddfSDavid du Colombier   "devicetype","operatortype"
2427dd7cddfSDavid du Colombier /*
2437dd7cddfSDavid du Colombier  * Define the type names for obj_cvp (the == operator).  We only need these
2447dd7cddfSDavid du Colombier  * for types that obj_cvp and obj_cvs don't handle specially.
2457dd7cddfSDavid du Colombier  */
2467dd7cddfSDavid du Colombier #define REF_TYPE_PRINT_STRINGS\
2477dd7cddfSDavid du Colombier   0,0,"-dict-","-file-",\
2487dd7cddfSDavid du Colombier   "-array-","-packedarray-","-packedarray-","-array-",\
2497dd7cddfSDavid du Colombier   0,0,\
2507dd7cddfSDavid du Colombier   "-fontID-",0,"-mark-",0,0,\
2517dd7cddfSDavid du Colombier   0,0,"-save-","-string-",\
2527dd7cddfSDavid du Colombier   "-device-",0
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier /*
2557dd7cddfSDavid du Colombier  * The following factors affect the encoding of attributes:
2567dd7cddfSDavid du Colombier  *
2577dd7cddfSDavid du Colombier  *      - The packed array format requires the high-order bits of the
2587dd7cddfSDavid du Colombier  *        type/attributes field to be 0.  (see packed.h)
2597dd7cddfSDavid du Colombier  *
2607dd7cddfSDavid du Colombier  *      - The interpreter wants the type, executable bit, and execute
2617dd7cddfSDavid du Colombier  *        permission to be adjacent, and in that order from high to low.
2627dd7cddfSDavid du Colombier  *
2637dd7cddfSDavid du Colombier  *      - Type testing is most efficient if the type is in a byte by itself.
2647dd7cddfSDavid du Colombier  *
2657dd7cddfSDavid du Colombier  * The layout given below results in the most efficient code overall.
2667dd7cddfSDavid du Colombier  */
2677dd7cddfSDavid du Colombier 
2683ff48bf5SDavid du Colombier /*
2693ff48bf5SDavid du Colombier  * A few of the fields of a ref are associated with the *location*;
2703ff48bf5SDavid du Colombier  * most are associated with the ref that is *stored* in that location.
2713ff48bf5SDavid du Colombier  * When a ref is copied from one location to another, the former are
2723ff48bf5SDavid du Colombier  * preserved in the destination, the latter are copied.
2733ff48bf5SDavid du Colombier  */
2743ff48bf5SDavid du Colombier /*
2753ff48bf5SDavid du Colombier  * The following are the attributes associated with the location:
2763ff48bf5SDavid du Colombier  */
2777dd7cddfSDavid du Colombier #define l_mark 1		/* mark for garbage collector */
2787dd7cddfSDavid du Colombier #define l_new 2			/* stored into since last save */
2793ff48bf5SDavid du Colombier /*
2803ff48bf5SDavid du Colombier  * The following are attributes associated with the ref itself (the
2813ff48bf5SDavid du Colombier  * contents of the location).  These are visible to PostScript code.
2823ff48bf5SDavid du Colombier  */
2833ff48bf5SDavid du Colombier /*
2843ff48bf5SDavid du Colombier  * Reserve bits for VM space information (defined in ivmspace.h).  Note that
2853ff48bf5SDavid du Colombier  * These bits refer to the VM space of the pointer in the ref, if any, not
2863ff48bf5SDavid du Colombier  * the location in which the ref itself is stored.  For scalars, these bits
2873ff48bf5SDavid du Colombier  * are always zero.
2883ff48bf5SDavid du Colombier  */
2897dd7cddfSDavid du Colombier #define r_space_bits 2
2907dd7cddfSDavid du Colombier #define r_space_shift 2
2913ff48bf5SDavid du Colombier /*
2923ff48bf5SDavid du Colombier  * Define the protection attributes.  Only 4 combinations are legal:
2933ff48bf5SDavid du Colombier  * 0, execute, execute + read, execute + read + write.  Note that some
2943ff48bf5SDavid du Colombier  * refs (such as scalars) do not use these: in such refs, they are
2953ff48bf5SDavid du Colombier  * always zero.
2963ff48bf5SDavid du Colombier  */
2977dd7cddfSDavid du Colombier #define a_write 0x10
2987dd7cddfSDavid du Colombier #define a_read 0x20
2997dd7cddfSDavid du Colombier #define a_execute 0x40
3007dd7cddfSDavid du Colombier #define a_readonly (a_read + a_execute)
3017dd7cddfSDavid du Colombier #define a_all (a_write + a_read+a_execute)
3023ff48bf5SDavid du Colombier /*
3033ff48bf5SDavid du Colombier  * Define the executable attribute.  All refs use this.
3043ff48bf5SDavid du Colombier  */
3053ff48bf5SDavid du Colombier #define a_executable 0x80
3063ff48bf5SDavid du Colombier /*
3073ff48bf5SDavid du Colombier  * Define the bits used for the ref type.  See ipacked.h for more
3083ff48bf5SDavid du Colombier  * information about the possible values of the type byte.
3093ff48bf5SDavid du Colombier  */
3107dd7cddfSDavid du Colombier #define r_type_shift 8
3117dd7cddfSDavid du Colombier #define r_type_bits 6
3127dd7cddfSDavid du Colombier 
313*593dc095SDavid du Colombier /*
314*593dc095SDavid du Colombier  * Define the attribute names for debugging printout.
315*593dc095SDavid du Colombier  * Each entry has the form <mask, value, character>.
316*593dc095SDavid du Colombier  */
317*593dc095SDavid du Colombier typedef struct ref_attr_print_mask_s {
3187dd7cddfSDavid du Colombier     ushort mask;
3197dd7cddfSDavid du Colombier     ushort value;
3207dd7cddfSDavid du Colombier     char print;
321*593dc095SDavid du Colombier } ref_attr_print_mask_t;
3227dd7cddfSDavid du Colombier 
323*593dc095SDavid du Colombier #define _REF_ATTR_PRINT_FLAG(m,c)\
3247dd7cddfSDavid du Colombier   {m,m,c},{m,0,'-'}
325*593dc095SDavid du Colombier #define _REF_ATTR_PRINT_SPACE(v,c)\
3267dd7cddfSDavid du Colombier   {((1<<r_space_bits)-1)<<r_space_shift,v,c}
327*593dc095SDavid du Colombier #define REF_ATTR_PRINT_MASKS\
328*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(l_mark,'m'),\
329*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(l_new,'n'),\
330*593dc095SDavid du Colombier   _REF_ATTR_PRINT_SPACE(avm_foreign,'F'),\
331*593dc095SDavid du Colombier   _REF_ATTR_PRINT_SPACE(avm_system,'S'),\
332*593dc095SDavid du Colombier   _REF_ATTR_PRINT_SPACE(avm_global,'G'),\
333*593dc095SDavid du Colombier   _REF_ATTR_PRINT_SPACE(avm_local,'L'),\
334*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(a_write,'w'),\
335*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(a_read,'r'),\
336*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(a_execute,'x'),\
337*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(a_executable,'e'),\
338*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(0x4000,'?'),\
339*593dc095SDavid du Colombier   _REF_ATTR_PRINT_FLAG(0x8000,'?')
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier /* Abstract types */
3427dd7cddfSDavid du Colombier typedef struct dict_s dict;
3437dd7cddfSDavid du Colombier typedef struct name_s name;
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier #ifndef stream_DEFINED
3467dd7cddfSDavid du Colombier #  define stream_DEFINED
3477dd7cddfSDavid du Colombier typedef struct stream_s stream;
3487dd7cddfSDavid du Colombier #endif
3497dd7cddfSDavid du Colombier #ifndef gx_device_DEFINED
3507dd7cddfSDavid du Colombier #  define gx_device_DEFINED
3517dd7cddfSDavid du Colombier typedef struct gx_device_s gx_device;
3527dd7cddfSDavid du Colombier #endif
3537dd7cddfSDavid du Colombier #ifndef obj_header_DEFINED
3547dd7cddfSDavid du Colombier #  define obj_header_DEFINED
3557dd7cddfSDavid du Colombier typedef struct obj_header_s obj_header_t;
3567dd7cddfSDavid du Colombier #endif
3577dd7cddfSDavid du Colombier 
3587dd7cddfSDavid du Colombier /*
3597dd7cddfSDavid du Colombier  * Define the argument type for operator procedures.  Note that the
3607dd7cddfSDavid du Colombier  * argument name is not arbitrary: it is used in access macros, so all
3617dd7cddfSDavid du Colombier  * operator procedures must use it.
3627dd7cddfSDavid du Colombier  */
3637dd7cddfSDavid du Colombier #ifndef i_ctx_t_DEFINED
3647dd7cddfSDavid du Colombier #  define i_ctx_t_DEFINED
3657dd7cddfSDavid du Colombier typedef struct gs_context_state_s i_ctx_t;
3667dd7cddfSDavid du Colombier #endif
367*593dc095SDavid du Colombier typedef int (*op_proc_t)(i_ctx_t *i_ctx_p);
3687dd7cddfSDavid du Colombier /* real_opproc is a holdover.... */
3697dd7cddfSDavid du Colombier #define real_opproc(pref) ((pref)->value.opproc)
3707dd7cddfSDavid du Colombier 
3717dd7cddfSDavid du Colombier /* Object reference */
3727dd7cddfSDavid du Colombier /*
3737dd7cddfSDavid du Colombier  * Note that because of the way packed arrays are represented,
3747dd7cddfSDavid du Colombier  * the type_attrs member must be the first one in the ref structure.
3757dd7cddfSDavid du Colombier  */
3767dd7cddfSDavid du Colombier struct tas_s {
377*593dc095SDavid du Colombier /* type_attrs is a single element for fast dispatching in the interpreter */
3787dd7cddfSDavid du Colombier     ushort type_attrs;
3797dd7cddfSDavid du Colombier     ushort rsize;
3807dd7cddfSDavid du Colombier };
3817dd7cddfSDavid du Colombier struct ref_s {
3827dd7cddfSDavid du Colombier 
3837dd7cddfSDavid du Colombier     struct tas_s tas;
3847dd7cddfSDavid du Colombier 
3857dd7cddfSDavid du Colombier     union v {			/* name the union to keep gdb happy */
3867dd7cddfSDavid du Colombier 	long intval;
3877dd7cddfSDavid du Colombier 	ushort boolval;
3887dd7cddfSDavid du Colombier 	float realval;
3897dd7cddfSDavid du Colombier 	ulong saveid;
3907dd7cddfSDavid du Colombier 	byte *bytes;
3917dd7cddfSDavid du Colombier 	const byte *const_bytes;
3927dd7cddfSDavid du Colombier 	ref *refs;
3937dd7cddfSDavid du Colombier 	const ref *const_refs;
3947dd7cddfSDavid du Colombier 	name *pname;
3957dd7cddfSDavid du Colombier 	const name *const_pname;
3967dd7cddfSDavid du Colombier 	dict *pdict;
3977dd7cddfSDavid du Colombier 	const dict *const_pdict;
3987dd7cddfSDavid du Colombier 	/*
3997dd7cddfSDavid du Colombier 	 * packed is the normal variant for referring to packed arrays,
4007dd7cddfSDavid du Colombier 	 * but we need a writable variant for memory management and for
4017dd7cddfSDavid du Colombier 	 * storing into packed dictionary key arrays.
4027dd7cddfSDavid du Colombier 	 */
4037dd7cddfSDavid du Colombier 	const ref_packed *packed;
4047dd7cddfSDavid du Colombier 	ref_packed *writable_packed;
4057dd7cddfSDavid du Colombier 	op_proc_t opproc;
4067dd7cddfSDavid du Colombier 	struct stream_s *pfile;
4077dd7cddfSDavid du Colombier 	struct gx_device_s *pdevice;
4087dd7cddfSDavid du Colombier 	obj_header_t *pstruct;
4097dd7cddfSDavid du Colombier     } value;
4107dd7cddfSDavid du Colombier };
4117dd7cddfSDavid du Colombier 
412*593dc095SDavid du Colombier /* ---------------- Private ref macros ---------------- */
413*593dc095SDavid du Colombier 
414*593dc095SDavid du Colombier /*
415*593dc095SDavid du Colombier  * Test whether a ref has a type within a given span, and also has all of a
416*593dc095SDavid du Colombier  * given set of attributes.
417*593dc095SDavid du Colombier  */
418*593dc095SDavid du Colombier #define _REF_HAS_MASKED_TYPE_ATTRS(rp,typ,tspan,mask)\
419*593dc095SDavid du Colombier  (((rp)->tas.type_attrs &\
420*593dc095SDavid du Colombier    ((((1 << r_type_bits) - (tspan)) << r_type_shift) + (mask))) ==\
421*593dc095SDavid du Colombier   (((typ) << r_type_shift) + (mask)))
422*593dc095SDavid du Colombier 
423*593dc095SDavid du Colombier /* ---------------- Public ref macros ---------------- */
424*593dc095SDavid du Colombier 
425*593dc095SDavid du Colombier /*
426*593dc095SDavid du Colombier  * All of these macros take an argument "rp" which is a pointer to a ref.
427*593dc095SDavid du Colombier  * Unless otherwise specified, they only apply to full-size (not packed)
428*593dc095SDavid du Colombier  * refs.
429*593dc095SDavid du Colombier  */
430*593dc095SDavid du Colombier 
431*593dc095SDavid du Colombier /*
432*593dc095SDavid du Colombier  * Read, set, increment, and decrement the size field of a ref.
433*593dc095SDavid du Colombier  */
434*593dc095SDavid du Colombier #define r_size(rp) ((rp)->tas.rsize)
435*593dc095SDavid du Colombier #define r_inc_size(rp,inc) ((rp)->tas.rsize += (inc))
436*593dc095SDavid du Colombier #define r_dec_size(rp,dec) ((rp)->tas.rsize -= (dec))
437*593dc095SDavid du Colombier #define r_set_size(rp,siz) ((rp)->tas.rsize = (siz))
438*593dc095SDavid du Colombier 
439*593dc095SDavid du Colombier /*
440*593dc095SDavid du Colombier  * Get the type of a ref; test whether a ref has a given type.  The
441*593dc095SDavid du Colombier  * difference between r_type and r_btype is that for refs with types greater
442*593dc095SDavid du Colombier  * than or equal to t_next_index, r_type returns that type, but r_btype
443*593dc095SDavid du Colombier  * returns t_operator (since those types just encode specific operators for
444*593dc095SDavid du Colombier  * faster dispatch in the interpreter -- see interp.h for more information).
445*593dc095SDavid du Colombier  */
446*593dc095SDavid du Colombier #if r_type_shift == 8
447*593dc095SDavid du Colombier #  if arch_is_big_endian
448*593dc095SDavid du Colombier #    define r_type(rp) (((const byte *)&((rp)->tas.type_attrs))[sizeof(ushort)-2])
449*593dc095SDavid du Colombier #  else
450*593dc095SDavid du Colombier #    define r_type(rp) (((const byte *)&((rp)->tas.type_attrs))[1])
451*593dc095SDavid du Colombier #  endif
452*593dc095SDavid du Colombier #  define r_has_type(rp,typ) (r_type(rp) == (typ))
453*593dc095SDavid du Colombier #else
454*593dc095SDavid du Colombier #  define r_type(rp) ((rp)->tas.type_attrs >> r_type_shift)
455*593dc095SDavid du Colombier #  define r_has_type(rp,typ) r_has_type_attrs(rp,typ,0)		/* see below */
456*593dc095SDavid du Colombier #endif
457*593dc095SDavid du Colombier #define r_btype(rp)\
458*593dc095SDavid du Colombier  ((rp)->tas.type_attrs >= (t_next_index << r_type_shift) ?\
459*593dc095SDavid du Colombier   t_operator : r_type(rp))
460*593dc095SDavid du Colombier 
461*593dc095SDavid du Colombier /*
462*593dc095SDavid du Colombier  * Test whether a ref is an array, or a procedure, or a(n) [a]struct.
463*593dc095SDavid du Colombier  */
464*593dc095SDavid du Colombier #define r_is_array(rp)\
465*593dc095SDavid du Colombier   _REF_HAS_MASKED_TYPE_ATTRS(rp,t_array,_REF_T_ARRAY_SPAN,0)
466*593dc095SDavid du Colombier #define r_is_proc(rp)\
467*593dc095SDavid du Colombier   _REF_HAS_MASKED_TYPE_ATTRS(rp,t_array,_REF_T_ARRAY_SPAN,a_execute+a_executable)
468*593dc095SDavid du Colombier #define r_is_struct(rp)\
469*593dc095SDavid du Colombier   _REF_HAS_MASKED_TYPE_ATTRS(rp,t_struct,_REF_T_STRUCT_SPAN,0)
470*593dc095SDavid du Colombier 
471*593dc095SDavid du Colombier /*
472*593dc095SDavid du Colombier  * Test whether a ref is a struct or astruct with a specific structure type
473*593dc095SDavid du Colombier  * (GC descriptor).
474*593dc095SDavid du Colombier  */
475*593dc095SDavid du Colombier #define r_has_stype(rp,mem,styp)\
476*593dc095SDavid du Colombier   (r_is_struct(rp) && gs_object_type(mem, (rp)->value.pstruct) == &styp)
477*593dc095SDavid du Colombier 
478*593dc095SDavid du Colombier /*
479*593dc095SDavid du Colombier  * Set the type of a ref.  This is only used in a few very special places.
480*593dc095SDavid du Colombier  * Normally the type of a ref is set when the ref is created (by one of
481*593dc095SDavid du Colombier  * the make_xxx macros in store.h) and never changed.
482*593dc095SDavid du Colombier  */
483*593dc095SDavid du Colombier #define r_set_type(rp,typ) ((rp)->tas.type_attrs = (typ) << r_type_shift)
484*593dc095SDavid du Colombier 
485*593dc095SDavid du Colombier /*
486*593dc095SDavid du Colombier  * Get, test, or set the type and attributes of a ref together as a single
487*593dc095SDavid du Colombier  * value.  This too is only used in a few special places.
488*593dc095SDavid du Colombier  */
489*593dc095SDavid du Colombier #define r_type_attrs(rp) ((rp)->tas.type_attrs)		/* reading only */
490*593dc095SDavid du Colombier #define r_has_type_attrs(rp,typ,mask)\
491*593dc095SDavid du Colombier   _REF_HAS_MASKED_TYPE_ATTRS(rp,typ,1,mask)
492*593dc095SDavid du Colombier #define r_set_type_attrs(rp,typ,mask)\
493*593dc095SDavid du Colombier   ((rp)->tas.type_attrs = ((typ) << r_type_shift) + (mask))
494*593dc095SDavid du Colombier 
495*593dc095SDavid du Colombier /*
496*593dc095SDavid du Colombier  * Get the combined type, a_executable, and a_execute bits of a ref,
497*593dc095SDavid du Colombier  * for fast dispatching in the interpreter.
498*593dc095SDavid du Colombier  */
499*593dc095SDavid du Colombier /*
500*593dc095SDavid du Colombier  * The r_type_xe macro is used in (and only in) the main interpreter loop,
501*593dc095SDavid du Colombier  * where its rp operand may be a ref_packed, not necessarily aligned as
502*593dc095SDavid du Colombier  * strictly as a full-size ref.  The DEC C compiler, and possibly others,
503*593dc095SDavid du Colombier  * may compile code assuming that rp is ref-aligned.  Therefore, we
504*593dc095SDavid du Colombier  * explicitly cast the pointer to a less-strictly-aligned type.
505*593dc095SDavid du Colombier  * In order to convince the compiler, we have to do the cast before
506*593dc095SDavid du Colombier  * indexing into the structure.
507*593dc095SDavid du Colombier  */
508*593dc095SDavid du Colombier #define _REF_TYPE_XE_SHIFT (r_type_shift - 2)
509*593dc095SDavid du Colombier #define _REF_TAS_TYPE_XE(tas) ((tas) >> _REF_TYPE_XE_SHIFT)
510*593dc095SDavid du Colombier #define r_type_xe(rp)\
511*593dc095SDavid du Colombier   _REF_TAS_TYPE_XE(((const ushort *)(rp))[offset_of(ref, tas.type_attrs) / sizeof(ushort)])
512*593dc095SDavid du Colombier #define type_xe_value(typ,xe) _REF_TAS_TYPE_XE(((typ) << r_type_shift) + (xe))
513*593dc095SDavid du Colombier 
514*593dc095SDavid du Colombier /*
515*593dc095SDavid du Colombier  * Test whether a ref has a given attribute, or all the given attributes.
516*593dc095SDavid du Colombier  */
517*593dc095SDavid du Colombier #define r_has_attr(rp,mask1)		/* optimize 1-bit case */\
518*593dc095SDavid du Colombier    (r_type_attrs(rp) & (mask1))
519*593dc095SDavid du Colombier #define r_has_attrs(rp,mask) !(~r_type_attrs(rp) & (mask))
520*593dc095SDavid du Colombier 
521*593dc095SDavid du Colombier /*
522*593dc095SDavid du Colombier  * Test whether those attributes of a ref selected by a mask have a
523*593dc095SDavid du Colombier  * given value.
524*593dc095SDavid du Colombier  */
525*593dc095SDavid du Colombier #define r_has_masked_attrs(rp,attrs,mask)\
526*593dc095SDavid du Colombier   ((r_type_attrs(rp) & (mask)) == (attrs))
527*593dc095SDavid du Colombier 
528*593dc095SDavid du Colombier /*
529*593dc095SDavid du Colombier  * Set, clear, store, or copy the attributes of a ref.  These are rarely
530*593dc095SDavid du Colombier  * needed.  Note that, unfortunately, the attrs and mask parameters of
531*593dc095SDavid du Colombier  * r_store_attrs are reversed from r_has_masked_attrs.
532*593dc095SDavid du Colombier  */
533*593dc095SDavid du Colombier #define r_set_attrs(rp,mask) ((rp)->tas.type_attrs |= (mask))
534*593dc095SDavid du Colombier #define r_clear_attrs(rp,mask) ((rp)->tas.type_attrs &= ~(mask))
535*593dc095SDavid du Colombier #define r_store_attrs(rp,mask,attrs)\
536*593dc095SDavid du Colombier   ((rp)->tas.type_attrs = ((rp)->tas.type_attrs & ~(mask)) | (attrs))
537*593dc095SDavid du Colombier #define r_copy_attrs(rp,mask,sp)\
538*593dc095SDavid du Colombier   r_store_attrs(rp,mask,(sp)->tas.type_attrs & (mask))
539*593dc095SDavid du Colombier 
540*593dc095SDavid du Colombier /*
541*593dc095SDavid du Colombier  * Get or set the pointer field of a struct or astruct ref.  The typ
542*593dc095SDavid du Colombier  * argument of r_ptr is the (C) type of the structure.
543*593dc095SDavid du Colombier  */
544*593dc095SDavid du Colombier #define r_ptr(rp,typ) ((typ *)((rp)->value.pstruct))
545*593dc095SDavid du Colombier #define r_set_ptr(rp,ptr) ((rp)->value.pstruct = (obj_header_t *)(ptr))
546*593dc095SDavid du Colombier 
547*593dc095SDavid du Colombier /* ---------------- End of ref macros ---------------- */
548*593dc095SDavid du Colombier 
5497dd7cddfSDavid du Colombier /* Define data for initializing an empty array or string. */
5507dd7cddfSDavid du Colombier #define empty_ref_data(type, attrs)\
5517dd7cddfSDavid du Colombier   { /*tas*/ { /*type_attrs*/ ((type) << r_type_shift) | (attrs),\
5527dd7cddfSDavid du Colombier 	      /*rsize*/ 0 } }
5537dd7cddfSDavid du Colombier 
5547dd7cddfSDavid du Colombier /* Define the size of a ref. */
5557dd7cddfSDavid du Colombier #define arch_sizeof_ref sizeof(ref)
5567dd7cddfSDavid du Colombier /* Define the required alignment for refs. */
5577dd7cddfSDavid du Colombier /* We assume all alignment values are powers of 2. */
5587dd7cddfSDavid du Colombier #define arch_align_ref_mod\
5597dd7cddfSDavid du Colombier  (((arch_align_long_mod - 1) | (arch_align_float_mod - 1) |\
5607dd7cddfSDavid du Colombier    (arch_align_ptr_mod - 1)) + 1)
5617dd7cddfSDavid du Colombier 
5627dd7cddfSDavid du Colombier /* Define the maximum size of an array or a string. */
5637dd7cddfSDavid du Colombier /* The maximum array size is determined by the fact that */
5647dd7cddfSDavid du Colombier /* the allocator cannot allocate a block larger than max_uint. */
5657dd7cddfSDavid du Colombier #define max_array_size (max_ushort & (max_uint / (uint)arch_sizeof_ref))
5667dd7cddfSDavid du Colombier #define max_string_size max_ushort
5677dd7cddfSDavid du Colombier 
5687dd7cddfSDavid du Colombier #endif /* iref_INCLUDED */
569