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