xref: /plan9/sys/src/cmd/gs/src/interp.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 2000, 2001 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: interp.c,v 1.20 2004/09/03 20:23:10 ray Exp $ */
18 /* Ghostscript language interpreter */
19 #include "memory_.h"
20 #include "string_.h"
21 #include "ghost.h"
22 #include "gsstruct.h"		/* for iastruct.h */
23 #include "stream.h"
24 #include "ierrors.h"
25 #include "estack.h"
26 #include "ialloc.h"
27 #include "iastruct.h"
28 #include "icontext.h"
29 #include "icremap.h"
30 #include "idebug.h"
31 #include "igstate.h"		/* for handling e_RemapColor */
32 #include "inamedef.h"
33 #include "iname.h"		/* for the_name_table */
34 #include "interp.h"
35 #include "ipacked.h"
36 #include "ostack.h"		/* must precede iscan.h */
37 #include "strimpl.h"		/* for sfilter.h */
38 #include "sfilter.h"		/* for iscan.h */
39 #include "iscan.h"
40 #include "iddict.h"
41 #include "isave.h"
42 #include "istack.h"
43 #include "itoken.h"
44 #include "iutil.h"		/* for array_get */
45 #include "ivmspace.h"
46 #include "dstack.h"
47 #include "files.h"		/* for file_check_read */
48 #include "oper.h"
49 #include "store.h"
50 #include "gpcheck.h"
51 
52 /*
53  * We may or may not optimize the handling of the special fast operators
54  * in packed arrays.  If we do this, they run much faster when packed, but
55  * slightly slower when not packed.
56  */
57 #define PACKED_SPECIAL_OPS 1
58 
59 /*
60  * Pseudo-operators (procedures of type t_oparray) record
61  * the operand and dictionary stack pointers, and restore them if an error
62  * occurs during the execution of the procedure and if the procedure hasn't
63  * (net) decreased the depth of the stack.  While this obviously doesn't
64  * do all the work of restoring the state if a pseudo-operator gets an
65  * error, it's a big help.  The only downside is that pseudo-operators run
66  * a little slower.
67  */
68 
69 /* GC descriptors for stacks */
70 extern_st(st_ref_stack);
71 public_st_dict_stack();
72 public_st_exec_stack();
73 public_st_op_stack();
74 
75 /*
76  * The procedure to call if an operator requests rescheduling.
77  * This causes an error unless the context machinery has been installed.
78  */
79 private int
no_reschedule(i_ctx_t ** pi_ctx_p)80 no_reschedule(i_ctx_t **pi_ctx_p)
81 {
82     return_error(e_invalidcontext);
83 }
84 int (*gs_interp_reschedule_proc)(i_ctx_t **) = no_reschedule;
85 
86 /*
87  * The procedure to call for time-slicing.
88  * This is a no-op unless the context machinery has been installed.
89  */
90 int (*gs_interp_time_slice_proc)(i_ctx_t **) = 0;
91 
92 /*
93  * The number of interpreter "ticks" between calls on the time_slice_proc.
94  * Currently, the clock ticks before each operator, and at each
95  * procedure return.
96  */
97 int gs_interp_time_slice_ticks = 0x7fff;
98 
99 /*
100  * Apply an operator.  When debugging, we route all operator calls
101  * through a procedure.
102  */
103 #ifdef DEBUG
104 private int
call_operator(op_proc_t op_proc,i_ctx_t * i_ctx_p)105 call_operator(op_proc_t op_proc, i_ctx_t *i_ctx_p)
106 {
107     int code = op_proc(i_ctx_p);
108 
109     return code;
110 }
111 #else
112 #  define call_operator(proc, p) ((*(proc))(p))
113 #endif
114 
115 /* Define debugging statistics. */
116 #ifdef DEBUG
117 struct stats_interp_s {
118     long top;
119     long lit, lit_array, exec_array, exec_operator, exec_name;
120     long x_add, x_def, x_dup, x_exch, x_if, x_ifelse,
121 	x_index, x_pop, x_roll, x_sub;
122     long find_name, name_lit, name_proc, name_oparray, name_operator;
123     long p_full, p_exec_operator, p_exec_oparray, p_exec_non_x_operator,
124 	p_integer, p_lit_name, p_exec_name;
125     long p_find_name, p_name_lit, p_name_proc;
126 } stats_interp;
127 # define INCR(v) (++(stats_interp.v))
128 #else
129 # define INCR(v) DO_NOTHING
130 #endif
131 
132 /* Forward references */
133 private int estack_underflow(i_ctx_t *);
134 private int interp(i_ctx_t **, const ref *, ref *);
135 private int interp_exit(i_ctx_t *);
136 private void set_gc_signal(i_ctx_t *, int *, int);
137 private int copy_stack(i_ctx_t *, const ref_stack_t *, ref *);
138 private int oparray_pop(i_ctx_t *);
139 private int oparray_cleanup(i_ctx_t *);
140 private int zsetstackprotect(i_ctx_t *);
141 private int zcurrentstackprotect(i_ctx_t *);
142 
143 /* Stack sizes */
144 
145 /* The maximum stack sizes may all be set in the makefile. */
146 
147 /*
148  * Define the initial maximum size of the operand stack (MaxOpStack
149  * user parameter).
150  */
151 #ifndef MAX_OSTACK
152 #  define MAX_OSTACK 800
153 #endif
154 /*
155  * The minimum block size for extending the operand stack is the larger of:
156  *      - the maximum number of parameters to an operator
157  *      (currently setcolorscreen, with 12 parameters);
158  *      - the maximum number of values pushed by an operator
159  *      (currently setcolortransfer, which calls zcolor_remap_one 4 times
160  *      and therefore pushes 16 values).
161  */
162 #define MIN_BLOCK_OSTACK 16
163 const int gs_interp_max_op_num_args = MIN_BLOCK_OSTACK;		/* for iinit.c */
164 
165 /*
166  * Define the initial maximum size of the execution stack (MaxExecStack
167  * user parameter).
168  */
169 #ifndef MAX_ESTACK
170 #  define MAX_ESTACK 5000
171 #endif
172 /*
173  * The minimum block size for extending the execution stack is the largest
174  * size of a contiguous block surrounding an e-stack mark.  (At least,
175  * that's what the minimum value would be if we supported multi-block
176  * estacks, which we currently don't.)  Currently, the largest such block is
177  * the one created for text processing, which is 8 (snumpush) slots.
178  */
179 #define MIN_BLOCK_ESTACK 8
180 /*
181  * If we get an e-stack overflow, we need to cut it back far enough to
182  * have some headroom for executing the error procedure.
183  */
184 #define ES_HEADROOM 20
185 
186 /*
187  * Define the initial maximum size of the dictionary stack (MaxDictStack
188  * user parameter).  Again, this is also currently the block size for
189  * extending the d-stack.
190  */
191 #ifndef MAX_DSTACK
192 #  define MAX_DSTACK 20
193 #endif
194 /*
195  * The minimum block size for extending the dictionary stack is the number
196  * of permanent entries on the dictionary stack, currently 3.
197  */
198 #define MIN_BLOCK_DSTACK 3
199 
200 /* See estack.h for a description of the execution stack. */
201 
202 /* The logic for managing icount and iref below assumes that */
203 /* there are no control operators which pop and then push */
204 /* information on the execution stack. */
205 
206 /* Stacks */
207 extern_st(st_ref_stack);
208 #define OS_GUARD_UNDER 10
209 #define OS_GUARD_OVER 10
210 #define OS_REFS_SIZE(body_size)\
211   (stack_block_refs + OS_GUARD_UNDER + (body_size) + OS_GUARD_OVER)
212 
213 #define ES_GUARD_UNDER 1
214 #define ES_GUARD_OVER 10
215 #define ES_REFS_SIZE(body_size)\
216   (stack_block_refs + ES_GUARD_UNDER + (body_size) + ES_GUARD_OVER)
217 
218 #define DS_REFS_SIZE(body_size)\
219   (stack_block_refs + (body_size))
220 
221 /* Extended types.  The interpreter may replace the type of operators */
222 /* in procedures with these, to speed up the interpretation loop. */
223 /****** NOTE: If you add or change entries in this list, */
224 /****** you must change the three dispatches in the interpreter loop. */
225 /* The operator procedures are declared in opextern.h. */
226 #define tx_op t_next_index
227 typedef enum {
228     tx_op_add = tx_op,
229     tx_op_def,
230     tx_op_dup,
231     tx_op_exch,
232     tx_op_if,
233     tx_op_ifelse,
234     tx_op_index,
235     tx_op_pop,
236     tx_op_roll,
237     tx_op_sub,
238     tx_next_op
239 } special_op_types;
240 
241 #define num_special_ops ((int)tx_next_op - tx_op)
242 const int gs_interp_num_special_ops = num_special_ops;	/* for iinit.c */
243 const int tx_next_index = tx_next_op;
244 
245 /*
246  * Define the interpreter operators, which include the extended-type
247  * operators defined in the list above.  NOTE: if the size of this table
248  * ever exceeds 15 real entries, it will have to be split.
249  */
250 const op_def interp_op_defs[] = {
251     /*
252      * The very first entry, which corresponds to operator index 0,
253      * must not contain an actual operator.
254      */
255     op_def_begin_dict("systemdict"),
256     /*
257      * The next entries must be the extended-type operators, in the
258      * correct order.
259      */
260     {"2add", zadd},
261     {"2def", zdef},
262     {"1dup", zdup},
263     {"2exch", zexch},
264     {"2if", zif},
265     {"3ifelse", zifelse},
266     {"1index", zindex},
267     {"1pop", zpop},
268     {"2roll", zroll},
269     {"2sub", zsub},
270     /*
271      * The remaining entries are internal operators.
272      */
273     {"0.currentstackprotect", zcurrentstackprotect},
274     {"1.setstackprotect", zsetstackprotect},
275     {"0%interp_exit", interp_exit},
276     {"0%oparray_pop", oparray_pop},
277     op_def_end(0)
278 };
279 
280 #define make_null_proc(pref)\
281   make_empty_const_array(pref, a_executable + a_readonly)
282 
283 /* Initialize the interpreter. */
284 int
gs_interp_init(i_ctx_t ** pi_ctx_p,const ref * psystem_dict,gs_dual_memory_t * dmem)285 gs_interp_init(i_ctx_t **pi_ctx_p, const ref *psystem_dict,
286 	       gs_dual_memory_t *dmem)
287 {
288     /* Create and initialize a context state. */
289     gs_context_state_t *pcst = 0;
290     int code = context_state_alloc(&pcst, psystem_dict, dmem);
291 
292     if (code >= 0)
293 	code = context_state_load(pcst);
294     if (code < 0)
295 	lprintf1("Fatal error %d in gs_interp_init!", code);
296     *pi_ctx_p = pcst;
297     return code;
298 }
299 /*
300  * Create initial stacks for the interpreter.
301  * We export this for creating new contexts.
302  */
303 int
gs_interp_alloc_stacks(gs_ref_memory_t * mem,gs_context_state_t * pcst)304 gs_interp_alloc_stacks(gs_ref_memory_t *mem, gs_context_state_t * pcst)
305 {
306     gs_ref_memory_t *smem =
307 	(gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem);
308     ref stk;
309 
310 #define REFS_SIZE_OSTACK OS_REFS_SIZE(MAX_OSTACK)
311 #define REFS_SIZE_ESTACK ES_REFS_SIZE(MAX_ESTACK)
312 #define REFS_SIZE_DSTACK DS_REFS_SIZE(MAX_DSTACK)
313     gs_alloc_ref_array(smem, &stk, 0,
314 		       REFS_SIZE_OSTACK + REFS_SIZE_ESTACK +
315 		       REFS_SIZE_DSTACK, "gs_interp_alloc_stacks");
316 
317     {
318 	ref_stack_t *pos = &pcst->op_stack.stack;
319 
320 	r_set_size(&stk, REFS_SIZE_OSTACK);
321 	ref_stack_init(pos, &stk, OS_GUARD_UNDER, OS_GUARD_OVER, NULL,
322 		       smem, NULL);
323 	ref_stack_set_error_codes(pos, e_stackunderflow, e_stackoverflow);
324 	ref_stack_set_max_count(pos, MAX_OSTACK);
325 	stk.value.refs += REFS_SIZE_OSTACK;
326     }
327 
328     {
329 	ref_stack_t *pes = &pcst->exec_stack.stack;
330 	ref euop;
331 
332 	r_set_size(&stk, REFS_SIZE_ESTACK);
333 	make_oper(&euop, 0, estack_underflow);
334 	ref_stack_init(pes, &stk, ES_GUARD_UNDER, ES_GUARD_OVER, &euop,
335 		       smem, NULL);
336 	ref_stack_set_error_codes(pes, e_ExecStackUnderflow,
337 				  e_execstackoverflow);
338 	/**************** E-STACK EXPANSION IS NYI. ****************/
339 	ref_stack_allow_expansion(pes, false);
340 	ref_stack_set_max_count(pes, MAX_ESTACK);
341 	stk.value.refs += REFS_SIZE_ESTACK;
342     }
343 
344     {
345 	ref_stack_t *pds = &pcst->dict_stack.stack;
346 
347 	r_set_size(&stk, REFS_SIZE_DSTACK);
348 	ref_stack_init(pds, &stk, 0, 0, NULL, smem, NULL);
349 	ref_stack_set_error_codes(pds, e_dictstackunderflow,
350 				  e_dictstackoverflow);
351 	ref_stack_set_max_count(pds, MAX_DSTACK);
352     }
353 
354 #undef REFS_SIZE_OSTACK
355 #undef REFS_SIZE_ESTACK
356 #undef REFS_SIZE_DSTACK
357     return 0;
358 }
359 /*
360  * Free the stacks when destroying a context.  This is the inverse of
361  * create_stacks.
362  */
363 void
gs_interp_free_stacks(gs_ref_memory_t * smem,gs_context_state_t * pcst)364 gs_interp_free_stacks(gs_ref_memory_t * smem, gs_context_state_t * pcst)
365 {
366     /* Free the stacks in inverse order of allocation. */
367     ref_stack_release(&pcst->dict_stack.stack);
368     ref_stack_release(&pcst->exec_stack.stack);
369     ref_stack_release(&pcst->op_stack.stack);
370 }
371 void
gs_interp_reset(i_ctx_t * i_ctx_p)372 gs_interp_reset(i_ctx_t *i_ctx_p)
373 {   /* Reset the stacks. */
374     ref_stack_clear(&o_stack);
375     ref_stack_clear(&e_stack);
376     esp++;
377     make_oper(esp, 0, interp_exit);
378     ref_stack_pop_to(&d_stack, min_dstack_size);
379     dict_set_top();
380 }
381 /* Report an e-stack block underflow.  The bottom guard slots of */
382 /* e-stack blocks contain a pointer to this procedure. */
383 private int
estack_underflow(i_ctx_t * i_ctx_p)384 estack_underflow(i_ctx_t *i_ctx_p)
385 {
386     return e_ExecStackUnderflow;
387 }
388 
389 /*
390  * Create an operator during initialization.
391  * If operator is hard-coded into the interpreter,
392  * assign it a special type and index.
393  */
394 void
gs_interp_make_oper(ref * opref,op_proc_t proc,int idx)395 gs_interp_make_oper(ref * opref, op_proc_t proc, int idx)
396 {
397     int i;
398 
399     for (i = num_special_ops; i > 0 && proc != interp_op_defs[i].proc; --i)
400 	DO_NOTHING;
401     if (i > 0)
402 	make_tasv(opref, tx_op + (i - 1), a_executable, i, opproc, proc);
403     else
404 	make_tasv(opref, t_operator, a_executable, idx, opproc, proc);
405 }
406 
407 /*
408  * Call the garbage collector, updating the context pointer properly.
409  */
410 int
interp_reclaim(i_ctx_t ** pi_ctx_p,int space)411 interp_reclaim(i_ctx_t **pi_ctx_p, int space)
412 {
413     i_ctx_t *i_ctx_p = *pi_ctx_p;
414     gs_gc_root_t ctx_root;
415     int code;
416 
417     gs_register_struct_root(imemory_system, &ctx_root,
418 			    (void **)pi_ctx_p, "interp_reclaim(pi_ctx_p)");
419     code = (*idmemory->reclaim)(idmemory, space);
420     i_ctx_p = *pi_ctx_p;	/* may have moved */
421     gs_unregister_root(imemory_system, &ctx_root, "interp_reclaim(pi_ctx_p)");
422     return code;
423 }
424 
425 /*
426  * Invoke the interpreter.  If execution completes normally, return 0.
427  * If an error occurs, the action depends on user_errors as follows:
428  *    user_errors < 0: always return an error code.
429  *    user_errors >= 0: let the PostScript machinery handle all errors.
430  *      (This will eventually result in a fatal error if no 'stopped'
431  *      is active.)
432  * In case of a quit or a fatal error, also store the exit code.
433  * Set *perror_object to null or the error object.
434  */
435 private int gs_call_interp(i_ctx_t **, ref *, int, int *, ref *);
436 int
gs_interpret(i_ctx_t ** pi_ctx_p,ref * pref,int user_errors,int * pexit_code,ref * perror_object)437 gs_interpret(i_ctx_t **pi_ctx_p, ref * pref, int user_errors, int *pexit_code,
438 	     ref * perror_object)
439 {
440     i_ctx_t *i_ctx_p = *pi_ctx_p;
441     gs_gc_root_t error_root;
442     int code;
443 
444     gs_register_ref_root(imemory_system, &error_root,
445 			 (void **)&perror_object, "gs_interpret");
446     code = gs_call_interp(pi_ctx_p, pref, user_errors, pexit_code,
447 			  perror_object);
448     i_ctx_p = *pi_ctx_p;
449     gs_unregister_root(imemory_system, &error_root, "gs_interpret");
450     /* Avoid a dangling reference to a stack-allocated GC signal. */
451     set_gc_signal(i_ctx_p, NULL, 0);
452     return code;
453 }
454 private int
gs_call_interp(i_ctx_t ** pi_ctx_p,ref * pref,int user_errors,int * pexit_code,ref * perror_object)455 gs_call_interp(i_ctx_t **pi_ctx_p, ref * pref, int user_errors,
456 	       int *pexit_code, ref * perror_object)
457 {
458     ref *epref = pref;
459     ref doref;
460     ref *perrordict;
461     ref error_name;
462     int code, ccode;
463     ref saref;
464     int gc_signal = 0;
465     i_ctx_t *i_ctx_p = *pi_ctx_p;
466 
467     *pexit_code = 0;
468     ialloc_reset_requested(idmemory);
469 again:
470     /* Avoid a dangling error object that might get traced by a future GC. */
471     make_null(perror_object);
472     o_stack.requested = e_stack.requested = d_stack.requested = 0;
473     while (gc_signal) {		/* Some routine below triggered a GC. */
474 	gs_gc_root_t epref_root;
475 
476 	gc_signal = 0;
477 	/* Make sure that doref will get relocated properly if */
478 	/* a garbage collection happens with epref == &doref. */
479 	gs_register_ref_root(imemory_system, &epref_root,
480 			     (void **)&epref, "gs_call_interp(epref)");
481 	code = interp_reclaim(pi_ctx_p, -1);
482 	i_ctx_p = *pi_ctx_p;
483 	gs_unregister_root(imemory_system, &epref_root,
484 			   "gs_call_interp(epref)");
485 	if (code < 0)
486 	    return code;
487     }
488     code = interp(pi_ctx_p, epref, perror_object);
489     i_ctx_p = *pi_ctx_p;
490     /* Prevent a dangling reference to the GC signal in ticks_left */
491     /* in the frame of interp, but be prepared to do a GC if */
492     /* an allocation in this routine asks for it. */
493     set_gc_signal(i_ctx_p, &gc_signal, 1);
494     if (esp < esbot)		/* popped guard entry */
495 	esp = esbot;
496     switch (code) {
497 	case e_Fatal:
498 	    *pexit_code = 255;
499 	    return code;
500 	case e_Quit:
501 	    *perror_object = osp[-1];
502 	    *pexit_code = code = osp->value.intval;
503 	    osp -= 2;
504 	    return
505 		(code == 0 ? e_Quit :
506 		 code < 0 && code > -100 ? code : e_Fatal);
507 	case e_InterpreterExit:
508 	    return 0;
509 	case e_ExecStackUnderflow:
510 /****** WRONG -- must keep mark blocks intact ******/
511 	    ref_stack_pop_block(&e_stack);
512 	    doref = *perror_object;
513 	    epref = &doref;
514 	    goto again;
515 	case e_VMreclaim:
516 	    /* Do the GC and continue. */
517 	    code = interp_reclaim(pi_ctx_p,
518 				  (osp->value.intval == 2 ?
519 				   avm_global : avm_local));
520 	    i_ctx_p = *pi_ctx_p;
521 	    /****** What if code < 0? ******/
522 	    make_oper(&doref, 0, zpop);
523 	    epref = &doref;
524 	    goto again;
525 	case e_NeedInput:
526 	case e_NeedStdin:
527 	case e_NeedStdout:
528 	case e_NeedStderr:
529 	    return code;
530     }
531     /* Adjust osp in case of operand stack underflow */
532     if (osp < osbot - 1)
533 	osp = osbot - 1;
534     /* We have to handle stack over/underflow specially, because */
535     /* we might be able to recover by adding or removing a block. */
536     switch (code) {
537 	case e_dictstackoverflow:
538 	    if (ref_stack_extend(&d_stack, d_stack.requested) >= 0) {
539 		dict_set_top();
540 		doref = *perror_object;
541 		epref = &doref;
542 		goto again;
543 	    }
544 	    if (osp >= ostop) {
545 		if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
546 		    return ccode;
547 	    }
548 	    ccode = copy_stack(i_ctx_p, &d_stack, &saref);
549 	    if (ccode < 0)
550 		return ccode;
551 	    ref_stack_pop_to(&d_stack, min_dstack_size);
552 	    dict_set_top();
553 	    *++osp = saref;
554 	    break;
555 	case e_dictstackunderflow:
556 	    if (ref_stack_pop_block(&d_stack) >= 0) {
557 		dict_set_top();
558 		doref = *perror_object;
559 		epref = &doref;
560 		goto again;
561 	    }
562 	    break;
563 	case e_execstackoverflow:
564 	    /* We don't have to handle this specially: */
565 	    /* The only places that could generate it */
566 	    /* use check_estack, which does a ref_stack_extend, */
567 	    /* so if we get this error, it's a real one. */
568 	    if (osp >= ostop) {
569 		if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
570 		    return ccode;
571 	    }
572 	    ccode = copy_stack(i_ctx_p, &e_stack, &saref);
573 	    if (ccode < 0)
574 		return ccode;
575 	    {
576 		uint count = ref_stack_count(&e_stack);
577 		uint limit = ref_stack_max_count(&e_stack) - ES_HEADROOM;
578 
579 		if (count > limit) {
580 		    /*
581 		     * If there is an e-stack mark within MIN_BLOCK_ESTACK of
582 		     * the new top, cut the stack back to remove the mark.
583 		     */
584 		    int skip = count - limit;
585 		    int i;
586 
587 		    for (i = skip; i < skip + MIN_BLOCK_ESTACK; ++i) {
588 			const ref *ep = ref_stack_index(&e_stack, i);
589 
590 			if (r_has_type_attrs(ep, t_null, a_executable)) {
591 			    skip = i + 1;
592 			    break;
593 			}
594 		    }
595 		    pop_estack(i_ctx_p, skip);
596 		}
597 	    }
598 	    *++osp = saref;
599 	    break;
600 	case e_stackoverflow:
601 	    if (ref_stack_extend(&o_stack, o_stack.requested) >= 0) {	/* We can't just re-execute the object, because */
602 		/* it might be a procedure being pushed as a */
603 		/* literal.  We check for this case specially. */
604 		doref = *perror_object;
605 		if (r_is_proc(&doref)) {
606 		    *++osp = doref;
607 		    make_null_proc(&doref);
608 		}
609 		epref = &doref;
610 		goto again;
611 	    }
612 	    ccode = copy_stack(i_ctx_p, &o_stack, &saref);
613 	    if (ccode < 0)
614 		return ccode;
615 	    ref_stack_clear(&o_stack);
616 	    *++osp = saref;
617 	    break;
618 	case e_stackunderflow:
619 	    if (ref_stack_pop_block(&o_stack) >= 0) {
620 		doref = *perror_object;
621 		epref = &doref;
622 		goto again;
623 	    }
624 	    break;
625     }
626     if (user_errors < 0)
627 	return code;
628     if (gs_errorname(i_ctx_p, code, &error_name) < 0)
629 	return code;		/* out-of-range error code! */
630     if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
631 	dict_find(perrordict, &error_name, &epref) <= 0
632 	)
633 	return code;		/* error name not in errordict??? */
634     doref = *epref;
635     epref = &doref;
636     /* Push the error object on the operand stack if appropriate. */
637     if (!ERROR_IS_INTERRUPT(code))
638 	*++osp = *perror_object;
639     goto again;
640 }
641 private int
interp_exit(i_ctx_t * i_ctx_p)642 interp_exit(i_ctx_t *i_ctx_p)
643 {
644     return e_InterpreterExit;
645 }
646 
647 /* Set the GC signal for all VMs. */
648 private void
set_gc_signal(i_ctx_t * i_ctx_p,int * psignal,int value)649 set_gc_signal(i_ctx_t *i_ctx_p, int *psignal, int value)
650 {
651     gs_memory_gc_status_t stat;
652     int i;
653 
654     for (i = 0; i < countof(idmemory->spaces_indexed); i++) {
655 	gs_ref_memory_t *mem = idmemory->spaces_indexed[i];
656 	gs_ref_memory_t *mem_stable;
657 
658 	if (mem == 0)
659 	    continue;
660 	for (;; mem = mem_stable) {
661 	    mem_stable = (gs_ref_memory_t *)
662 		gs_memory_stable((gs_memory_t *)mem);
663 	    gs_memory_gc_status(mem, &stat);
664 	    stat.psignal = psignal;
665 	    stat.signal_value = value;
666 	    gs_memory_set_gc_status(mem, &stat);
667 	    if (mem_stable == mem)
668 		break;
669 	}
670     }
671 }
672 
673 /* Copy the contents of an overflowed stack into a (local) array. */
674 private int
copy_stack(i_ctx_t * i_ctx_p,const ref_stack_t * pstack,ref * arr)675 copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, ref * arr)
676 {
677     uint size = ref_stack_count(pstack);
678     uint save_space = ialloc_space(idmemory);
679     int code;
680 
681     ialloc_set_space(idmemory, avm_local);
682     code = ialloc_ref_array(arr, a_all, size, "copy_stack");
683     if (code >= 0)
684 	code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory,
685 			       "copy_stack");
686     ialloc_set_space(idmemory, save_space);
687     return code;
688 }
689 
690 /* Get the name corresponding to an error number. */
691 int
gs_errorname(i_ctx_t * i_ctx_p,int code,ref * perror_name)692 gs_errorname(i_ctx_t *i_ctx_p, int code, ref * perror_name)
693 {
694     ref *perrordict, *pErrorNames;
695 
696     if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
697 	dict_find_string(systemdict, "ErrorNames", &pErrorNames) <= 0
698 	)
699 	return_error(e_undefined);	/* errordict or ErrorNames not found?! */
700     return array_get(imemory, pErrorNames, (long)(-code - 1), perror_name);
701 }
702 
703 /* Store an error string in $error.errorinfo. */
704 /* This routine is here because of the proximity to the error handler. */
705 int
gs_errorinfo_put_string(i_ctx_t * i_ctx_p,const char * str)706 gs_errorinfo_put_string(i_ctx_t *i_ctx_p, const char *str)
707 {
708     ref rstr;
709     ref *pderror;
710     int code = string_to_ref(str, &rstr, iimemory, "gs_errorinfo_put_string");
711 
712     if (code < 0)
713 	return code;
714     if (dict_find_string(systemdict, "$error", &pderror) <= 0 ||
715 	!r_has_type(pderror, t_dictionary) ||
716 	idict_put_string(pderror, "errorinfo", &rstr) < 0
717 	)
718 	return_error(e_Fatal);
719     return 0;
720 }
721 
722 /* Main interpreter. */
723 /* If execution terminates normally, return e_InterpreterExit. */
724 /* If an error occurs, leave the current object in *perror_object */
725 /* and return a (negative) error code. */
726 private int
interp(i_ctx_t ** pi_ctx_p,const ref * pref,ref * perror_object)727 interp(i_ctx_t **pi_ctx_p /* context for execution, updated if resched */,
728        const ref * pref /* object to interpret */,
729        ref * perror_object)
730 {
731     i_ctx_t *i_ctx_p = *pi_ctx_p;
732     /*
733      * Note that iref may actually be either a ref * or a ref_packed *.
734      * Certain DEC compilers assume that a ref * is ref-aligned even if it
735      * is cast to a short *, and generate code on this assumption, leading
736      * to "unaligned access" errors.  For this reason, we declare
737      * iref_packed, and use a macro to cast it to the more aligned type
738      * where necessary (which is almost everywhere it is used).  This may
739      * lead to compiler warnings about "cast increases alignment
740      * requirements", but this is less harmful than expensive traps at run
741      * time.
742      */
743     register const ref_packed *iref_packed = (const ref_packed *)pref;
744     /*
745      * To make matters worse, some versions of gcc/egcs have a bug that
746      * leads them to assume that if iref_packed is EVER cast to a ref *,
747      * it is ALWAYS ref-aligned.  We detect this in stdpre.h and provide
748      * the following workaround:
749      */
750 #ifdef ALIGNMENT_ALIASING_BUG
751     const ref *iref_temp;
752 #  define IREF (iref_temp = (const ref *)iref_packed, iref_temp)
753 #else
754 #  define IREF ((const ref *)iref_packed)
755 #endif
756 #define SET_IREF(rp) (iref_packed = (const ref_packed *)(rp))
757     register int icount = 0;	/* # of consecutive tokens at iref */
758     register os_ptr iosp = osp;	/* private copy of osp */
759     register es_ptr iesp = esp;	/* private copy of esp */
760     int code;
761     ref token;			/* token read from file or string, */
762 				/* must be declared in this scope */
763     register const ref *pvalue;
764     os_ptr whichp;
765 
766     /*
767      * We have to make the error information into a struct;
768      * otherwise, the Watcom compiler will assign it to registers
769      * strictly on the basis of textual frequency.
770      * We also have to use ref_assign_inline everywhere, and
771      * avoid direct assignments of refs, so that esi and edi
772      * will remain available on Intel processors.
773      */
774     struct interp_error_s {
775 	int code;
776 	int line;
777 	const ref *obj;
778 	ref full;
779     } ierror;
780 
781     /*
782      * Get a pointer to the name table so that we can use the
783      * inline version of name_index_ref.
784      */
785     const name_table *const int_nt = imemory->gs_lib_ctx->gs_name_table;
786 
787 #define set_error(ecode)\
788   { ierror.code = ecode; ierror.line = __LINE__; }
789 #define return_with_error(ecode, objp)\
790   { set_error(ecode); ierror.obj = objp; goto rwe; }
791 #define return_with_error_iref(ecode)\
792   { set_error(ecode); goto rwei; }
793 #define return_with_code_iref()\
794   { ierror.line = __LINE__; goto rweci; }
795 #define return_with_error_code_op(nargs)\
796   return_with_code_iref()
797 #define return_with_stackoverflow(objp)\
798   { o_stack.requested = 1; return_with_error(e_stackoverflow, objp); }
799 #define return_with_stackoverflow_iref()\
800   { o_stack.requested = 1; return_with_error_iref(e_stackoverflow); }
801     int ticks_left = gs_interp_time_slice_ticks;
802 
803     /*
804      * If we exceed the VMThreshold, set ticks_left to -100
805      * to alert the interpreter that we need to garbage collect.
806      */
807     set_gc_signal(i_ctx_p, &ticks_left, -100);
808 
809     esfile_clear_cache();
810     /*
811      * From here on, if icount > 0, iref and icount correspond
812      * to the top entry on the execution stack: icount is the count
813      * of sequential entries remaining AFTER the current one.
814      */
815 #define IREF_NEXT(ip)\
816   ((const ref_packed *)((const ref *)(ip) + 1))
817 #define IREF_NEXT_EITHER(ip)\
818   ( r_is_packed(ip) ? (ip) + 1 : IREF_NEXT(ip) )
819 #define store_state(ep)\
820   ( icount > 0 ? (ep->value.const_refs = IREF + 1, r_set_size(ep, icount)) : 0 )
821 #define store_state_short(ep)\
822   ( icount > 0 ? (ep->value.packed = iref_packed + 1, r_set_size(ep, icount)) : 0 )
823 #define store_state_either(ep)\
824   ( icount > 0 ? (ep->value.packed = IREF_NEXT_EITHER(iref_packed), r_set_size(ep, icount)) : 0 )
825 #define next()\
826   if ( --icount > 0 ) { iref_packed = IREF_NEXT(iref_packed); goto top; } else goto out
827 #define next_short()\
828   if ( --icount <= 0 ) { if ( icount < 0 ) goto up; iesp--; }\
829   ++iref_packed; goto top
830 #define next_either()\
831   if ( --icount <= 0 ) { if ( icount < 0 ) goto up; iesp--; }\
832   iref_packed = IREF_NEXT_EITHER(iref_packed); goto top
833 
834 #if !PACKED_SPECIAL_OPS
835 #  undef next_either
836 #  define next_either() next()
837 #  undef store_state_either
838 #  define store_state_either(ep) store_state(ep)
839 #endif
840 
841     /* We want to recognize executable arrays here, */
842     /* so we push the argument on the estack and enter */
843     /* the loop at the bottom. */
844     if (iesp >= estop)
845 	return_with_error(e_execstackoverflow, pref);
846     ++iesp;
847     ref_assign_inline(iesp, pref);
848     goto bot;
849   top:
850 	/*
851 	 * This is the top of the interpreter loop.
852 	 * iref points to the ref being interpreted.
853 	 * Note that this might be an element of a packed array,
854 	 * not a real ref: we carefully arranged the first 16 bits of
855 	 * a ref and of a packed array element so they could be distinguished
856 	 * from each other.  (See ghost.h and packed.h for more detail.)
857 	 */
858     INCR(top);
859 #ifdef DEBUG
860     /* Do a little validation on the top o-stack entry. */
861     if (iosp >= osbot &&
862 	(r_type(iosp) == t__invalid || r_type(iosp) >= tx_next_op)
863 	) {
864 	lprintf("Invalid value on o-stack!\n");
865 	return_with_error_iref(e_Fatal);
866     }
867     if (gs_debug['I'] ||
868 	(gs_debug['i'] &&
869 	 (r_is_packed(iref_packed) ?
870 	  r_packed_is_name(iref_packed) :
871 	  r_has_type(IREF, t_name)))
872 	) {
873 	os_ptr save_osp = osp;	/* avoid side-effects */
874 	es_ptr save_esp = esp;
875 
876 	osp = iosp;
877 	esp = iesp;
878 	dlprintf5("d%u,e%u<%u>0x%lx(%d): ",
879 		  ref_stack_count(&d_stack), ref_stack_count(&e_stack),
880 		  ref_stack_count(&o_stack), (ulong)IREF, icount);
881 	debug_print_ref(imemory, IREF);
882 	if (iosp >= osbot) {
883 	    dputs(" // ");
884 	    debug_print_ref(imemory, iosp);
885 	}
886 	dputc('\n');
887 	osp = save_osp;
888 	esp = save_esp;
889 	fflush(dstderr);
890     }
891 #endif
892 /* Objects that have attributes (arrays, dictionaries, files, and strings) */
893 /* use lit and exec; other objects use plain and plain_exec. */
894 #define lit(t) type_xe_value(t, a_execute)
895 #define exec(t) type_xe_value(t, a_execute + a_executable)
896 #define nox(t) type_xe_value(t, 0)
897 #define nox_exec(t) type_xe_value(t, a_executable)
898 #define plain(t) type_xe_value(t, 0)
899 #define plain_exec(t) type_xe_value(t, a_executable)
900     /*
901      * We have to populate enough cases of the switch statement to force
902      * some compilers to use a dispatch rather than a testing loop.
903      * What a nuisance!
904      */
905     switch (r_type_xe(iref_packed)) {
906 	    /* Access errors. */
907 #define cases_invalid()\
908   case plain(t__invalid): case plain_exec(t__invalid)
909 	  cases_invalid():
910 	    return_with_error_iref(e_Fatal);
911 #define cases_nox()\
912   case nox_exec(t_array): case nox_exec(t_dictionary):\
913   case nox_exec(t_file): case nox_exec(t_string):\
914   case nox_exec(t_mixedarray): case nox_exec(t_shortarray)
915 	  cases_nox():
916 	    return_with_error_iref(e_invalidaccess);
917 	    /*
918 	     * Literal objects.  We have to enumerate all the types.
919 	     * In fact, we have to include some extra plain_exec entries
920 	     * just to populate the switch.  We break them up into groups
921 	     * to avoid overflowing some preprocessors.
922 	     */
923 #define cases_lit_1()\
924   case lit(t_array): case nox(t_array):\
925   case plain(t_boolean): case plain_exec(t_boolean):\
926   case lit(t_dictionary): case nox(t_dictionary)
927 #define cases_lit_2()\
928   case lit(t_file): case nox(t_file):\
929   case plain(t_fontID): case plain_exec(t_fontID):\
930   case plain(t_integer): case plain_exec(t_integer):\
931   case plain(t_mark): case plain_exec(t_mark)
932 #define cases_lit_3()\
933   case plain(t_name):\
934   case plain(t_null):\
935   case plain(t_oparray):\
936   case plain(t_operator)
937 #define cases_lit_4()\
938   case plain(t_real): case plain_exec(t_real):\
939   case plain(t_save): case plain_exec(t_save):\
940   case lit(t_string): case nox(t_string)
941 #define cases_lit_5()\
942   case lit(t_mixedarray): case nox(t_mixedarray):\
943   case lit(t_shortarray): case nox(t_shortarray):\
944   case plain(t_device): case plain_exec(t_device):\
945   case plain(t_struct): case plain_exec(t_struct):\
946   case plain(t_astruct): case plain_exec(t_astruct)
947 	    /* Executable arrays are treated as literals in direct execution. */
948 #define cases_lit_array()\
949   case exec(t_array): case exec(t_mixedarray): case exec(t_shortarray)
950 	  cases_lit_1():
951 	  cases_lit_2():
952 	  cases_lit_3():
953 	  cases_lit_4():
954 	  cases_lit_5():
955 	    INCR(lit);
956 	    break;
957 	  cases_lit_array():
958 	    INCR(lit_array);
959 	    break;
960 	    /* Special operators. */
961 	case plain_exec(tx_op_add):
962 x_add:	    INCR(x_add);
963 	    if ((code = zop_add(iosp)) < 0)
964 		return_with_error_code_op(2);
965 	    iosp--;
966 	    next_either();
967 	case plain_exec(tx_op_def):
968 x_def:	    INCR(x_def);
969 	    osp = iosp;	/* sync o_stack */
970 	    if ((code = zop_def(i_ctx_p)) < 0)
971 		return_with_error_code_op(2);
972 	    iosp -= 2;
973 	    next_either();
974 	case plain_exec(tx_op_dup):
975 x_dup:	    INCR(x_dup);
976 	    if (iosp < osbot)
977 		return_with_error_iref(e_stackunderflow);
978 	    if (iosp >= ostop)
979 		return_with_stackoverflow_iref();
980 	    iosp++;
981 	    ref_assign_inline(iosp, iosp - 1);
982 	    next_either();
983 	case plain_exec(tx_op_exch):
984 x_exch:	    INCR(x_exch);
985 	    if (iosp <= osbot)
986 		return_with_error_iref(e_stackunderflow);
987 	    ref_assign_inline(&token, iosp);
988 	    ref_assign_inline(iosp, iosp - 1);
989 	    ref_assign_inline(iosp - 1, &token);
990 	    next_either();
991 	case plain_exec(tx_op_if):
992 x_if:	    INCR(x_if);
993 	    if (!r_has_type(iosp - 1, t_boolean))
994 		return_with_error_iref((iosp <= osbot ?
995 					e_stackunderflow : e_typecheck));
996 	    if (!r_is_proc(iosp))
997 		return_with_error_iref(check_proc_failed(iosp));
998 	    if (!iosp[-1].value.boolval) {
999 		iosp -= 2;
1000 		next_either();
1001 	    }
1002 	    if (iesp >= estop)
1003 		return_with_error_iref(e_execstackoverflow);
1004 	    store_state_either(iesp);
1005 	    whichp = iosp;
1006 	    iosp -= 2;
1007 	    goto ifup;
1008 	case plain_exec(tx_op_ifelse):
1009 x_ifelse:   INCR(x_ifelse);
1010 	    if (!r_has_type(iosp - 2, t_boolean))
1011 		return_with_error_iref((iosp < osbot + 2 ?
1012 					e_stackunderflow : e_typecheck));
1013 	    if (!r_is_proc(iosp - 1))
1014 		return_with_error_iref(check_proc_failed(iosp - 1));
1015 	    if (!r_is_proc(iosp))
1016 		return_with_error_iref(check_proc_failed(iosp));
1017 	    if (iesp >= estop)
1018 		return_with_error_iref(e_execstackoverflow);
1019 	    store_state_either(iesp);
1020 	    whichp = (iosp[-2].value.boolval ? iosp - 1 : iosp);
1021 	    iosp -= 3;
1022 	    /* Open code "up" for the array case(s) */
1023 	  ifup:if ((icount = r_size(whichp) - 1) <= 0) {
1024 		if (icount < 0)
1025 		    goto up;	/* 0-element proc */
1026 		SET_IREF(whichp->value.refs);	/* 1-element proc */
1027 		if (--ticks_left > 0)
1028 		    goto top;
1029 	    }
1030 	    ++iesp;
1031 	    /* Do a ref_assign, but also set iref. */
1032 	    iesp->tas = whichp->tas;
1033 	    SET_IREF(iesp->value.refs = whichp->value.refs);
1034 	    if (--ticks_left > 0)
1035 		goto top;
1036 	    goto slice;
1037 	case plain_exec(tx_op_index):
1038 x_index:    INCR(x_index);
1039 	    osp = iosp;	/* zindex references o_stack */
1040 	    if ((code = zindex(i_ctx_p)) < 0)
1041 		return_with_error_code_op(1);
1042 	    next_either();
1043 	case plain_exec(tx_op_pop):
1044 x_pop:	    INCR(x_pop);
1045 	    if (iosp < osbot)
1046 		return_with_error_iref(e_stackunderflow);
1047 	    iosp--;
1048 	    next_either();
1049 	case plain_exec(tx_op_roll):
1050 x_roll:	    INCR(x_roll);
1051 	    osp = iosp;	/* zroll references o_stack */
1052 	    if ((code = zroll(i_ctx_p)) < 0)
1053 		return_with_error_code_op(2);
1054 	    iosp -= 2;
1055 	    next_either();
1056 	case plain_exec(tx_op_sub):
1057 x_sub:	    INCR(x_sub);
1058 	    if ((code = zop_sub(iosp)) < 0)
1059 		return_with_error_code_op(2);
1060 	    iosp--;
1061 	    next_either();
1062 	    /* Executable types. */
1063 	case plain_exec(t_null):
1064 	    goto bot;
1065 	case plain_exec(t_oparray):
1066 	    /* Replace with the definition and go again. */
1067 	    INCR(exec_array);
1068 	    pvalue = IREF->value.const_refs;
1069 	  opst:		/* Prepare to call a t_oparray procedure in *pvalue. */
1070 	    store_state(iesp);
1071 	  oppr:		/* Record the stack depths in case of failure. */
1072 	    if (iesp >= estop - 3)
1073 		return_with_error_iref(e_execstackoverflow);
1074 	    iesp += 4;
1075 	    osp = iosp;		/* ref_stack_count_inline needs this */
1076 	    make_mark_estack(iesp - 3, es_other, oparray_cleanup);
1077 	    make_int(iesp - 2, ref_stack_count_inline(&o_stack));
1078 	    make_int(iesp - 1, ref_stack_count_inline(&d_stack));
1079 	    make_op_estack(iesp, oparray_pop);
1080 	    goto pr;
1081 	  prst:		/* Prepare to call the procedure (array) in *pvalue. */
1082 	    store_state(iesp);
1083 	  pr:			/* Call the array in *pvalue.  State has been stored. */
1084 	    if ((icount = r_size(pvalue) - 1) <= 0) {
1085 		if (icount < 0)
1086 		    goto up;	/* 0-element proc */
1087 		SET_IREF(pvalue->value.refs);	/* 1-element proc */
1088 		if (--ticks_left > 0)
1089 		    goto top;
1090 	    }
1091 	    if (iesp >= estop)
1092 		return_with_error_iref(e_execstackoverflow);
1093 	    ++iesp;
1094 	    /* Do a ref_assign, but also set iref. */
1095 	    iesp->tas = pvalue->tas;
1096 	    SET_IREF(iesp->value.refs = pvalue->value.refs);
1097 	    if (--ticks_left > 0)
1098 		goto top;
1099 	    goto slice;
1100 	case plain_exec(t_operator):
1101 	    INCR(exec_operator);
1102 	    if (--ticks_left <= 0) {	/* The following doesn't work, */
1103 		/* and I can't figure out why. */
1104 /****** goto sst; ******/
1105 	    }
1106 	    esp = iesp;		/* save for operator */
1107 	    osp = iosp;		/* ditto */
1108 	    /* Operator routines take osp as an argument. */
1109 	    /* This is just a convenience, since they adjust */
1110 	    /* osp themselves to reflect the results. */
1111 	    /* Operators that (net) push information on the */
1112 	    /* operand stack must check for overflow: */
1113 	    /* this normally happens automatically through */
1114 	    /* the push macro (in oper.h). */
1115 	    /* Operators that do not typecheck their operands, */
1116 	    /* or take a variable number of arguments, */
1117 	    /* must check explicitly for stack underflow. */
1118 	    /* (See oper.h for more detail.) */
1119 	    /* Note that each case must set iosp = osp: */
1120 	    /* this is so we can switch on code without having to */
1121 	    /* store it and reload it (for dumb compilers). */
1122 	    switch (code = call_operator(real_opproc(IREF), i_ctx_p)) {
1123 		case 0:	/* normal case */
1124 		case 1:	/* alternative success case */
1125 		    iosp = osp;
1126 		    next();
1127 		case o_push_estack:	/* store the state and go to up */
1128 		    store_state(iesp);
1129 		  opush:iosp = osp;
1130 		    iesp = esp;
1131 		    if (--ticks_left > 0)
1132 			goto up;
1133 		    goto slice;
1134 		case o_pop_estack:	/* just go to up */
1135 		  opop:iosp = osp;
1136 		    if (esp == iesp)
1137 			goto bot;
1138 		    iesp = esp;
1139 		    goto up;
1140 		case o_reschedule:
1141 		    store_state(iesp);
1142 		    goto res;
1143 		case e_RemapColor:
1144 oe_remap:	    store_state(iesp);
1145 remap:		    if (iesp + 2 >= estop) {
1146 			esp = iesp;
1147 			code = ref_stack_extend(&e_stack, 2);
1148 			if (code < 0)
1149 			    return_with_error_iref(code);
1150 			iesp = esp;
1151 		    }
1152 		    packed_get(imemory, iref_packed, iesp + 1);
1153 		    make_oper(iesp + 2, 0,
1154 			      r_ptr(&istate->remap_color_info,
1155 				    int_remap_color_info_t)->proc);
1156 		    iesp += 2;
1157 		    goto up;
1158 	    }
1159 	    iosp = osp;
1160 	    iesp = esp;
1161 	    return_with_code_iref();
1162 	case plain_exec(t_name):
1163 	    INCR(exec_name);
1164 	    pvalue = IREF->value.pname->pvalue;
1165 	    if (!pv_valid(pvalue)) {
1166 		uint nidx = names_index(int_nt, IREF);
1167 		uint htemp;
1168 
1169 		INCR(find_name);
1170 		if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0)
1171 		    return_with_error_iref(e_undefined);
1172 	    }
1173 	    /* Dispatch on the type of the value. */
1174 	    /* Again, we have to over-populate the switch. */
1175 	    switch (r_type_xe(pvalue)) {
1176 		  cases_invalid():
1177 		    return_with_error_iref(e_Fatal);
1178 		  cases_nox():	/* access errors */
1179 		    return_with_error_iref(e_invalidaccess);
1180 		  cases_lit_1():
1181 		  cases_lit_2():
1182 		  cases_lit_3():
1183 		  cases_lit_4():
1184 		  cases_lit_5():
1185 		      INCR(name_lit);
1186 		    /* Just push the value */
1187 		    if (iosp >= ostop)
1188 			return_with_stackoverflow(pvalue);
1189 		    ++iosp;
1190 		    ref_assign_inline(iosp, pvalue);
1191 		    next();
1192 		case exec(t_array):
1193 		case exec(t_mixedarray):
1194 		case exec(t_shortarray):
1195 		    INCR(name_proc);
1196 		    /* This is an executable procedure, execute it. */
1197 		    goto prst;
1198 		case plain_exec(tx_op_add):
1199 		    goto x_add;
1200 		case plain_exec(tx_op_def):
1201 		    goto x_def;
1202 		case plain_exec(tx_op_dup):
1203 		    goto x_dup;
1204 		case plain_exec(tx_op_exch):
1205 		    goto x_exch;
1206 		case plain_exec(tx_op_if):
1207 		    goto x_if;
1208 		case plain_exec(tx_op_ifelse):
1209 		    goto x_ifelse;
1210 		case plain_exec(tx_op_index):
1211 		    goto x_index;
1212 		case plain_exec(tx_op_pop):
1213 		    goto x_pop;
1214 		case plain_exec(tx_op_roll):
1215 		    goto x_roll;
1216 		case plain_exec(tx_op_sub):
1217 		    goto x_sub;
1218 		case plain_exec(t_null):
1219 		    goto bot;
1220 		case plain_exec(t_oparray):
1221 		    INCR(name_oparray);
1222 		    pvalue = (const ref *)pvalue->value.const_refs;
1223 		    goto opst;
1224 		case plain_exec(t_operator):
1225 		    INCR(name_operator);
1226 		    {		/* Shortcut for operators. */
1227 			/* See above for the logic. */
1228 			if (--ticks_left <= 0) {	/* The following doesn't work, */
1229 			    /* and I can't figure out why. */
1230 /****** goto sst; ******/
1231 			}
1232 			esp = iesp;
1233 			osp = iosp;
1234 			switch (code = call_operator(real_opproc(pvalue),
1235 						     i_ctx_p)
1236 				) {
1237 			    case 0:	/* normal case */
1238 			    case 1:	/* alternative success case */
1239 				iosp = osp;
1240 				next();
1241 			    case o_push_estack:
1242 				store_state(iesp);
1243 				goto opush;
1244 			    case o_pop_estack:
1245 				goto opop;
1246 			    case o_reschedule:
1247 				store_state(iesp);
1248 				goto res;
1249 			    case e_RemapColor:
1250 				goto oe_remap;
1251 			}
1252 			iosp = osp;
1253 			iesp = esp;
1254 			return_with_error(code, pvalue);
1255 		    }
1256 		case plain_exec(t_name):
1257 		case exec(t_file):
1258 		case exec(t_string):
1259 		default:
1260 		    /* Not a procedure, reinterpret it. */
1261 		    store_state(iesp);
1262 		    icount = 0;
1263 		    SET_IREF(pvalue);
1264 		    goto top;
1265 	    }
1266 	case exec(t_file):
1267 	    {			/* Executable file.  Read the next token and interpret it. */
1268 		stream *s;
1269 		scanner_state sstate;
1270 
1271 		check_read_known_file(s, IREF, return_with_error_iref);
1272 	    rt:
1273 		if (iosp >= ostop)	/* check early */
1274 		    return_with_stackoverflow_iref();
1275 		osp = iosp;	/* scan_token uses ostack */
1276 		scanner_state_init_options(&sstate, i_ctx_p->scanner_options);
1277 	    again:
1278 		code = scan_token(i_ctx_p, s, &token, &sstate);
1279 		iosp = osp;	/* ditto */
1280 		switch (code) {
1281 		    case 0:	/* read a token */
1282 			/* It's worth checking for literals, which make up */
1283 			/* the majority of input tokens, before storing the */
1284 			/* state on the e-stack.  Note that because of //, */
1285 			/* the token may have *any* type and attributes. */
1286 			/* Note also that executable arrays aren't executed */
1287 			/* at the top level -- they're treated as literals. */
1288 			if (!r_has_attr(&token, a_executable) ||
1289 			    r_is_array(&token)
1290 			    ) {	/* If scan_token used the o-stack, */
1291 			    /* we know we can do a push now; if not, */
1292 			    /* the pre-check is still valid. */
1293 			    iosp++;
1294 			    ref_assign_inline(iosp, &token);
1295 			    goto rt;
1296 			}
1297 			store_state(iesp);
1298 			/* Push the file on the e-stack */
1299 			if (iesp >= estop)
1300 			    return_with_error_iref(e_execstackoverflow);
1301 			esfile_set_cache(++iesp);
1302 			ref_assign_inline(iesp, IREF);
1303 			SET_IREF(&token);
1304 			icount = 0;
1305 			goto top;
1306 		    case e_undefined:	/* //name undefined */
1307 			return_with_error(code, &token);
1308 		    case scan_EOF:	/* end of file */
1309 			esfile_clear_cache();
1310 			goto bot;
1311 		    case scan_BOS:
1312 			/* Binary object sequences */
1313 			/* ARE executed at the top level. */
1314 			store_state(iesp);
1315 			/* Push the file on the e-stack */
1316 			if (iesp >= estop)
1317 			    return_with_error_iref(e_execstackoverflow);
1318 			esfile_set_cache(++iesp);
1319 			ref_assign_inline(iesp, IREF);
1320 			pvalue = &token;
1321 			goto pr;
1322 		    case scan_Refill:
1323 			store_state(iesp);
1324 			/* iref may point into the exec stack; */
1325 			/* save its referent now. */
1326 			ref_assign_inline(&token, IREF);
1327 			/* Push the file on the e-stack */
1328 			if (iesp >= estop)
1329 			    return_with_error_iref(e_execstackoverflow);
1330 			++iesp;
1331 			ref_assign_inline(iesp, &token);
1332 			esp = iesp;
1333 			osp = iosp;
1334 			code = scan_handle_refill(i_ctx_p, &token, &sstate,
1335 						  true, true,
1336 						  ztokenexec_continue);
1337 		scan_cont:
1338 			iosp = osp;
1339 			iesp = esp;
1340 			switch (code) {
1341 			    case 0:
1342 				iesp--;		/* don't push the file */
1343 				goto again;	/* stacks are unchanged */
1344 			    case o_push_estack:
1345 				esfile_clear_cache();
1346 				if (--ticks_left > 0)
1347 				    goto up;
1348 				goto slice;
1349 			}
1350 			/* must be an error */
1351 			iesp--;	/* don't push the file */
1352 			return_with_code_iref();
1353 		    case scan_Comment:
1354 		    case scan_DSC_Comment: {
1355 			/* See scan_Refill above for comments. */
1356 			ref file_token;
1357 
1358 			store_state(iesp);
1359 			ref_assign_inline(&file_token, IREF);
1360 			if (iesp >= estop)
1361 			    return_with_error_iref(e_execstackoverflow);
1362 			++iesp;
1363 			ref_assign_inline(iesp, &file_token);
1364 			esp = iesp;
1365 			osp = iosp;
1366 			code = ztoken_handle_comment(i_ctx_p, &file_token,
1367 						     &sstate, &token,
1368 						     code, true, true,
1369 						     ztokenexec_continue);
1370 		    }
1371 			goto scan_cont;
1372 		    default:	/* error */
1373 			return_with_code_iref();
1374 		}
1375 	    }
1376 	case exec(t_string):
1377 	    {			/* Executable string.  Read a token and interpret it. */
1378 		stream ss;
1379 		scanner_state sstate;
1380 
1381 		scanner_state_init_options(&sstate, SCAN_FROM_STRING);
1382 		s_init(&ss, NULL);
1383 		sread_string(&ss, IREF->value.bytes, r_size(IREF));
1384 		osp = iosp;	/* scan_token uses ostack */
1385 		code = scan_token(i_ctx_p, &ss, &token, &sstate);
1386 		iosp = osp;	/* ditto */
1387 		switch (code) {
1388 		    case 0:	/* read a token */
1389 		    case scan_BOS:	/* binary object sequence */
1390 			store_state(iesp);
1391 			/* If the updated string isn't empty, push it back */
1392 			/* on the e-stack. */
1393 			{
1394 			    uint size = sbufavailable(&ss);
1395 
1396 			    if (size) {
1397 				if (iesp >= estop)
1398 				    return_with_error_iref(e_execstackoverflow);
1399 				++iesp;
1400 				iesp->tas.type_attrs = IREF->tas.type_attrs;
1401 				iesp->value.const_bytes = sbufptr(&ss);
1402 				r_set_size(iesp, size);
1403 			    }
1404 			}
1405 			if (code == 0) {
1406 			    SET_IREF(&token);
1407 			    icount = 0;
1408 			    goto top;
1409 			}
1410 			/* Handle BOS specially */
1411 			pvalue = &token;
1412 			goto pr;
1413 		    case scan_EOF:	/* end of string */
1414 			goto bot;
1415 		    case scan_Refill:	/* error */
1416 			code = gs_note_error(e_syntaxerror);
1417 		    default:	/* error */
1418 			return_with_code_iref();
1419 		}
1420 	    }
1421 	    /* Handle packed arrays here by re-dispatching. */
1422 	    /* This also picks up some anomalous cases of non-packed arrays. */
1423 	default:
1424 	    {
1425 		uint index;
1426 
1427 		switch (*iref_packed >> r_packed_type_shift) {
1428 		    case pt_full_ref:
1429 		    case pt_full_ref + 1:
1430 			INCR(p_full);
1431 			if (iosp >= ostop)
1432 			    return_with_stackoverflow_iref();
1433 			/* We know this can't be an executable object */
1434 			/* requiring special handling, so we just push it. */
1435 			++iosp;
1436 			/* We know that refs are properly aligned: */
1437 			/* see packed.h for details. */
1438 			ref_assign_inline(iosp, IREF);
1439 			next();
1440 		    case pt_executable_operator:
1441 			index = *iref_packed & packed_value_mask;
1442 			if (--ticks_left <= 0) {	/* The following doesn't work, */
1443 			    /* and I can't figure out why. */
1444 /****** goto sst_short; ******/
1445 			}
1446 			if (!op_index_is_operator(index)) {
1447 			    INCR(p_exec_oparray);
1448 			    store_state_short(iesp);
1449 			    /* Call the operator procedure. */
1450 			    index -= op_def_count;
1451 			    pvalue = (const ref *)
1452 				(index < r_size(&op_array_table_global.table) ?
1453 			      op_array_table_global.table.value.const_refs +
1454 				 index :
1455 			       op_array_table_local.table.value.const_refs +
1456 			    (index - r_size(&op_array_table_global.table)));
1457 			    goto oppr;
1458 			}
1459 			INCR(p_exec_operator);
1460 			/* See the main plain_exec(t_operator) case */
1461 			/* for details of what happens here. */
1462 #if PACKED_SPECIAL_OPS
1463 			/*
1464 			 * We arranged in iinit.c that the special ops
1465 			 * have operator indices starting at 1.
1466 			 *
1467 			 * The (int) cast in the next line is required
1468 			 * because some compilers don't allow arithmetic
1469 			 * involving two different enumerated types.
1470 			 */
1471 #  define case_xop(xop) case xop - (int)tx_op + 1
1472 			switch (index) {
1473 			      case_xop(tx_op_add):goto x_add;
1474 			      case_xop(tx_op_def):goto x_def;
1475 			      case_xop(tx_op_dup):goto x_dup;
1476 			      case_xop(tx_op_exch):goto x_exch;
1477 			      case_xop(tx_op_if):goto x_if;
1478 			      case_xop(tx_op_ifelse):goto x_ifelse;
1479 			      case_xop(tx_op_index):goto x_index;
1480 			      case_xop(tx_op_pop):goto x_pop;
1481 			      case_xop(tx_op_roll):goto x_roll;
1482 			      case_xop(tx_op_sub):goto x_sub;
1483 			    case 0:	/* for dumb compilers */
1484 			    default:
1485 				;
1486 			}
1487 #  undef case_xop
1488 #endif
1489 			INCR(p_exec_non_x_operator);
1490 			esp = iesp;
1491 			osp = iosp;
1492 			switch (code = call_operator(op_index_proc(index), i_ctx_p)) {
1493 			    case 0:
1494 			    case 1:
1495 				iosp = osp;
1496 				next_short();
1497 			    case o_push_estack:
1498 				store_state_short(iesp);
1499 				goto opush;
1500 			    case o_pop_estack:
1501 				iosp = osp;
1502 				if (esp == iesp) {
1503 				    next_short();
1504 				}
1505 				iesp = esp;
1506 				goto up;
1507 			    case o_reschedule:
1508 				store_state_short(iesp);
1509 				goto res;
1510 			    case e_RemapColor:
1511 				store_state_short(iesp);
1512 				goto remap;
1513 			}
1514 			iosp = osp;
1515 			iesp = esp;
1516 			return_with_code_iref();
1517 		    case pt_integer:
1518 			INCR(p_integer);
1519 			if (iosp >= ostop)
1520 			    return_with_stackoverflow_iref();
1521 			++iosp;
1522 			make_int(iosp,
1523 				 ((int)*iref_packed & packed_int_mask) +
1524 				 packed_min_intval);
1525 			next_short();
1526 		    case pt_literal_name:
1527 			INCR(p_lit_name);
1528 			{
1529 			    uint nidx = *iref_packed & packed_value_mask;
1530 
1531 			    if (iosp >= ostop)
1532 				return_with_stackoverflow_iref();
1533 			    ++iosp;
1534 			    name_index_ref_inline(int_nt, nidx, iosp);
1535 			    next_short();
1536 			}
1537 		    case pt_executable_name:
1538 			INCR(p_exec_name);
1539 			{
1540 			    uint nidx = *iref_packed & packed_value_mask;
1541 
1542 			    pvalue = name_index_ptr_inline(int_nt, nidx)->pvalue;
1543 			    if (!pv_valid(pvalue)) {
1544 				uint htemp;
1545 
1546 				INCR(p_find_name);
1547 				if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0) {
1548 				    names_index_ref(int_nt, nidx, &token);
1549 				    return_with_error(e_undefined, &token);
1550 				}
1551 			    }
1552 			    if (r_has_masked_attrs(pvalue, a_execute, a_execute + a_executable)) {	/* Literal, push it. */
1553 				INCR(p_name_lit);
1554 				if (iosp >= ostop)
1555 				    return_with_stackoverflow_iref();
1556 				++iosp;
1557 				ref_assign_inline(iosp, pvalue);
1558 				next_short();
1559 			    }
1560 			    if (r_is_proc(pvalue)) {	/* This is an executable procedure, */
1561 				/* execute it. */
1562 				INCR(p_name_proc);
1563 				store_state_short(iesp);
1564 				goto pr;
1565 			    }
1566 			    /* Not a literal or procedure, reinterpret it. */
1567 			    store_state_short(iesp);
1568 			    icount = 0;
1569 			    SET_IREF(pvalue);
1570 			    goto top;
1571 			}
1572 			/* default can't happen here */
1573 		}
1574 	    }
1575     }
1576     /* Literal type, just push it. */
1577     if (iosp >= ostop)
1578 	return_with_stackoverflow_iref();
1579     ++iosp;
1580     ref_assign_inline(iosp, IREF);
1581   bot:next();
1582   out:				/* At most 1 more token in the current procedure. */
1583     /* (We already decremented icount.) */
1584     if (!icount) {
1585 	/* Pop the execution stack for tail recursion. */
1586 	iesp--;
1587 	iref_packed = IREF_NEXT(iref_packed);
1588 	goto top;
1589     }
1590   up:if (--ticks_left < 0)
1591 	goto slice;
1592     /* See if there is anything left on the execution stack. */
1593     if (!r_is_proc(iesp)) {
1594 	SET_IREF(iesp--);
1595 	icount = 0;
1596 	goto top;
1597     }
1598     SET_IREF(iesp->value.refs);	/* next element of array */
1599     icount = r_size(iesp) - 1;
1600     if (icount <= 0) {		/* <= 1 more elements */
1601 	iesp--;			/* pop, or tail recursion */
1602 	if (icount < 0)
1603 	    goto up;
1604     }
1605     goto top;
1606 res:
1607     /* Some operator has asked for context rescheduling. */
1608     /* We've done a store_state. */
1609     *pi_ctx_p = i_ctx_p;
1610     code = (*gs_interp_reschedule_proc)(pi_ctx_p);
1611     i_ctx_p = *pi_ctx_p;
1612   sched:			/* We've just called a scheduling procedure. */
1613     /* The interpreter state is in memory; iref is not current. */
1614     if (code < 0) {
1615 	set_error(code);
1616 	/*
1617 	 * We need a real object to return as the error object.
1618 	 * (It only has to last long enough to store in
1619 	 * *perror_object.)
1620 	 */
1621 	make_null_proc(&ierror.full);
1622 	SET_IREF(ierror.obj = &ierror.full);
1623 	goto error_exit;
1624     }
1625     /* Reload state information from memory. */
1626     iosp = osp;
1627     iesp = esp;
1628     goto up;
1629 #if 0				/****** ****** ***** */
1630   sst:				/* Time-slice, but push the current object first. */
1631     store_state(iesp);
1632     if (iesp >= estop)
1633 	return_with_error_iref(e_execstackoverflow);
1634     iesp++;
1635     ref_assign_inline(iesp, iref);
1636 #endif /****** ****** ***** */
1637   slice:			/* It's time to time-slice or garbage collect. */
1638     /* iref is not live, so we don't need to do a store_state. */
1639     osp = iosp;
1640     esp = iesp;
1641     /* If ticks_left <= -100, we need to GC now. */
1642     if (ticks_left <= -100) {	/* We need to garbage collect now. */
1643 	*pi_ctx_p = i_ctx_p;
1644 	code = interp_reclaim(pi_ctx_p, -1);
1645 	i_ctx_p = *pi_ctx_p;
1646     } else if (gs_interp_time_slice_proc) {
1647 	*pi_ctx_p = i_ctx_p;
1648 	code = (*gs_interp_time_slice_proc)(pi_ctx_p);
1649 	i_ctx_p = *pi_ctx_p;
1650     } else
1651 	code = 0;
1652     ticks_left = gs_interp_time_slice_ticks;
1653     set_code_on_interrupt(imemory, &code);
1654     goto sched;
1655 
1656     /* Error exits. */
1657 
1658   rweci:
1659     ierror.code = code;
1660   rwei:
1661     ierror.obj = IREF;
1662   rwe:
1663     if (!r_is_packed(iref_packed))
1664 	store_state(iesp);
1665     else {
1666 	/*
1667 	 * We need a real object to return as the error object.
1668 	 * (It only has to last long enough to store in *perror_object.)
1669 	 */
1670 	packed_get(imemory, (const ref_packed *)ierror.obj, &ierror.full);
1671 	store_state_short(iesp);
1672 	if (IREF == ierror.obj)
1673 	    SET_IREF(&ierror.full);
1674 	ierror.obj = &ierror.full;
1675     }
1676   error_exit:
1677     if (ERROR_IS_INTERRUPT(ierror.code)) {	/* We must push the current object being interpreted */
1678 	/* back on the e-stack so it will be re-executed. */
1679 	/* Currently, this is always an executable operator, */
1680 	/* but it might be something else someday if we check */
1681 	/* for interrupts in the interpreter loop itself. */
1682 	if (iesp >= estop)
1683 	    code = e_execstackoverflow;
1684 	else {
1685 	    iesp++;
1686 	    ref_assign_inline(iesp, IREF);
1687 	}
1688     }
1689     esp = iesp;
1690     osp = iosp;
1691     ref_assign_inline(perror_object, ierror.obj);
1692     return gs_log_error(ierror.code, __FILE__, ierror.line);
1693 }
1694 
1695 /* Pop the bookkeeping information for a normal exit from a t_oparray. */
1696 private int
oparray_pop(i_ctx_t * i_ctx_p)1697 oparray_pop(i_ctx_t *i_ctx_p)
1698 {
1699     esp -= 3;
1700     return o_pop_estack;
1701 }
1702 
1703 /* Restore the stack pointers after an error inside a t_oparray procedure. */
1704 /* This procedure is called only from pop_estack. */
1705 private int
oparray_cleanup(i_ctx_t * i_ctx_p)1706 oparray_cleanup(i_ctx_t *i_ctx_p)
1707 {				/* esp points just below the cleanup procedure. */
1708     es_ptr ep = esp;
1709     uint ocount_old = (uint) ep[2].value.intval;
1710     uint dcount_old = (uint) ep[3].value.intval;
1711     uint ocount = ref_stack_count(&o_stack);
1712     uint dcount = ref_stack_count(&d_stack);
1713 
1714     if (ocount > ocount_old)
1715 	ref_stack_pop(&o_stack, ocount - ocount_old);
1716     if (dcount > dcount_old) {
1717 	ref_stack_pop(&d_stack, dcount - dcount_old);
1718 	dict_set_top();
1719     }
1720     return 0;
1721 }
1722 
1723 /* Don't restore the stack pointers. */
1724 private int
oparray_no_cleanup(i_ctx_t * i_ctx_p)1725 oparray_no_cleanup(i_ctx_t *i_ctx_p)
1726 {
1727     return 0;
1728 }
1729 
1730 /* Find the innermost oparray. */
1731 private ref *
oparray_find(i_ctx_t * i_ctx_p)1732 oparray_find(i_ctx_t *i_ctx_p)
1733 {
1734     long i;
1735     ref *ep;
1736 
1737     for (i = 0; (ep = ref_stack_index(&e_stack, i)) != 0; ++i) {
1738 	if (r_is_estack_mark(ep) &&
1739 	    (ep->value.opproc == oparray_cleanup ||
1740 	     ep->value.opproc == oparray_no_cleanup)
1741 	    )
1742 	    return ep;
1743     }
1744     return 0;
1745 }
1746 
1747 /* <bool> .setstackprotect - */
1748 /* Set whether to protect the stack for the innermost oparray. */
1749 private int
zsetstackprotect(i_ctx_t * i_ctx_p)1750 zsetstackprotect(i_ctx_t *i_ctx_p)
1751 {
1752     os_ptr op = osp;
1753     ref *ep = oparray_find(i_ctx_p);
1754 
1755     check_type(*op, t_boolean);
1756     if (ep == 0)
1757 	return_error(e_rangecheck);
1758     ep->value.opproc =
1759 	(op->value.boolval ? oparray_cleanup : oparray_no_cleanup);
1760     pop(1);
1761     return 0;
1762 }
1763 
1764 /* - .currentstackprotect <bool> */
1765 /* Return the stack protection status. */
1766 private int
zcurrentstackprotect(i_ctx_t * i_ctx_p)1767 zcurrentstackprotect(i_ctx_t *i_ctx_p)
1768 {
1769     os_ptr op = osp;
1770     ref *ep = oparray_find(i_ctx_p);
1771 
1772     if (ep == 0)
1773 	return_error(e_rangecheck);
1774     push(1);
1775     make_bool(op, ep->value.opproc == oparray_cleanup);
1776     return 0;
1777 }
1778