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