summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Deutschmann <whissi@gentoo.org>2019-10-15 12:24:12 +0200
committerThomas Deutschmann <whissi@gentoo.org>2020-08-13 11:26:55 +0200
commite088156d5b620e5e639580dacf85c6dc13823c74 (patch)
tree57f5c025e203279944da512166c20bc0521d8ccd /psi/store.h
downloadghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.tar.gz
ghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.tar.bz2
ghostscript-gpl-patches-e088156d5b620e5e639580dacf85c6dc13823c74.zip
Import Ghostscript 9.50ghostscript-9.50
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'psi/store.h')
-rw-r--r--psi/store.h265
1 files changed, 265 insertions, 0 deletions
diff --git a/psi/store.h b/psi/store.h
new file mode 100644
index 00000000..3bed0e9f
--- /dev/null
+++ b/psi/store.h
@@ -0,0 +1,265 @@
+/* Copyright (C) 2001-2019 Artifex Software, Inc.
+ All Rights Reserved.
+
+ This software is provided AS-IS with no warranty, either express or
+ implied.
+
+ This software is distributed under license and may not be copied,
+ modified or distributed except as expressly authorized under the terms
+ of the license contained in the file LICENSE in this distribution.
+
+ Refer to licensing information at http://www.artifex.com or contact
+ Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
+ CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+
+/* Assignment-related macros */
+
+#ifndef store_INCLUDED
+# define store_INCLUDED
+
+#include "ialloc.h" /* for imemory masks & checks */
+#include "idosave.h"
+
+/*
+ * Macros for storing a ref. We use macros for storing into objects,
+ * since the storage manager needs to be able to track stores for
+ * save/restore and also for global/local checking.
+ * We also use macros for other ref assignments, because (as it happens)
+ * Turbo C generates pretty awful code for doing this.
+ *
+ * There are three cases that we need to distinguish:
+ * - Storing to a stack (no special action);
+ * - Storing into a newly created object (set l_new);
+ * - Storing into a slot of an existing object (check l_new in
+ * old value, set in new value).
+ * The macros are called
+ * <make/store><new_type><case>(place_to_store, new_value)
+ * where <case> is nothing for storing to the stack, _new for storing into
+ * a new object, and _old for storing into an existing object.
+ * (The _old macros also take a client name for tracing and debugging.)
+ * <new_type> and new_value are chosen from the following alternatives:
+ * ref_assign POINTER TO arbitrary ref
+ * make_t type (only for null and mark)
+ * make_tv type, value field name, value
+ * (only for scalars, which don't have attributes)
+ * make_tav type, attributes, value field name, value
+ * make_tasv type, attributes, size, value field name, value
+ * There are also specialized make_ macros for specific types:
+ * make_array, make_int, make_real, make_bool, make_false, make_true,
+ * make_mark, make_null, make_oper, make_[const_]string, make_struct.
+ * Not all of the specialized make_ macros have _new and _old variants.
+ *
+ * For _tav and _tasv, we must store the value first, because sometimes
+ * it depends on the contents of the place being stored into.
+ *
+ * Note that for composite objects (dictionary, file, array, string, device,
+ * struct), we must set a_foreign if the contents are allocated statically
+ * (e.g., for constant C strings) or not by the Ghostscript allocator
+ * (e.g., with malloc).
+ */
+
+/*
+ * Define the most efficient ref assignment macro for the platform.
+ */
+/*
+ * Assigning the components individually is fastest on Turbo C,
+ * and on Watcom C when one or both of the addresses are
+ * already known or in a register.
+ *
+ * Though, it sends wrong signals to the compiler that believes it's okay-ish
+ * to update the structure in two calls, and risks very wrong reordering. This
+ * _MUST_ be done in one call, and trust the compiler to do the proper thing,
+ * if not too bad. And we're using GCC anyways on Debian.
+ */
+#define ref_assign_inline(pto,pfrom)\
+ (*(pto) = *(pfrom))
+#ifdef __TURBOC__
+ /*
+ * Move the data in two 32-bit chunks, because
+ * otherwise the compiler calls SCOPY@.
+ * The cast to void is to discourage the compiler from
+ * wanting to deliver the value of the expression.
+ */
+# define ref_assign(pto,pfrom)\
+ discard(ref_assign_inline(pto, pfrom))
+#else
+ /*
+ * Trust the compiler and hope for the best.
+ * The MIPS compiler doesn't like the cast to void.
+ */
+# define ref_assign(pto,pfrom)\
+ (*(pto) = *(pfrom))
+#endif
+
+#define ialloc_new_mask (idmemory->new_mask)
+ /*
+ * The mmem argument may be either a gs_dual_memory_t or a
+ * gs_ref_memory_t, since it is only used for accessing the masks.
+ */
+#define ref_saving_in(mmem)\
+ ((mmem)->new_mask != 0)
+#define ref_must_save_in(mmem,pto)\
+ ((r_type_attrs(pto) & (mmem)->test_mask) == 0)
+#define ref_must_save(pto) ref_must_save_in(idmemory, pto)
+#define ref_do_save_in(mem, pcont, pto, cname)\
+ alloc_save_change_in(mem, pcont, (ref_packed *)(pto), cname)
+#define ref_do_save(pcont, pto, cname)\
+ alloc_save_change(idmemory, pcont, (ref_packed *)(pto), cname)
+#define ref_save_in(mem, pcont, pto, cname)\
+ discard((ref_must_save_in(mem, pto) ?\
+ ref_do_save_in(mem, pcont, pto, cname) : 0))
+#define ref_save(pcont, pto, cname)\
+ discard((ref_must_save(pto) ? ref_do_save(pcont, pto, cname) : 0))
+#define ref_mark_new_in(mmem,pto)\
+ ((pto)->tas.type_attrs |= (mmem)->new_mask)
+#define ref_mark_new(pto) ref_mark_new_in(idmemory, pto)
+#define ref_assign_new_in(mem,pto,pfrom)\
+ discard((ref_assign(pto,pfrom), ref_mark_new_in(mem,pto)))
+#define ref_assign_new(pto,pfrom)\
+ discard((ref_assign(pto,pfrom), ref_mark_new(pto)))
+#define ref_assign_new_inline(pto,pfrom)\
+ discard((ref_assign_inline(pto,pfrom), ref_mark_new(pto)))
+#define ref_assign_old_in(mem,pcont,pto,pfrom,cname)\
+ (ref_save_in(mem,pcont,pto,cname), ref_assign_new_in(mem,pto,pfrom))
+#define ref_assign_old(pcont,pto,pfrom,cname)\
+ (ref_save(pcont,pto,cname), ref_assign_new(pto,pfrom))
+#define ref_assign_old_inline(pcont,pto,pfrom,cname)\
+ (ref_save(pcont,pto,cname), ref_assign_new_inline(pto,pfrom))
+/* ref_mark_old is only needed in very unusual situations, namely, */
+/* when we want to do a ref_save just before a save instead of */
+/* when the actual assignment occurs. */
+#define ref_mark_old(pto) ((pto)->tas.type_attrs &= ~ialloc_new_mask)
+
+/* Define macros for conditionally clearing the parts of a ref */
+/* that aren't being set to anything useful. */
+
+#ifdef DEBUG
+# define and_fill_s(pref)\
+ , (gs_debug['$'] ? r_set_size(pref, 0xfeed) : 0)
+/*
+ * The following nonsense avoids compiler warnings about signed/unsigned
+ * integer constants.
+ */
+#define DEADBEEF ((int)(((uint)0xdead << 16) | 0xbeef))
+# define and_fill_sv(pref)\
+ , (gs_debug['$'] ? (r_set_size(pref, 0xfeed),\
+ (pref)->value.intval = DEADBEEF) : 0)
+#else /* !DEBUG */
+# define and_fill_s(pref) /* */
+# define and_fill_sv(pref) /* */
+#endif
+
+/* make_t must set the attributes to 0 to clear a_local! */
+#define make_ta(pref,newtype,newattrs)\
+ (r_set_type_attrs(pref, newtype, newattrs) and_fill_sv(pref))
+#define make_t(pref,newtype)\
+ make_ta(pref, newtype, 0)
+#define make_t_new_in(mem,pref,newtype)\
+ make_ta(pref, newtype, imemory_new_mask(mem))
+#define make_t_new(pref,newtype)\
+ make_ta(pref, newtype, ialloc_new_mask)
+#define make_t_old_in(mem,pcont,pref,newtype,cname)\
+ (ref_save_in(mem,pcont,pref,cname), make_t_new_in(mem,pref,newtype))
+#define make_t_old(pcont,pref,newtype,cname)\
+ (ref_save(pcont,pref,cname), make_t_new(pref,newtype))
+
+#define make_tav(pref,newtype,newattrs,valfield,newvalue)\
+ ((pref)->value.valfield = (newvalue),\
+ r_set_type_attrs(pref, newtype, newattrs)\
+ and_fill_s(pref))
+#define make_tav_new(pref,t,a,vf,v)\
+ make_tav(pref,t,(a)|ialloc_new_mask,vf,v)
+#define make_tav_old(pcont,pref,t,a,vf,v,cname)\
+ (ref_save(pcont,pref,cname), make_tav_new(pref,t,a,vf,v))
+
+#define make_tv(pref,newtype,valfield,newvalue)\
+ make_tav(pref,newtype,0,valfield,newvalue)
+#define make_tv_new(pref,t,vf,v)\
+ make_tav_new(pref,t,0,vf,v)
+#define make_tv_old(pcont,pref,t,vf,v,cname)\
+ make_tav_old(pcont,pref,t,0,vf,v,cname)
+
+#define make_tasv(pref,newtype,newattrs,newsize,valfield,newvalue)\
+ ((pref)->value.valfield = (newvalue),\
+ r_set_type_attrs(pref, newtype, newattrs),\
+ r_set_size(pref, newsize))
+#define make_tasv_new(pref,t,a,s,vf,v)\
+ make_tasv(pref,t,(a)|ialloc_new_mask,s,vf,v)
+#define make_tasv_old(pcont,pref,t,a,s,vf,v,cname)\
+ (ref_save(pcont,pref,cname), make_tasv_new(pref,t,a,s,vf,v))
+
+/* Type-specific constructor macros for scalar (non-composite) types */
+
+#define make_bool(pref,bval)\
+ make_tv(pref, t_boolean, boolval, bval)
+#define make_false(pref)\
+ make_bool(pref, 0)
+#define make_true(pref)\
+ make_bool(pref, 1)
+
+#define make_int(pref,ival)\
+ make_tv(pref, t_integer, intval, ival)
+#define make_int_new(pref,ival)\
+ make_tv_new(pref, t_integer, intval, ival)
+
+#define make_mark(pref)\
+ make_t(pref, t_mark)
+
+#define make_null(pref)\
+ make_t(pref, t_null)
+#define make_null_new(pref)\
+ make_t_new(pref, t_null)
+#define make_null_old_in(mem,pcont,pref,cname)\
+ make_t_old_in(mem, pcont, pref, t_null, cname)
+#define make_null_old(pcont,pref,cname)\
+ make_t_old(pcont, pref, t_null, cname)
+
+#define make_oper(pref,opidx,proc)\
+ make_tasv(pref, t_operator, a_executable, opidx, opproc, proc)
+#define make_oper_new(pref,opidx,proc)\
+ make_tasv_new(pref, t_operator, a_executable, opidx, opproc, proc)
+
+#define make_real(pref,rval)\
+ make_tv(pref, t_real, realval, rval)
+#define make_real_new(pref,rval)\
+ make_tv_new(pref, t_real, realval, rval)
+
+/* Type-specific constructor macros for composite types */
+
+/* For composite types, the a_space field is relevant; however, */
+/* as noted in ivmspace.h, a value of 0 designates the most static space, */
+/* so for making empty composites, a space value of 0 is appropriate. */
+
+#define make_array(pref,attrs,size,elts)\
+ make_tasv(pref, t_array, attrs, size, refs, elts)
+#define make_array_new(pref,attrs,size,elts)\
+ make_tasv_new(pref, t_array, attrs, size, refs, elts)
+#define make_const_array(pref,attrs,size,elts)\
+ make_tasv(pref, t_array, attrs, size, const_refs, elts)
+#define make_empty_array(pref,attrs)\
+ make_array(pref, attrs, 0, (ref *)NULL)
+#define make_empty_const_array(pref,attrs)\
+ make_const_array(pref, attrs, 0, (const ref *)NULL)
+
+#define make_string(pref,attrs,size,chars)\
+ make_tasv(pref, t_string, attrs, size, bytes, chars)
+#define make_const_string(pref,attrs,size,chars)\
+ make_tasv(pref, t_string, attrs, size, const_bytes, chars)
+#define make_empty_string(pref,attrs)\
+ make_string(pref, attrs, 0, (byte *)NULL)
+#define make_empty_const_string(pref,attrs)\
+ make_const_string(pref, attrs, 0, (const byte *)NULL)
+
+#define make_struct(pref,attrs,ptr)\
+ make_tav(pref, t_struct, attrs, pstruct, (obj_header_t *)(ptr))
+#define make_struct_new(pref,attrs,ptr)\
+ make_tav_new(pref, t_struct, attrs, pstruct, (obj_header_t *)(ptr))
+
+#define make_astruct(pref,attrs,ptr)\
+ make_tav(pref, t_astruct, attrs, pstruct, (obj_header_t *)(ptr))
+#define make_astruct_new(pref,attrs,ptr)\
+ make_tav_new(pref, t_astruct, attrs, pstruct, (obj_header_t *)(ptr))
+
+#endif /* store_INCLUDED */