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