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