2 |
- |
1 |
/* Copyright (C) 1989, 1992, 1993, 1994, 1996, 1997, 1998, 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: estack.h,v 1.6 2002/06/16 04:47:10 lpd Exp $ */
|
|
|
18 |
/* Definitions for the execution stack */
|
|
|
19 |
|
|
|
20 |
#ifndef estack_INCLUDED
|
|
|
21 |
# define estack_INCLUDED
|
|
|
22 |
|
|
|
23 |
#include "iestack.h"
|
|
|
24 |
#include "icstate.h" /* for access to exec_stack */
|
|
|
25 |
|
|
|
26 |
/* Define access to the cached current_file pointer. */
|
|
|
27 |
#define esfile (iexec_stack.current_file)
|
|
|
28 |
#define esfile_clear_cache() estack_clear_cache(&iexec_stack)
|
|
|
29 |
#define esfile_set_cache(pref) estack_set_cache(&iexec_stack, pref)
|
|
|
30 |
#define esfile_check_cache() estack_check_cache(&iexec_stack)
|
|
|
31 |
|
|
|
32 |
/* Define the execution stack pointers for operators. */
|
|
|
33 |
#define iexec_stack (i_ctx_p->exec_stack)
|
|
|
34 |
#define e_stack (iexec_stack.stack)
|
|
|
35 |
|
|
|
36 |
#define esbot (e_stack.bot)
|
|
|
37 |
#define esp (e_stack.p)
|
|
|
38 |
#define estop (e_stack.top)
|
|
|
39 |
|
|
|
40 |
/*
|
|
|
41 |
* The execution stack holds several different kinds of objects (refs)
|
|
|
42 |
* related to executing PostScript code:
|
|
|
43 |
*
|
|
|
44 |
* - Procedures being executed are held here. They always have
|
|
|
45 |
* type = t_array, t_mixedarray, or t_shortarray, with a_executable set.
|
|
|
46 |
* More specifically, the e-stack holds the as yet unexecuted tail of the
|
|
|
47 |
* procedure.
|
|
|
48 |
*
|
|
|
49 |
* - if, ifelse, etc. push arguments to be executed here. They may be
|
|
|
50 |
* any kind of object whatever. Similarly, looping operators (forall, for,
|
|
|
51 |
* etc.) push the procedure that is to be executed for each iteration.
|
|
|
52 |
*
|
|
|
53 |
* - Control operators (filenameforall, for, repeat, loop, forall,
|
|
|
54 |
* pathforall, run, stopped, ...) use continuations as described below.
|
|
|
55 |
*
|
|
|
56 |
* Note that there are many internal operators that need to use
|
|
|
57 |
* continuations -- for example, all the 'show' operators, since they may
|
|
|
58 |
* call out to BuildChar procedures.
|
|
|
59 |
*/
|
|
|
60 |
|
|
|
61 |
/*
|
|
|
62 |
* Because the Ghostscript architecture doesn't allow recursive calls to the
|
|
|
63 |
* interpreter, any operator that needs to call out to PostScript code (for
|
|
|
64 |
* example, the 'show' operators calling a BuildChar procedure, or setscreen
|
|
|
65 |
* sampling a spot function) must use a continuation -- an internal
|
|
|
66 |
* "operator" procedure that continues the logical thread of execution after
|
|
|
67 |
* the callout. Operators needing to use continuations push the following
|
|
|
68 |
* onto the execution stack (from bottom to top):
|
|
|
69 |
*
|
|
|
70 |
* - An e-stack mark -- an executable null that indicates the bottom of
|
|
|
71 |
* the block associated with a callout. (This should not be confused
|
|
|
72 |
* with a PostScript mark, a ref of type t_mark on the operand stack.)
|
|
|
73 |
* See make_mark_estack and push_mark_estack below. The value.opproc
|
|
|
74 |
* member of the e-stack mark contains a procedure to execute in case
|
|
|
75 |
* the e-stack is stripped back beyond this point by a 'stop' or
|
|
|
76 |
* 'exit': see pop_estack in zcontrol.c for details.
|
|
|
77 |
*
|
|
|
78 |
* - Any number of refs holding information that the continuation
|
|
|
79 |
* operator needs -- i.e., the saved logical state of the thread of
|
|
|
80 |
* execution. For example, 'for' stores the procedure, the current
|
|
|
81 |
* value, the increment, and the limit here.
|
|
|
82 |
*
|
|
|
83 |
* - The continuation procedure itself -- the pseudo-operator to be
|
|
|
84 |
* called after returns from the interpreter callout. See
|
|
|
85 |
* make_op_estack and push_op_estack below.
|
|
|
86 |
*
|
|
|
87 |
* - The PostScript procedure for the interpreter to execute.
|
|
|
88 |
*
|
|
|
89 |
* The operator then returns o_push_estack, indicating to the interpreter
|
|
|
90 |
* that the operator has pushed information on the e-stack for the
|
|
|
91 |
* interpreter to process.
|
|
|
92 |
*
|
|
|
93 |
* When the interpreter finishes executing the PostScript procedure, it pops
|
|
|
94 |
* the next item off the e-stack, which is the continuation procedure. When
|
|
|
95 |
* the continuation procedure gets control, the top of the e-stack (esp)
|
|
|
96 |
* points just below the continuation procedure slot -- i.e., to the topmost
|
|
|
97 |
* saved state item. The continuation procedure normally pops all of the
|
|
|
98 |
* saved state, and the e-stack mark, and continues execution normally,
|
|
|
99 |
* eventually returning o_pop_estack to tell the interpreter that the
|
|
|
100 |
* "operator" has popped information off the e-stack. (Loop operators do
|
|
|
101 |
* something a bit more efficient than popping the information and then
|
|
|
102 |
* pushing it again: refer to the examples in zcontrol.c for details.)
|
|
|
103 |
*
|
|
|
104 |
* Continuation procedures are called just like any other operator, so they
|
|
|
105 |
* can call each other, or be called from ordinary operator procedures, as
|
|
|
106 |
* long as the e-stack is in the right state. The most complex example of
|
|
|
107 |
* this is probably the Type 1 character rendering code in zchar1.c, where
|
|
|
108 |
* continuation procedures either call each other directly or call out to
|
|
|
109 |
* the interpreter to execute optional PostScript procedures like CDevProc.
|
|
|
110 |
*/
|
|
|
111 |
|
|
|
112 |
/* Macro for marking the execution stack */
|
|
|
113 |
#define make_mark_estack(ep, es_idx, proc)\
|
|
|
114 |
make_tasv(ep, t_null, a_executable, es_idx, opproc, proc)
|
|
|
115 |
#define push_mark_estack(es_idx, proc)\
|
|
|
116 |
(++esp, make_mark_estack(esp, es_idx, proc))
|
|
|
117 |
#define r_is_estack_mark(ep)\
|
|
|
118 |
r_has_type_attrs(ep, t_null, a_executable)
|
|
|
119 |
#define estack_mark_index(ep) r_size(ep)
|
|
|
120 |
#define set_estack_mark_index(ep, es_idx) r_set_size(ep, es_idx)
|
|
|
121 |
|
|
|
122 |
/* Macro for pushing an operator on the execution stack */
|
|
|
123 |
/* to represent a continuation procedure */
|
|
|
124 |
#define make_op_estack(ep, proc)\
|
|
|
125 |
make_oper(ep, 0, proc)
|
|
|
126 |
#define push_op_estack(proc)\
|
|
|
127 |
(++esp, make_op_estack(esp, proc))
|
|
|
128 |
|
|
|
129 |
/* Macro to ensure enough room on the execution stack */
|
|
|
130 |
#define check_estack(n)\
|
|
|
131 |
if ( esp > estop - (n) )\
|
|
|
132 |
{ int es_code_ = ref_stack_extend(&e_stack, n);\
|
|
|
133 |
if ( es_code_ < 0 ) return es_code_;\
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
/* Macro to ensure enough entries on the execution stack */
|
|
|
137 |
#define check_esp(n)\
|
|
|
138 |
if ( esp < esbot + ((n) - 1) )\
|
|
|
139 |
{ e_stack.requested = (n); return_error(e_ExecStackUnderflow); }
|
|
|
140 |
|
|
|
141 |
/* Define the various kinds of execution stack marks. */
|
|
|
142 |
#define es_other 0 /* internal use */
|
|
|
143 |
#define es_show 1 /* show operators */
|
|
|
144 |
#define es_for 2 /* iteration operators */
|
|
|
145 |
#define es_stopped 3 /* stopped operator */
|
|
|
146 |
|
|
|
147 |
/*
|
|
|
148 |
* Pop a given number of elements off the execution stack,
|
|
|
149 |
* executing cleanup procedures as necessary.
|
|
|
150 |
*/
|
|
|
151 |
void pop_estack(i_ctx_t *, uint);
|
|
|
152 |
|
|
|
153 |
/*
|
|
|
154 |
* The execution stack is implemented as a linked list of blocks;
|
|
|
155 |
* operators that can push or pop an unbounded number of values, or that
|
|
|
156 |
* access the entire e-stack, must take this into account. These are:
|
|
|
157 |
* exit .stop .instopped countexecstack execstack currentfile
|
|
|
158 |
* .execn
|
|
|
159 |
* pop_estack(exit, stop, error recovery)
|
|
|
160 |
* gs_show_find(all the show operators)
|
|
|
161 |
* In addition, for e-stack entries created by control operators, we must
|
|
|
162 |
* ensure that the mark and its data are never separated. We do this
|
|
|
163 |
* by ensuring that when splitting the top block, at least N items
|
|
|
164 |
* are kept in the new top block above the bottommost retained mark,
|
|
|
165 |
* where N is the largest number of data items associated with a mark.
|
|
|
166 |
* Finally, in order to avoid specific checks for underflowing a block,
|
|
|
167 |
* we put a guard entry at the bottom of each block except the top one
|
|
|
168 |
* that contains a procedure that returns an internal "exec stack block
|
|
|
169 |
* underflow" error.
|
|
|
170 |
*/
|
|
|
171 |
|
|
|
172 |
#endif /* estack_INCLUDED */
|