1 /* Copyright (C) 1992, 1995, 1997, 1998, 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: istack.h,v 1.2.6.1.2.1 2003/01/17 00:49:04 giles Exp $ */
20 /* Definitions for expandable stacks of refs */
21 /* Requires iref.h */
22 
23 #ifndef istack_INCLUDED
24 #  define istack_INCLUDED
25 
26 #include "isdata.h"
27 
28 /*
29  * The 3 principal Ghostscript stacks (operand, execution, and dictionary)
30  * are implemented as a linked list of blocks.
31  *
32  * Since all operators exit cleanly in case of stack under- or overflow,
33  * we handle all issues related to stack blocks in the top-level error
34  * recovery code in interp.c.  A few situations require special treatment:
35  * see ostack.h, estack.h, and dstack.h for details.
36  */
37 
38 /*
39  * Define the structure for a stack block.
40  * In order to simplify allocation, stack blocks are implemented as
41  * t_array objects, with the first few elements used for special purposes.
42  * The actual layout is as follows:
43  *              ref_stack_block structure
44  *              bottom guard if any (see below)
45  *              used elements of block
46  *              unused elements of block
47  *              top guard if any (see below)
48  * The `next' member of the next higher stack block includes all of this.
49  * The `used' member only includes the used elements of this block.
50  * Notes:
51  *      - In the top block, the size of the `used' member may not be correct.
52  *      - In all blocks but the top, we fill the unused elements with nulls.
53  */
54 typedef struct ref_stack_block_s {
55     ref next;			/* t_array, next lower block on stack */
56     ref used;			/* t_array, subinterval of this block */
57     /* Actual stack starts here */
58 } ref_stack_block;
59 
60 #define stack_block_refs (sizeof(ref_stack_block) / sizeof(ref))
61 
62 /* ------ Procedural interface ------ */
63 
64 /*
65  * Initialize a stack.  Note that this allocates the stack parameter
66  * structure iff params is not NULL.
67  */
68 int ref_stack_init(P7(ref_stack_t *pstack, const ref *pblock_array,
69 		      uint bot_guard, uint top_guard,
70 		      const ref *pguard_value, gs_ref_memory_t *mem,
71 		      ref_stack_params_t *params));
72 
73 /* Set whether a stack is allowed to expand.  The initial value is true. */
74 void ref_stack_allow_expansion(P2(ref_stack_t *pstack, bool expand));
75 
76 /* Set the error codes for under- and overflow.  The initial values are -1. */
77 void ref_stack_set_error_codes(P3(ref_stack_t *pstack, int underflow_error,
78 				  int overflow_error));
79 
80 /*
81  * Set the maximum number of elements allowed on a stack.
82  * Note that the value is a long, not a uint or a ulong.
83  */
84 int ref_stack_set_max_count(P2(ref_stack_t *pstack, long nmax));
85 
86 /*
87  * Set the margin between the limit and the top of the stack.
88  * Note that this may require allocating a block.
89  */
90 int ref_stack_set_margin(P2(ref_stack_t *pstack, uint margin));
91 
92 /* Return the number of elements on a stack. */
93 uint ref_stack_count(P1(const ref_stack_t *pstack));
94 
95 #define ref_stack_count_inline(pstk)\
96   ((pstk)->p + 1 - (pstk)->bot + (pstk)->extension_used)
97 
98 /* Return the maximum number of elements allowed on a stack. */
99 #define ref_stack_max_count(pstk) (uint)((pstk)->max_stack.value.intval)
100 
101 /*
102  * Return a pointer to a given element from the stack, counting from
103  * 0 as the top element.  If the index is out of range, return 0.
104  * Note that the index is a long, not a uint or a ulong.
105  */
106 ref *ref_stack_index(P2(const ref_stack_t *pstack, long index));
107 
108 /*
109  * Count the number of elements down to and including the first mark.
110  * If no mark is found, return 0.
111  */
112 uint ref_stack_counttomark(P1(const ref_stack_t *pstack));
113 
114 /*
115  * Do the store check for storing 'count' elements of a stack, starting
116  * 'skip' elements below the top, into an array.  Return 0 or e_invalidaccess.
117  */
118 int ref_stack_store_check(P4(const ref_stack_t *pstack, ref *parray,
119 			     uint count, uint skip));
120 
121 /*
122  * Store the top 'count' elements of a stack, starting 'skip' elements below
123  * the top, into an array, with or without store/undo checking.  age=-1 for
124  * no check, 0 for old, 1 for new.  May return e_rangecheck or
125  * e_invalidaccess.
126  */
127 #ifndef gs_dual_memory_DEFINED
128 #  define gs_dual_memory_DEFINED
129 typedef struct gs_dual_memory_s gs_dual_memory_t;
130 #endif
131 int ref_stack_store(P8(const ref_stack_t *pstack, ref *parray, uint count,
132 		       uint skip, int age, bool check,
133 		       gs_dual_memory_t *idmem, client_name_t cname));
134 
135 /*
136  * Pop the top N elements off a stack.
137  * The number must not exceed the number of elements in use.
138  */
139 void ref_stack_pop(P2(ref_stack_t *pstack, uint count));
140 
141 #define ref_stack_clear(pstk) ref_stack_pop(pstk, ref_stack_count(pstk))
142 #define ref_stack_pop_to(pstk, depth)\
143   ref_stack_pop(pstk, ref_stack_count(pstk) - (depth))
144 
145 /* Pop the top block off a stack.  May return underflow_error. */
146 int ref_stack_pop_block(P1(ref_stack_t *pstack));
147 
148 /*
149  * Extend a stack to recover from an overflow condition.
150  * Uses the requested value to decide what to do.
151  * May return overflow_error or e_VMerror.
152  */
153 int ref_stack_extend(P2(ref_stack_t *pstack, uint request));
154 
155 /*
156  * Push N empty slots onto a stack.  These slots are not initialized:
157  * the caller must immediately fill them.  May return overflow_error
158  * (if max_stack would be exceeded, or the stack has no allocator)
159  * or e_VMerror.
160  */
161 int ref_stack_push(P2(ref_stack_t *pstack, uint count));
162 
163 /*
164  * Enumerate the blocks of a stack from top to bottom, as follows:
165 
166    ref_stack_enum_t rsenum;
167 
168    ref_stack_enum_begin(&rsenum, pstack);
169    do {
170       ... process rsenum.size refs starting at rsenum.ptr ...
171    } while (ref_stack_enum_next(&rsenum));
172 
173  */
174 typedef struct ref_stack_enum_s {
175     ref_stack_block *block;
176     ref *ptr;
177     uint size;
178 } ref_stack_enum_t;
179 void ref_stack_enum_begin(P2(ref_stack_enum_t *prse,
180 			     const ref_stack_t *pstack));
181 bool ref_stack_enum_next(P1(ref_stack_enum_t *prse));
182 
183 /* Clean up a stack for garbage collection. */
184 void ref_stack_cleanup(P1(ref_stack_t *pstack));
185 
186 /*
187  * Free the entire contents of a stack, including the bottom block.  The
188  * client must still free the ref_stack_t object.  Note that after calling
189  * ref_stack_release, the stack is no longer usable.
190  */
191 void ref_stack_release(P1(ref_stack_t *pstack));
192 
193 /*
194  * Release a stack and then free the stack object.
195  */
196 void ref_stack_free(P1(ref_stack_t *pstack));
197 
198 #endif /* istack_INCLUDED */
199