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 */ 263