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