1 /* Copyright (C) 2001-2006 Artifex Software, Inc.
2    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, modified
8    or distributed except as expressly authorized under the terms of that
9    license.  Refer to licensing information at http://www.artifex.com/
10    or contact Artifex Software, Inc.,  7 Mt. Lassen Drive - Suite A-134,
11    San Rafael, CA  94903, U.S.A., +1(415)492-9861, for further information.
12 */
13 
14 /* $Id: store.h 9323 2009-01-04 20:20:47Z till $ */
15 /* Assignment-related macros */
16 
17 #ifndef store_INCLUDED
18 #  define store_INCLUDED
19 
20 #include "ialloc.h"		/* for imemory masks & checks */
21 #include "idosave.h"
22 
23 /*
24  * Macros for storing a ref.  We use macros for storing into objects,
25  * since the storage manager needs to be able to track stores for
26  * save/restore and also for global/local checking.
27  * We also use macros for other ref assignments, because (as it happens)
28  * Turbo C generates pretty awful code for doing this.
29  *
30  * There are three cases that we need to distinguish:
31  *      - Storing to a stack (no special action);
32  *      - Storing into a newly created object (set l_new);
33  *      - Storing into a slot of an existing object (check l_new in
34  *          old value, set in new value).
35  * The macros are called
36  *      <make/store><new_type><case>(place_to_store, new_value)
37  * where <case> is nothing for storing to the stack, _new for storing into
38  * a new object, and _old for storing into an existing object.
39  * (The _old macros also take a client name for tracing and debugging.)
40  * <new_type> and new_value are chosen from the following alternatives:
41  *      ref_assign      POINTER TO arbitrary ref
42  *      make_t          type (only for null and mark)
43  *      make_tv         type, value field name, value
44  *                        (only for scalars, which don't have attributes)
45  *      make_tav        type, attributes, value field name, value
46  *      make_tasv       type, attributes, size, value field name, value
47  * There are also specialized make_ macros for specific types:
48  *      make_array, make_int, make_real, make_bool, make_false, make_true,
49  *      make_mark, make_null, make_oper, make_[const_]string, make_struct.
50  * Not all of the specialized make_ macros have _new and _old variants.
51  *
52  * For _tav and _tasv, we must store the value first, because sometimes
53  * it depends on the contents of the place being stored into.
54  *
55  * Note that for composite objects (dictionary, file, array, string, device,
56  * struct), we must set a_foreign if the contents are allocated statically
57  * (e.g., for constant C strings) or not by the Ghostscript allocator
58  * (e.g., with malloc).
59  */
60 
61 /*
62  * Define the most efficient ref assignment macro for the platform.
63  */
64 /*
65  * Assigning the components individually is fastest on Turbo C,
66  * and on Watcom C when one or both of the addresses are
67  * already known or in a register.
68  *
69  * Though, it sends wrong signals to the compiler that believes it's okay-ish
70  * to update the structure in two calls, and risks very wrong reordering. This
71  * _MUST_ be done in one call, and trust the compiler to do the proper thing,
72  * if not too bad. And we're using GCC anyways on Debian.
73  */
74 #define ref_assign_inline(pto,pfrom)\
75 	(*(pto) = *(pfrom))
76 #ifdef __TURBOC__
77 	/*
78 	 * Move the data in two 32-bit chunks, because
79 	 * otherwise the compiler calls SCOPY@.
80 	 * The cast to void is to discourage the compiler from
81 	 * wanting to deliver the value of the expression.
82 	 */
83 #  define ref_assign(pto,pfrom)\
84 	discard(ref_assign_inline(pto, pfrom))
85 #else
86 	/*
87 	 * Trust the compiler and hope for the best.
88 	 * The MIPS compiler doesn't like the cast to void.
89 	 */
90 #  define ref_assign(pto,pfrom)\
91 	(*(pto) = *(pfrom))
92 #endif
93 
94 #define ialloc_new_mask (idmemory->new_mask)
95      /*
96       * The mmem argument may be either a gs_dual_memory_t or a
97       * gs_ref_memory_t, since it is only used for accessing the masks.
98       */
99 #define ref_saving_in(mmem)\
100   ((mmem)->new_mask != 0)
101 #define ref_must_save_in(mmem,pto)\
102   ((r_type_attrs(pto) & (mmem)->test_mask) == 0)
103 #define ref_must_save(pto) ref_must_save_in(idmemory, pto)
104 #define ref_do_save_in(mem, pcont, pto, cname)\
105   alloc_save_change_in(mem, pcont, (ref_packed *)(pto), cname)
106 #define ref_do_save(pcont, pto, cname)\
107   alloc_save_change(idmemory, pcont, (ref_packed *)(pto), cname)
108 #define ref_save_in(mem, pcont, pto, cname)\
109   discard((ref_must_save_in(mem, pto) ?\
110 	   ref_do_save_in(mem, pcont, pto, cname) : 0))
111 #define ref_save(pcont, pto, cname)\
112   discard((ref_must_save(pto) ? ref_do_save(pcont, pto, cname) : 0))
113 #define ref_mark_new_in(mmem,pto)\
114   ((pto)->tas.type_attrs |= (mmem)->new_mask)
115 #define ref_mark_new(pto) ref_mark_new_in(idmemory, pto)
116 #define ref_assign_new_in(mem,pto,pfrom)\
117   discard((ref_assign(pto,pfrom), ref_mark_new_in(mem,pto)))
118 #define ref_assign_new(pto,pfrom)\
119   discard((ref_assign(pto,pfrom), ref_mark_new(pto)))
120 #define ref_assign_new_inline(pto,pfrom)\
121   discard((ref_assign_inline(pto,pfrom), ref_mark_new(pto)))
122 #define ref_assign_old_in(mem,pcont,pto,pfrom,cname)\
123   (ref_save_in(mem,pcont,pto,cname), ref_assign_new_in(mem,pto,pfrom))
124 #define ref_assign_old(pcont,pto,pfrom,cname)\
125   (ref_save(pcont,pto,cname), ref_assign_new(pto,pfrom))
126 #define ref_assign_old_inline(pcont,pto,pfrom,cname)\
127   (ref_save(pcont,pto,cname), ref_assign_new_inline(pto,pfrom))
128 /* ref_mark_old is only needed in very unusual situations, namely, */
129 /* when we want to do a ref_save just before a save instead of */
130 /* when the actual assignment occurs. */
131 #define ref_mark_old(pto) ((pto)->tas.type_attrs &= ~ialloc_new_mask)
132 
133 /* Define macros for conditionally clearing the parts of a ref */
134 /* that aren't being set to anything useful. */
135 
136 #ifdef DEBUG
137 #  define and_fill_s(pref)\
138     , (gs_debug['$'] ? r_set_size(pref, 0xfeed) : 0)
139 /*
140  * The following nonsense avoids compiler warnings about signed/unsigned
141  * integer constants.
142  */
143 #define DEADBEEF ((int)(((uint)0xdead << 16) | 0xbeef))
144 #  define and_fill_sv(pref)\
145     , (gs_debug['$'] ? (r_set_size(pref, 0xfeed),\
146 			(pref)->value.intval = DEADBEEF) : 0)
147 #else /* !DEBUG */
148 #  define and_fill_s(pref)	/* */
149 #  define and_fill_sv(pref)	/* */
150 #endif
151 
152 /* make_t must set the attributes to 0 to clear a_local! */
153 #define make_ta(pref,newtype,newattrs)\
154   (r_set_type_attrs(pref, newtype, newattrs) and_fill_sv(pref))
155 #define make_t(pref,newtype)\
156   make_ta(pref, newtype, 0)
157 #define make_t_new_in(mem,pref,newtype)\
158   make_ta(pref, newtype, imemory_new_mask(mem))
159 #define make_t_new(pref,newtype)\
160   make_ta(pref, newtype, ialloc_new_mask)
161 #define make_t_old_in(mem,pcont,pref,newtype,cname)\
162   (ref_save_in(mem,pcont,pref,cname), make_t_new_in(mem,pref,newtype))
163 #define make_t_old(pcont,pref,newtype,cname)\
164   (ref_save(pcont,pref,cname), make_t_new(pref,newtype))
165 
166 #define make_tav(pref,newtype,newattrs,valfield,newvalue)\
167   ((pref)->value.valfield = (newvalue),\
168    r_set_type_attrs(pref, newtype, newattrs)\
169    and_fill_s(pref))
170 #define make_tav_new(pref,t,a,vf,v)\
171   make_tav(pref,t,(a)|ialloc_new_mask,vf,v)
172 #define make_tav_old(pcont,pref,t,a,vf,v,cname)\
173   (ref_save(pcont,pref,cname), make_tav_new(pref,t,a,vf,v))
174 
175 #define make_tv(pref,newtype,valfield,newvalue)\
176   make_tav(pref,newtype,0,valfield,newvalue)
177 #define make_tv_new(pref,t,vf,v)\
178   make_tav_new(pref,t,0,vf,v)
179 #define make_tv_old(pcont,pref,t,vf,v,cname)\
180   make_tav_old(pcont,pref,t,0,vf,v,cname)
181 
182 #define make_tasv(pref,newtype,newattrs,newsize,valfield,newvalue)\
183   ((pref)->value.valfield = (newvalue),\
184    r_set_type_attrs(pref, newtype, newattrs),\
185    r_set_size(pref, newsize))
186 #define make_tasv_new(pref,t,a,s,vf,v)\
187   make_tasv(pref,t,(a)|ialloc_new_mask,s,vf,v)
188 #define make_tasv_old(pcont,pref,t,a,s,vf,v,cname)\
189   (ref_save(pcont,pref,cname), make_tasv_new(pref,t,a,s,vf,v))
190 
191 /* Type-specific constructor macros for scalar (non-composite) types */
192 
193 #define make_bool(pref,bval)\
194   make_tv(pref, t_boolean, boolval, bval)
195 #define make_false(pref)\
196   make_bool(pref, 0)
197 #define make_true(pref)\
198   make_bool(pref, 1)
199 
200 #define make_int(pref,ival)\
201   make_tv(pref, t_integer, intval, ival)
202 #define make_int_new(pref,ival)\
203   make_tv_new(pref, t_integer, intval, ival)
204 
205 #define make_mark(pref)\
206   make_t(pref, t_mark)
207 
208 #define make_null(pref)\
209   make_t(pref, t_null)
210 #define make_null_new(pref)\
211   make_t_new(pref, t_null)
212 #define make_null_old_in(mem,pcont,pref,cname)\
213   make_t_old_in(mem, pcont, pref, t_null, cname)
214 #define make_null_old(pcont,pref,cname)\
215   make_t_old(pcont, pref, t_null, cname)
216 
217 #define make_oper(pref,opidx,proc)\
218   make_tasv(pref, t_operator, a_executable, opidx, opproc, proc)
219 #define make_oper_new(pref,opidx,proc)\
220   make_tasv_new(pref, t_operator, a_executable, opidx, opproc, proc)
221 
222 #define make_real(pref,rval)\
223   make_tv(pref, t_real, realval, rval)
224 #define make_real_new(pref,rval)\
225   make_tv_new(pref, t_real, realval, rval)
226 
227 /* Type-specific constructor macros for composite types */
228 
229 /* For composite types, the a_space field is relevant; however, */
230 /* as noted in ivmspace.h, a value of 0 designates the most static space, */
231 /* so for making empty composites, a space value of 0 is appropriate. */
232 
233 #define make_array(pref,attrs,size,elts)\
234   make_tasv(pref, t_array, attrs, size, refs, elts)
235 #define make_array_new(pref,attrs,size,elts)\
236   make_tasv_new(pref, t_array, attrs, size, refs, elts)
237 #define make_const_array(pref,attrs,size,elts)\
238   make_tasv(pref, t_array, attrs, size, const_refs, elts)
239 #define make_empty_array(pref,attrs)\
240   make_array(pref, attrs, 0, (ref *)NULL)
241 #define make_empty_const_array(pref,attrs)\
242   make_const_array(pref, attrs, 0, (const ref *)NULL)
243 
244 #define make_string(pref,attrs,size,chars)\
245   make_tasv(pref, t_string, attrs, size, bytes, chars)
246 #define make_const_string(pref,attrs,size,chars)\
247   make_tasv(pref, t_string, attrs, size, const_bytes, chars)
248 #define make_empty_string(pref,attrs)\
249   make_string(pref, attrs, 0, (byte *)NULL)
250 #define make_empty_const_string(pref,attrs)\
251   make_const_string(pref, attrs, 0, (const byte *)NULL)
252 
253 #define make_struct(pref,attrs,ptr)\
254   make_tav(pref, t_struct, attrs, pstruct, (obj_header_t *)(ptr))
255 #define make_struct_new(pref,attrs,ptr)\
256   make_tav_new(pref, t_struct, attrs, pstruct, (obj_header_t *)(ptr))
257 
258 #define make_astruct(pref,attrs,ptr)\
259   make_tav(pref, t_astruct, attrs, pstruct, (obj_header_t *)(ptr))
260 #define make_astruct_new(pref,attrs,ptr)\
261   make_tav_new(pref, t_astruct, attrs, pstruct, (obj_header_t *)(ptr))
262 
263 #endif /* store_INCLUDED */
264