Coverage Report

Created: 2025-06-10 07:19

/src/ghostpdl/psi/interp.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 2001-2024 Artifex Software, Inc.
2
   All Rights Reserved.
3
4
   This software is provided AS-IS with no warranty, either express or
5
   implied.
6
7
   This software is distributed under license and may not be copied,
8
   modified or distributed except as expressly authorized under the terms
9
   of the license contained in the file LICENSE in this distribution.
10
11
   Refer to licensing information at http://www.artifex.com or contact
12
   Artifex Software, Inc.,  39 Mesa Street, Suite 108A, San Francisco,
13
   CA 94129, USA, for further information.
14
*/
15
16
17
/* Ghostscript language interpreter */
18
#include "memory_.h"
19
#include "string_.h"
20
#include "ghost.h"
21
#include "gsstruct.h"           /* for iastruct.h */
22
#include "gserrors.h"           /* for gpcheck.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 gs_error_Remap_Color */
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 "iinit.h"
47
#include "dstack.h"
48
#include "files.h"              /* for file_check_read */
49
#include "oper.h"
50
#include "store.h"
51
#include "gpcheck.h"
52
#define FORCE_ASSERT_CHECKING 1
53
#define DEBUG_TRACE_PS_OPERATORS 1
54
#include "assert_.h"
55
56
/*
57
 * We may or may not optimize the handling of the special fast operators
58
 * in packed arrays.  If we do this, they run much faster when packed, but
59
 * slightly slower when not packed.
60
 */
61
#define PACKED_SPECIAL_OPS 1
62
63
/*
64
 * Pseudo-operators (procedures of type t_oparray) record
65
 * the operand and dictionary stack pointers, and restore them if an error
66
 * occurs during the execution of the procedure and if the procedure hasn't
67
 * (net) decreased the depth of the stack.  While this obviously doesn't
68
 * do all the work of restoring the state if a pseudo-operator gets an
69
 * error, it's a big help.  The only downside is that pseudo-operators run
70
 * a little slower.
71
 */
72
73
/* GC descriptors for stacks */
74
extern_st(st_ref_stack);
75
public_st_dict_stack();
76
public_st_exec_stack();
77
public_st_op_stack();
78
79
/*
80
 * Apply an operator.  When debugging, we route all operator calls
81
 * through a procedure.
82
 */
83
#if defined(DEBUG_TRACE_PS_OPERATORS) || defined(DEBUG)
84
1.89G
#define call_operator(proc, p) (*call_operator_fn)(proc, p)
85
static int
86
do_call_operator(op_proc_t op_proc, i_ctx_t *i_ctx_p)
87
1.89G
{
88
1.89G
    int code;
89
1.89G
    assert(e_stack.p >= e_stack.bot - 1 && e_stack.p < e_stack.top + 1);
90
1.89G
    assert(o_stack.p >= o_stack.bot - 1 && o_stack.p < o_stack.top + 1);
91
1.89G
    code = op_proc(i_ctx_p);
92
1.89G
    if (gs_debug_c(gs_debug_flag_validate_clumps))
93
0
        ivalidate_clean_spaces(i_ctx_p);
94
1.89G
    assert(e_stack.p >= e_stack.bot - 1 && e_stack.p < e_stack.top + 1);
95
1.89G
    assert(o_stack.p >= o_stack.bot - 1 && o_stack.p < o_stack.top + 1);
96
1.89G
    return code; /* A good place for a conditional breakpoint. */
97
1.89G
}
98
static int
99
do_call_operator_verbose(op_proc_t op_proc, i_ctx_t *i_ctx_p)
100
0
{
101
0
    int code;
102
103
0
#ifndef SHOW_STACK_DEPTHS
104
0
    if_debug1m('!', imemory, "[!]operator %s\n", op_get_name_string(op_proc));
105
#else
106
    if_debug3m('!', imemory, "[!][es=%d os=%d]operator %s\n",
107
            esp-i_ctx_p->exec_stack.stack.bot,
108
            osp-i_ctx_p->op_stack.stack.bot,
109
            op_get_name_string(op_proc));
110
#endif
111
0
    code = do_call_operator(op_proc, i_ctx_p);
112
0
    if (code < 0)
113
0
        if_debug1m('!', imemory, "[!]   error: %d\n", code);
114
#if defined(SHOW_STACK_DEPTHS)
115
    if_debug2m('!', imemory, "[!][es=%d os=%d]\n",
116
            esp-i_ctx_p->exec_stack.stack.bot,
117
            osp-i_ctx_p->op_stack.stack.bot);
118
#endif
119
0
    if (gs_debug_c(gs_debug_flag_validate_clumps))
120
0
        ivalidate_clean_spaces(i_ctx_p);
121
0
    return code; /* A good place for a conditional breakpoint. */
122
0
}
123
#else
124
#  define call_operator(proc, p) ((*(proc))(p))
125
#endif
126
127
/* Define debugging statistics (not threadsafe as uses globals) */
128
/* #define COLLECT_STATS_IDSTACK */
129
130
#ifdef COLLECT_STATS_INTERP
131
struct stats_interp_s {
132
    long top;
133
    long lit, lit_array, exec_array, exec_operator, exec_name;
134
    long x_add, x_def, x_dup, x_exch, x_if, x_ifelse,
135
        x_index, x_pop, x_roll, x_sub;
136
    long find_name, name_lit, name_proc, name_oparray, name_operator;
137
    long p_full, p_exec_operator, p_exec_oparray, p_exec_non_x_operator,
138
        p_integer, p_lit_name, p_exec_name;
139
    long p_find_name, p_name_lit, p_name_proc;
140
} stats_interp;
141
# define INCR(v) (++(stats_interp.v))
142
#else
143
16.8G
# define INCR(v) DO_NOTHING
144
#endif
145
146
/* Forward references */
147
static int estack_underflow(i_ctx_t *);
148
static int interp(i_ctx_t **, const ref *, ref *);
149
static int interp_exit(i_ctx_t *);
150
static int zforceinterp_exit(i_ctx_t *i_ctx_p);
151
static void set_gc_signal(i_ctx_t *, int);
152
static int copy_stack(i_ctx_t *, const ref_stack_t *, int skip, ref *);
153
static int oparray_pop(i_ctx_t *);
154
static int oparray_cleanup(i_ctx_t *);
155
static int zerrorexec(i_ctx_t *);
156
static int zfinderrorobject(i_ctx_t *);
157
static int errorexec_pop(i_ctx_t *);
158
static int errorexec_cleanup(i_ctx_t *);
159
static int zsetstackprotect(i_ctx_t *);
160
static int zcurrentstackprotect(i_ctx_t *);
161
static int zactonuel(i_ctx_t *);
162
163
/* Stack sizes */
164
165
/* The maximum stack sizes may all be set in the makefile. */
166
167
/*
168
 * Define the initial maximum size of the operand stack (MaxOpStack
169
 * user parameter).
170
 */
171
#ifndef MAX_OSTACK
172
9.57k
#  define MAX_OSTACK 800
173
#endif
174
/*
175
 * The minimum block size for extending the operand stack is the larger of:
176
 *      - the maximum number of parameters to an operator
177
 *      (currently setcolorscreen, with 12 parameters);
178
 *      - the maximum number of values pushed by an operator
179
 *      (currently setcolortransfer, which calls zcolor_remap_one 4 times
180
 *      and therefore pushes 16 values).
181
 */
182
#define MIN_BLOCK_OSTACK 16
183
const int gs_interp_max_op_num_args = MIN_BLOCK_OSTACK;         /* for iinit.c */
184
185
/*
186
 * Define the initial maximum size of the execution stack (MaxExecStack
187
 * user parameter).
188
 */
189
#ifndef MAX_ESTACK
190
9.57k
#  define MAX_ESTACK 5000
191
#endif
192
/*
193
 * The minimum block size for extending the execution stack is the largest
194
 * size of a contiguous block surrounding an e-stack mark.  (At least,
195
 * that's what the minimum value would be if we supported multi-block
196
 * estacks, which we currently don't.)  Currently, the largest such block is
197
 * the one created for text processing, which is 8 (snumpush) slots.
198
 */
199
16
#define MIN_BLOCK_ESTACK 8
200
/*
201
 * If we get an e-stack overflow, we need to cut it back far enough to
202
 * have some headroom for executing the error procedure.
203
 */
204
3
#define ES_HEADROOM 20
205
206
/*
207
 * Define the initial maximum size of the dictionary stack (MaxDictStack
208
 * user parameter).  Again, this is also currently the block size for
209
 * extending the d-stack.
210
 */
211
#ifndef MAX_DSTACK
212
9.57k
#  define MAX_DSTACK 20
213
#endif
214
/*
215
 * The minimum block size for extending the dictionary stack is the number
216
 * of permanent entries on the dictionary stack, currently 3.
217
 */
218
#define MIN_BLOCK_DSTACK 3
219
220
/* See estack.h for a description of the execution stack. */
221
222
/* The logic for managing icount and iref below assumes that */
223
/* there are no control operators which pop and then push */
224
/* information on the execution stack. */
225
226
/* Stacks */
227
extern_st(st_ref_stack);
228
28.7k
#define OS_GUARD_UNDER 10
229
28.7k
#define OS_GUARD_OVER 10
230
#define OS_REFS_SIZE(body_size)\
231
19.1k
  (stack_block_refs + OS_GUARD_UNDER + (body_size) + OS_GUARD_OVER)
232
233
28.7k
#define ES_GUARD_UNDER 1
234
28.7k
#define ES_GUARD_OVER 10
235
#define ES_REFS_SIZE(body_size)\
236
19.1k
  (stack_block_refs + ES_GUARD_UNDER + (body_size) + ES_GUARD_OVER)
237
238
#define DS_REFS_SIZE(body_size)\
239
9.57k
  (stack_block_refs + (body_size))
240
241
/* Extended types.  The interpreter may replace the type of operators */
242
/* in procedures with these, to speed up the interpretation loop. */
243
/****** NOTE: If you add or change entries in this list, */
244
/****** you must change the three dispatches in the interpreter loop. */
245
/* The operator procedures are declared in opextern.h. */
246
1.24G
#define tx_op t_next_index
247
typedef enum {
248
    tx_op_add = tx_op,
249
    tx_op_def,
250
    tx_op_dup,
251
    tx_op_exch,
252
    tx_op_if,
253
    tx_op_ifelse,
254
    tx_op_index,
255
    tx_op_pop,
256
    tx_op_roll,
257
    tx_op_sub,
258
    tx_next_op
259
} special_op_types;
260
261
6.27M
#define num_special_ops ((int)tx_next_op - tx_op)
262
const int gs_interp_num_special_ops = num_special_ops;  /* for iinit.c */
263
const int tx_next_index = tx_next_op;
264
265
/*
266
 * NOTE: if the size of either table below ever exceeds 15 real entries, it
267
 * will have to be split.
268
 */
269
/* Define the extended-type operators per the list above. */
270
const op_def interp1_op_defs[] = {
271
    /*
272
     * The very first entry, which corresponds to operator index 0,
273
     * must not contain an actual operator.
274
     */
275
    op_def_begin_dict("systemdict"),
276
    {"2add", zadd},
277
    {"2def", zdef},
278
    {"1dup", zdup},
279
    {"2exch", zexch},
280
    {"2if", zif},
281
    {"3ifelse", zifelse},
282
    {"1index", zindex},
283
    {"1pop", zpop},
284
    {"2roll", zroll},
285
    {"2sub", zsub},
286
    op_def_end(0)
287
};
288
/* Define the internal interpreter operators. */
289
const op_def interp2_op_defs[] = {
290
    {"0.currentstackprotect", zcurrentstackprotect},
291
    {"1.setstackprotect", zsetstackprotect},
292
    {"2.errorexec", zerrorexec},
293
    {"0.finderrorobject", zfinderrorobject},
294
    {"0%interp_exit", interp_exit},
295
    {"0.forceinterp_exit", zforceinterp_exit},
296
    {"0%oparray_pop", oparray_pop},
297
    {"0%errorexec_pop", errorexec_pop},
298
    {"0.actonuel", zactonuel},
299
    op_def_end(0)
300
};
301
302
#define make_null_proc(pref)\
303
2.84k
  make_empty_const_array(pref, a_executable + a_readonly)
304
305
/* Initialize the interpreter. */
306
int
307
gs_interp_init(i_ctx_t **pi_ctx_p, const ref *psystem_dict,
308
               gs_dual_memory_t *dmem)
309
9.57k
{
310
    /* Create and initialize a context state. */
311
9.57k
    gs_context_state_t *pcst = 0;
312
9.57k
    int code = context_state_alloc(&pcst, psystem_dict, dmem);
313
9.57k
    if (code >= 0) {
314
9.57k
        code = context_state_load(pcst);
315
9.57k
        if (code < 0) {
316
0
            context_state_free(pcst);
317
0
            pcst = NULL;
318
0
        }
319
9.57k
    }
320
321
9.57k
    if (code < 0)
322
0
        lprintf1("Fatal error %d in gs_interp_init!\n", code);
323
9.57k
    *pi_ctx_p = pcst;
324
325
9.57k
    return code;
326
9.57k
}
327
/*
328
 * Create initial stacks for the interpreter.
329
 * We export this for creating new contexts.
330
 */
331
int
332
gs_interp_alloc_stacks(gs_ref_memory_t *mem, gs_context_state_t * pcst)
333
9.57k
{
334
9.57k
    int code;
335
9.57k
    gs_ref_memory_t *smem =
336
9.57k
        (gs_ref_memory_t *)gs_memory_stable((gs_memory_t *)mem);
337
9.57k
    ref stk;
338
339
19.1k
#define REFS_SIZE_OSTACK OS_REFS_SIZE(MAX_OSTACK)
340
19.1k
#define REFS_SIZE_ESTACK ES_REFS_SIZE(MAX_ESTACK)
341
9.57k
#define REFS_SIZE_DSTACK DS_REFS_SIZE(MAX_DSTACK)
342
9.57k
    code = gs_alloc_ref_array(smem, &stk, 0,
343
9.57k
                       REFS_SIZE_OSTACK + REFS_SIZE_ESTACK +
344
9.57k
                       REFS_SIZE_DSTACK, "gs_interp_alloc_stacks");
345
9.57k
    if (code < 0)
346
0
        return code;
347
348
9.57k
    {
349
9.57k
        ref_stack_t *pos = &pcst->op_stack.stack;
350
351
9.57k
        r_set_size(&stk, REFS_SIZE_OSTACK);
352
9.57k
        code = ref_stack_init(pos, &stk, OS_GUARD_UNDER, OS_GUARD_OVER, NULL,
353
9.57k
                              smem, NULL);
354
9.57k
  if (code < 0)
355
0
            return code;
356
9.57k
        ref_stack_set_error_codes(pos, gs_error_stackunderflow, gs_error_stackoverflow);
357
9.57k
        ref_stack_set_max_count(pos, MAX_OSTACK);
358
9.57k
        stk.value.refs += REFS_SIZE_OSTACK;
359
9.57k
    }
360
361
0
    {
362
9.57k
        ref_stack_t *pes = &pcst->exec_stack.stack;
363
9.57k
        ref euop;
364
365
9.57k
        r_set_size(&stk, REFS_SIZE_ESTACK);
366
9.57k
        make_oper(&euop, 0, estack_underflow);
367
9.57k
        code = ref_stack_init(pes, &stk, ES_GUARD_UNDER, ES_GUARD_OVER, &euop,
368
9.57k
                       smem, NULL);
369
9.57k
  if (code < 0)
370
0
            return code;
371
9.57k
        ref_stack_set_error_codes(pes, gs_error_ExecStackUnderflow,
372
9.57k
                                  gs_error_execstackoverflow);
373
        /**************** E-STACK EXPANSION IS NYI. ****************/
374
9.57k
        ref_stack_allow_expansion(pes, false);
375
9.57k
        ref_stack_set_max_count(pes, MAX_ESTACK);
376
9.57k
        stk.value.refs += REFS_SIZE_ESTACK;
377
9.57k
    }
378
379
0
    {
380
9.57k
        ref_stack_t *pds = &pcst->dict_stack.stack;
381
382
9.57k
        r_set_size(&stk, REFS_SIZE_DSTACK);
383
9.57k
        code = ref_stack_init(pds, &stk, 0, 0, NULL, smem, NULL);
384
9.57k
        if (code < 0)
385
0
            return code;
386
9.57k
        ref_stack_set_error_codes(pds, gs_error_dictstackunderflow,
387
9.57k
                                  gs_error_dictstackoverflow);
388
9.57k
        ref_stack_set_max_count(pds, MAX_DSTACK);
389
9.57k
    }
390
391
0
#undef REFS_SIZE_OSTACK
392
0
#undef REFS_SIZE_ESTACK
393
0
#undef REFS_SIZE_DSTACK
394
0
    return 0;
395
9.57k
}
396
/*
397
 * Free the stacks when destroying a context.  This is the inverse of
398
 * create_stacks.
399
 */
400
void
401
gs_interp_free_stacks(gs_ref_memory_t * smem, gs_context_state_t * pcst)
402
0
{
403
    /* Free the stacks in inverse order of allocation. */
404
0
    ref_stack_release(&pcst->dict_stack.stack);
405
0
    ref_stack_release(&pcst->exec_stack.stack);
406
0
    ref_stack_release(&pcst->op_stack.stack);
407
0
}
408
void
409
gs_interp_reset(i_ctx_t *i_ctx_p)
410
9.57k
{   /* Reset the stacks. */
411
9.57k
    ref_stack_clear(&o_stack);
412
9.57k
    ref_stack_clear(&e_stack);
413
9.57k
    esp++;
414
9.57k
    make_oper(esp, 0, interp_exit);
415
9.57k
    ref_stack_pop_to(&d_stack, min_dstack_size);
416
9.57k
    dict_set_top();
417
9.57k
}
418
/* Report an e-stack block underflow.  The bottom guard slots of */
419
/* e-stack blocks contain a pointer to this procedure. */
420
static int
421
estack_underflow(i_ctx_t *i_ctx_p)
422
0
{
423
0
    return gs_error_ExecStackUnderflow;
424
0
}
425
426
/*
427
 * Create an operator during initialization.
428
 * If operator is hard-coded into the interpreter,
429
 * assign it a special type and index.
430
 */
431
void
432
gs_interp_make_oper(ref * opref, op_proc_t proc, int idx)
433
6.27M
{
434
6.27M
    int i;
435
436
67.9M
    for (i = num_special_ops; i > 0 && proc != interp1_op_defs[i].proc; --i)
437
61.6M
        DO_NOTHING;
438
6.27M
    if (i > 0)
439
191k
        make_tasv(opref, tx_op + (i - 1), a_executable, i, opproc, proc);
440
6.08M
    else
441
6.08M
        make_tasv(opref, t_operator, a_executable, idx, opproc, proc);
442
6.27M
}
443
444
/*
445
 * Call the garbage collector, updating the context pointer properly.
446
 */
447
int
448
interp_reclaim(i_ctx_t **pi_ctx_p, int space)
449
20.1k
{
450
20.1k
    i_ctx_t *i_ctx_p = *pi_ctx_p;
451
20.1k
    gs_gc_root_t ctx_root, *r = &ctx_root;
452
20.1k
    int code;
453
454
#ifdef DEBUG
455
    if (gs_debug_c(gs_debug_flag_gc_disable))
456
        return 0;
457
#endif
458
459
20.1k
    gs_register_struct_root(imemory_system, &r,
460
20.1k
                            (void **)pi_ctx_p, "interp_reclaim(pi_ctx_p)");
461
20.1k
    code = (*idmemory->reclaim)(idmemory, space);
462
20.1k
    i_ctx_p = *pi_ctx_p;        /* may have moved */
463
20.1k
    gs_unregister_root(imemory_system, r, "interp_reclaim(pi_ctx_p)");
464
20.1k
    return code;
465
20.1k
}
466
467
/*
468
 * Invoke the interpreter.  If execution completes normally, return 0.
469
 * If an error occurs, the action depends on user_errors as follows:
470
 *    user_errors < 0: always return an error code.
471
 *    user_errors >= 0: let the PostScript machinery handle all errors.
472
 *      (This will eventually result in a fatal error if no 'stopped'
473
 *      is active.)
474
 * In case of a quit or a fatal error, also store the exit code.
475
 * Set *perror_object to null or the error object.
476
 */
477
static int gs_call_interp(i_ctx_t **, ref *, int, int *, ref *);
478
int
479
gs_interpret(i_ctx_t **pi_ctx_p, ref * pref, int user_errors, int *pexit_code,
480
             ref * perror_object)
481
172k
{
482
172k
    i_ctx_t *i_ctx_p = *pi_ctx_p;
483
172k
    gs_gc_root_t error_root, *r = &error_root;
484
172k
    int code;
485
486
172k
    gs_register_ref_root(imemory_system, &r,
487
172k
                         (void **)&perror_object, "gs_interpret");
488
172k
    code = gs_call_interp(pi_ctx_p, pref, user_errors, pexit_code,
489
172k
                          perror_object);
490
172k
    i_ctx_p = *pi_ctx_p;
491
172k
    gs_unregister_root(imemory_system, &error_root, "gs_interpret");
492
    /* Avoid a dangling reference to the lib context GC signal. */
493
172k
    set_gc_signal(i_ctx_p, 0);
494
172k
    return code;
495
172k
}
496
static int
497
gs_call_interp(i_ctx_t **pi_ctx_p, ref * pref, int user_errors,
498
               int *pexit_code, ref * perror_object)
499
172k
{
500
172k
    ref *epref = pref;
501
172k
    ref doref;
502
172k
    ref *perrordict;
503
172k
    ref error_name;
504
172k
    int code, ccode;
505
172k
    ref saref;
506
172k
    i_ctx_t *i_ctx_p = *pi_ctx_p;
507
172k
    int *gc_signal = &imemory_system->gs_lib_ctx->gcsignal;
508
509
172k
    *pexit_code = 0;
510
172k
    *gc_signal = 0;
511
512
    /* This avoids a valgrind error */
513
172k
    doref.tas.type_attrs = error_name.tas.type_attrs = saref.tas.type_attrs = 0;
514
515
172k
    ialloc_reset_requested(idmemory);
516
7.04M
again:
517
    /* Avoid a dangling error object that might get traced by a future GC. */
518
7.04M
    make_null(perror_object);
519
7.04M
    o_stack.requested = e_stack.requested = d_stack.requested = 0;
520
7.04M
    while (*gc_signal) { /* Some routine below triggered a GC. */
521
0
        gs_gc_root_t epref_root, *r = &epref_root;
522
523
0
        *gc_signal = 0;
524
        /* Make sure that doref will get relocated properly if */
525
        /* a garbage collection happens with epref == &doref. */
526
0
        gs_register_ref_root(imemory_system, &r,
527
0
                             (void **)&epref, "gs_call_interp(epref)");
528
0
        code = interp_reclaim(pi_ctx_p, -1);
529
0
        i_ctx_p = *pi_ctx_p;
530
0
        gs_unregister_root(imemory_system, &epref_root,
531
0
                           "gs_call_interp(epref)");
532
0
        if (code < 0)
533
0
            return code;
534
0
    }
535
7.04M
    code = interp(pi_ctx_p, epref, perror_object);
536
7.04M
    i_ctx_p = *pi_ctx_p;
537
7.04M
    if (!r_has_type(&i_ctx_p->error_object, t__invalid)) {
538
4
        *perror_object = i_ctx_p->error_object;
539
4
        make_t(&i_ctx_p->error_object, t__invalid);
540
4
    }
541
    /* Prevent a dangling reference to the GC signal in ticks_left */
542
    /* in the frame of interp, but be prepared to do a GC if */
543
    /* an allocation in this routine asks for it. */
544
7.04M
    *gc_signal = 0;
545
7.04M
    set_gc_signal(i_ctx_p, 1);
546
7.04M
    if (esp < esbot)            /* popped guard entry */
547
25.7k
        esp = esbot;
548
7.04M
    switch (code) {
549
0
        case gs_error_Fatal:
550
0
            *pexit_code = 255;
551
0
            return code;
552
41.2k
        case gs_error_Quit:
553
41.2k
            *perror_object = osp[-1];
554
41.2k
            *pexit_code = code = osp->value.intval;
555
41.2k
            osp -= 2;
556
41.2k
            return
557
41.2k
                (code == 0 ? gs_error_Quit :
558
41.2k
                 code < 0 && code > -100 ? code : gs_error_Fatal);
559
25.7k
        case gs_error_InterpreterExit:
560
25.7k
            return 0;
561
0
        case gs_error_ExecStackUnderflow:
562
/****** WRONG -- must keep mark blocks intact ******/
563
0
            ref_stack_pop_block(&e_stack);
564
0
            doref = *perror_object;
565
0
            epref = &doref;
566
0
            goto again;
567
9.57k
        case gs_error_VMreclaim:
568
            /* Do the GC and continue. */
569
            /* We ignore the return value here, if it fails here
570
             * we'll call it again having jumped to the "again" label.
571
             * Where, assuming it fails again, we'll handle the error.
572
             */
573
9.57k
            (void)interp_reclaim(pi_ctx_p,
574
9.57k
                                  (osp->value.intval == 2 ?
575
9.57k
                                   avm_global : avm_local));
576
9.57k
            i_ctx_p = *pi_ctx_p;
577
9.57k
            make_oper(&doref, 0, zpop);
578
9.57k
            epref = &doref;
579
9.57k
            goto again;
580
105k
        case gs_error_NeedInput:
581
105k
        case gs_error_interrupt:
582
105k
            return code;
583
7.04M
    }
584
    /* Adjust osp in case of operand stack underflow */
585
6.86M
    if (osp < osbot - 1)
586
0
        osp = osbot - 1;
587
    /* We have to handle stack over/underflow specially, because */
588
    /* we might be able to recover by adding or removing a block. */
589
6.86M
    switch (code) {
590
1
        case gs_error_dictstackoverflow:
591
            /* We don't have to handle this specially: */
592
            /* The only places that could generate it */
593
            /* use check_dstack, which does a ref_stack_extend, */
594
            /* so if` we get this error, it's a real one. */
595
1
            if (osp >= ostop) {
596
0
                if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
597
0
                    return ccode;
598
0
            }
599
            /* Skip system dictionaries for CET 20-02-02 */
600
1
            ccode = copy_stack(i_ctx_p, &d_stack, min_dstack_size, &saref);
601
1
            if (ccode < 0)
602
0
                return ccode;
603
1
            ref_stack_pop_to(&d_stack, min_dstack_size);
604
1
            dict_set_top();
605
1
            *++osp = saref;
606
1
            break;
607
1
        case gs_error_dictstackunderflow:
608
1
            if (ref_stack_pop_block(&d_stack) >= 0) {
609
0
                dict_set_top();
610
0
                doref = *perror_object;
611
0
                epref = &doref;
612
0
                goto again;
613
0
            }
614
1
            break;
615
3
        case gs_error_execstackoverflow:
616
            /* We don't have to handle this specially: */
617
            /* The only places that could generate it */
618
            /* use check_estack, which does a ref_stack_extend, */
619
            /* so if we get this error, it's a real one. */
620
3
            if (osp >= ostop) {
621
0
                if ((ccode = ref_stack_extend(&o_stack, 1)) < 0)
622
0
                    return ccode;
623
0
            }
624
3
            ccode = copy_stack(i_ctx_p, &e_stack, 0, &saref);
625
3
            if (ccode < 0)
626
0
                return ccode;
627
3
            {
628
3
                uint count = ref_stack_count(&e_stack);
629
3
                uint limit = ref_stack_max_count(&e_stack) - ES_HEADROOM;
630
631
3
                if (count > limit) {
632
                    /*
633
                     * If there is an e-stack mark within MIN_BLOCK_ESTACK of
634
                     * the new top, cut the stack back to remove the mark.
635
                     */
636
3
                    int skip = count - limit;
637
3
                    int i;
638
639
16
                    for (i = skip; i < skip + MIN_BLOCK_ESTACK; ++i) {
640
16
                        const ref *ep = ref_stack_index(&e_stack, i);
641
642
16
                        if (ep == NULL)
643
0
                            continue;
644
645
16
                        if (r_has_type_attrs(ep, t_null, a_executable)) {
646
3
                            skip = i + 1;
647
3
                            break;
648
3
                        }
649
16
                    }
650
3
                    pop_estack(i_ctx_p, skip);
651
3
                }
652
3
            }
653
3
            *++osp = saref;
654
3
            break;
655
313k
        case gs_error_stackoverflow:
656
313k
            if (ref_stack_extend(&o_stack, o_stack.requested) >= 0) {   /* We can't just re-execute the object, because */
657
                /* it might be a procedure being pushed as a */
658
                /* literal.  We check for this case specially. */
659
313k
                doref = *perror_object;
660
313k
                if (r_is_proc(&doref)) {
661
2.84k
                    *++osp = doref;
662
2.84k
                    make_null_proc(&doref);
663
2.84k
                }
664
313k
                epref = &doref;
665
313k
                goto again;
666
313k
            }
667
40
            ccode = copy_stack(i_ctx_p, &o_stack, 0, &saref);
668
40
            if (ccode < 0)
669
0
                return ccode;
670
40
            ref_stack_clear(&o_stack);
671
40
            *++osp = saref;
672
40
            break;
673
4.38k
        case gs_error_stackunderflow:
674
4.38k
            if (ref_stack_pop_block(&o_stack) >= 0) {
675
4.20k
                doref = *perror_object;
676
4.20k
                epref = &doref;
677
4.20k
                goto again;
678
4.20k
            }
679
180
            break;
680
6.86M
    }
681
6.54M
    if (user_errors < 0)
682
0
        return code;
683
6.54M
    if (gs_errorname(i_ctx_p, code, &error_name) < 0)
684
0
        return code;            /* out-of-range error code! */
685
686
    /*  We refer to gserrordict first, which is not accessible to Postcript jobs
687
     *  If we're running with SAFERERRORS all the handlers are copied to gserrordict
688
     *  so we'll always find the default one. If not SAFERERRORS, only gs specific
689
     *  errors are in gserrordict.
690
     */
691
6.54M
    if ((dict_find_string(systemdict, "gserrordict", &perrordict) <= 0 ||
692
6.54M
        !r_has_type(perrordict, t_dictionary)                          ||
693
6.54M
        dict_find(perrordict, &error_name, &epref) <= 0)               &&
694
6.54M
       (dict_find_string(systemdict, "errordict", &perrordict) <= 0    ||
695
6.54M
        !r_has_type(perrordict, t_dictionary)                          ||
696
6.54M
        dict_find(perrordict, &error_name, &epref) <= 0))
697
0
        return code;            /* error name not in errordict??? */
698
699
6.54M
    if (code == gs_error_execstackoverflow
700
6.54M
        && obj_eq(imemory, &doref, epref)) {
701
        /* This strongly suggests we're in an error handler that
702
           calls itself infinitely, so Postscript is done, return
703
           to the caller.
704
         */
705
0
         ref_stack_clear(&e_stack);
706
0
         *pexit_code = gs_error_execstackoverflow;
707
0
         return_error(gs_error_execstackoverflow);
708
0
    }
709
710
6.54M
    if (!r_is_proc(epref)){
711
0
        *pexit_code = gs_error_Fatal;
712
0
        return_error(gs_error_Fatal);
713
0
    }
714
715
6.54M
    doref = *epref;
716
6.54M
    epref = &doref;
717
    /* Push the error object on the operand stack if appropriate. */
718
6.54M
    if (!GS_ERROR_IS_INTERRUPT(code)) {
719
6.54M
        byte buf[260], *bufptr;
720
6.54M
        uint rlen;
721
        /* Replace the error object if within an oparray or .errorexec. */
722
6.54M
        osp++;
723
6.54M
        if (osp >= ostop) {
724
1
            *pexit_code = gs_error_Fatal;
725
1
            return_error(gs_error_Fatal);
726
1
        }
727
6.54M
        *osp = *perror_object;
728
6.54M
        errorexec_find(i_ctx_p, osp);
729
730
6.54M
        if (!r_has_type(osp, t_string) && !r_has_type(osp, t_name)) {
731
6.43M
            code = obj_cvs(imemory, osp, buf + 2, 256, &rlen, (const byte **)&bufptr);
732
6.43M
            if (code < 0) {
733
0
                const char *unknownstr = "--unknown--";
734
0
                rlen = strlen(unknownstr);
735
0
                memcpy(buf, unknownstr, rlen);
736
0
                bufptr = buf;
737
0
            }
738
6.43M
            else {
739
6.43M
                ref *tobj;
740
6.43M
                bufptr[rlen] = '\0';
741
                /* Only pass a name object if the operator doesn't exist in systemdict
742
                 * i.e. it's an internal operator we have hidden
743
                 */
744
6.43M
                code = dict_find_string(systemdict, (const char *)bufptr, &tobj);
745
6.43M
                if (code <= 0) {
746
138k
                    buf[0] = buf[1] = buf[rlen + 2] = buf[rlen + 3] = '-';
747
138k
                    rlen += 4;
748
138k
                    bufptr = buf;
749
138k
                }
750
6.29M
                else {
751
6.29M
                    bufptr = NULL;
752
6.29M
                }
753
6.43M
            }
754
6.43M
            if (bufptr) {
755
138k
                code = name_ref(imemory, buf, rlen, osp, 1);
756
138k
                if (code < 0)
757
138k
                    make_null(osp);
758
138k
            }
759
6.43M
        }
760
6.54M
    }
761
6.54M
    goto again;
762
6.54M
}
763
static int
764
interp_exit(i_ctx_t *i_ctx_p)
765
25.7k
{
766
25.7k
    return gs_error_InterpreterExit;
767
25.7k
}
768
769
/* Only used (currently) with language switching:
770
 * allows the PS interpreter to co-exist with the
771
 * PJL interpreter.
772
 */
773
static int
774
zforceinterp_exit(i_ctx_t *i_ctx_p)
775
0
{
776
0
    os_ptr op = osp;
777
0
    stream *s;
778
779
0
    check_file(s, op);
780
0
    i_ctx_p->uel_position = stell(s)-1;
781
    /* resetfile */
782
0
    if (file_is_valid(s, op))
783
0
        sreset(s);
784
785
0
    if (!gs_lib_ctx_get_act_on_uel((gs_memory_t *)(i_ctx_p->memory.current)))
786
0
        return 0;
787
788
0
    gs_interp_reset(i_ctx_p);
789
    /* gs_interp_reset() actually leaves the op stack one entry below
790
     * the bottom of the stack, and that can cause problems depending
791
     * on the interpreter state at the end of the job.
792
     * So push a null object, and the return code before continuing.
793
     */
794
0
    push(2);
795
0
    op = osp;
796
0
    make_null(op - 1);
797
0
    make_int(op, gs_error_InterpreterExit);
798
0
    return_error(gs_error_Quit);
799
0
}
800
801
/* Set the GC signal for all VMs. */
802
static void
803
set_gc_signal(i_ctx_t *i_ctx_p, int value)
804
14.2M
{
805
14.2M
    gs_memory_gc_status_t stat;
806
14.2M
    int i;
807
808
71.2M
    for (i = 0; i < countof(idmemory->spaces_indexed); i++) {
809
57.0M
        gs_ref_memory_t *mem = idmemory->spaces_indexed[i];
810
57.0M
        gs_ref_memory_t *mem_stable;
811
812
57.0M
        if (mem == 0)
813
14.2M
            continue;
814
71.2M
        for (;; mem = mem_stable) {
815
71.2M
            mem_stable = (gs_ref_memory_t *)
816
71.2M
                gs_memory_stable((gs_memory_t *)mem);
817
71.2M
            gs_memory_gc_status(mem, &stat);
818
71.2M
            stat.signal_value = value;
819
71.2M
            gs_memory_set_gc_status(mem, &stat);
820
71.2M
            if (mem_stable == mem)
821
42.7M
                break;
822
71.2M
        }
823
42.7M
    }
824
14.2M
}
825
826
/* Create a printable string ref (or null) from an arbitrary ref.
827
 * For the purpose this is used here, it cannot fail, any
828
 * error in the process results in a null object, instead
829
 * of the string.
830
 */
831
static void obj_cvs_ref(i_ctx_t *i_ctx_p, const ref *in, ref *out)
832
0
{
833
0
    uint rlen;
834
0
    int code;
835
0
    byte sbuf[65], *buf = sbuf;
836
0
    uint len = sizeof(sbuf) - 1;
837
838
0
    code = obj_cvs(imemory, in, buf, len, &rlen, NULL);
839
0
    if (code == gs_error_rangecheck) {
840
0
        len = rlen;
841
0
        buf = gs_alloc_bytes(imemory, len + 1, "obj_cvs_ref");
842
0
        if (!buf)
843
0
            code = -1;
844
0
        else
845
0
            code = obj_cvs(imemory, in, buf, len, &rlen, NULL);
846
0
    }
847
0
    if (code < 0) {
848
0
        make_null(out);
849
0
    }
850
0
    else {
851
0
        buf[rlen] = '\0';
852
0
        code = string_to_ref((const char *)buf, out, iimemory, "obj_cvs_ref");
853
0
        if (code < 0)
854
0
            make_null(out);
855
0
    }
856
0
    if (buf != sbuf)
857
0
        gs_free_object(imemory, buf, "obj_cvs_ref");
858
0
    return;
859
0
}
860
861
/* Copy top elements of an overflowed stack into a (local) array. */
862
/* Adobe copies only 500 top elements, we copy up to 65535 top elements */
863
/* for better debugging, PLRM compliance, and backward compatibility. */
864
static int
865
copy_stack(i_ctx_t *i_ctx_p, const ref_stack_t * pstack, int skip, ref * arr)
866
44
{
867
44
    uint size = ref_stack_count(pstack) - skip;
868
44
    uint save_space = ialloc_space(idmemory);
869
44
    int code, i;
870
44
    ref *safety, *safe;
871
872
44
    if (size > 65535)
873
40
        size = 65535;
874
44
    ialloc_set_space(idmemory, avm_local);
875
44
    code = ialloc_ref_array(arr, a_all, size, "copy_stack");
876
44
    if (code >= 0)
877
44
        code = ref_stack_store(pstack, arr, size, 0, 1, true, idmemory,
878
44
                               "copy_stack");
879
    /* If we are copying the exec stack, try to replace any oparrays with
880
     * the operator that references them
881
     * We also replace any internal objects (t_struct and t_astruct) with
882
     * string representations, since these can contain references to objects
883
     * with uncertain lifespans, it is safer not to risk them persisting.
884
     * Since we basically did this later on for the error handler, it isn't
885
     * a significant speed hit.
886
     */
887
44
    if (pstack == &e_stack) {
888
14.9k
        for (i = 0; i < size; i++) {
889
14.9k
            if (errorexec_find(i_ctx_p, &arr->value.refs[i]) < 0)
890
14.9k
                make_null(&arr->value.refs[i]);
891
14.9k
            else if (r_has_type(&arr->value.refs[i], t_struct)
892
14.9k
                  || r_has_type(&arr->value.refs[i], t_astruct)) {
893
0
                ref r;
894
0
                obj_cvs_ref(i_ctx_p, (const ref *)&arr->value.refs[i], &r);
895
0
                ref_assign(&arr->value.refs[i], &r);
896
0
            }
897
14.9k
        }
898
3
    }
899
44
    if (pstack == &o_stack && dict_find_string(systemdict, "SAFETY", &safety) > 0 &&
900
44
        dict_find_string(safety, "safe", &safe) > 0 && r_has_type(safe, t_boolean) &&
901
44
        safe->value.boolval == true) {
902
0
        code = ref_stack_array_sanitize(i_ctx_p, arr, arr, 0);
903
0
        if (code < 0)
904
0
            return code;
905
0
    }
906
44
    ialloc_set_space(idmemory, save_space);
907
44
    return code;
908
44
}
909
910
/* Get the name corresponding to an error number. */
911
int
912
gs_errorname(i_ctx_t *i_ctx_p, int code, ref * perror_name)
913
6.54M
{
914
6.54M
    ref *perrordict, *pErrorNames;
915
916
6.54M
    if (dict_find_string(systemdict, "errordict", &perrordict) <= 0 ||
917
6.54M
        dict_find_string(systemdict, "ErrorNames", &pErrorNames) <= 0
918
6.54M
        )
919
0
        return_error(gs_error_undefined);      /* errordict or ErrorNames not found?! */
920
6.54M
    return array_get(imemory, pErrorNames, (long)(-code - 1), perror_name);
921
6.54M
}
922
923
/* Store an error string in $error.errorinfo. */
924
/* This routine is here because of the proximity to the error handler. */
925
int
926
gs_errorinfo_put_string(i_ctx_t *i_ctx_p, const char *str)
927
0
{
928
0
    ref rstr;
929
0
    ref *pderror;
930
0
    int code = string_to_ref(str, &rstr, iimemory, "gs_errorinfo_put_string");
931
932
0
    if (code < 0)
933
0
        return code;
934
0
    if (dict_find_string(systemdict, "$error", &pderror) <= 0 ||
935
0
        !r_has_type(pderror, t_dictionary) ||
936
0
        idict_put_string(pderror, "errorinfo", &rstr) < 0
937
0
        )
938
0
        return_error(gs_error_Fatal);
939
0
    return 0;
940
0
}
941
942
/* Main interpreter. */
943
/* If execution terminates normally, return gs_error_InterpreterExit. */
944
/* If an error occurs, leave the current object in *perror_object */
945
/* and return a (negative) error code. */
946
static int
947
interp(/* lgtm [cpp/use-of-goto] */
948
       i_ctx_t **pi_ctx_p /* context for execution, updated if resched */,
949
       const ref * pref /* object to interpret */,
950
       ref * perror_object)
951
7.04M
{
952
7.04M
    i_ctx_t *i_ctx_p = *pi_ctx_p;
953
    /*
954
     * Note that iref may actually be either a ref * or a ref_packed *.
955
     * Certain DEC compilers assume that a ref * is ref-aligned even if it
956
     * is cast to a short *, and generate code on this assumption, leading
957
     * to "unaligned access" errors.  For this reason, we declare
958
     * iref_packed, and use a macro to cast it to the more aligned type
959
     * where necessary (which is almost everywhere it is used).  This may
960
     * lead to compiler warnings about "cast increases alignment
961
     * requirements", but this is less harmful than expensive traps at run
962
     * time.
963
     */
964
7.04M
    register const ref_packed *iref_packed = (const ref_packed *)pref;
965
    /*
966
     * To make matters worse, some versions of gcc/egcs have a bug that
967
     * leads them to assume that if iref_packed is EVER cast to a ref *,
968
     * it is ALWAYS ref-aligned.  We detect this in stdpre.h and provide
969
     * the following workaround:
970
     */
971
#ifdef ALIGNMENT_ALIASING_BUG
972
    const ref *iref_temp;
973
#  define IREF (iref_temp = (const ref *)iref_packed, iref_temp)
974
#else
975
922M
#  define IREF ((const ref *)iref_packed)
976
7.04M
#endif
977
2.42G
#define SET_IREF(rp) (iref_packed = (const ref_packed *)(rp))
978
7.04M
    register int icount = 0;    /* # of consecutive tokens at iref */
979
7.04M
    register os_ptr iosp = osp; /* private copy of osp */
980
7.04M
    register es_ptr iesp = esp; /* private copy of esp */
981
7.04M
    int code;
982
7.04M
    ref token;                  /* token read from file or string, */
983
                                /* must be declared in this scope */
984
7.04M
    ref *pvalue;
985
7.04M
    ref refnull;
986
7.04M
    uint opindex;               /* needed for oparrays */
987
7.04M
    os_ptr whichp;
988
989
    /*
990
     * We have to make the error information into a struct;
991
     * otherwise, the Watcom compiler will assign it to registers
992
     * strictly on the basis of textual frequency.
993
     * We also have to use ref_assign_inline everywhere, and
994
     * avoid direct assignments of refs, so that esi and edi
995
     * will remain available on Intel processors.
996
     */
997
7.04M
    struct interp_error_s {
998
7.04M
        int code;
999
7.04M
        int line;
1000
7.04M
        const ref *obj;
1001
7.04M
        ref full;
1002
7.04M
    } ierror;
1003
1004
    /*
1005
     * Get a pointer to the name table so that we can use the
1006
     * inline version of name_index_ref.
1007
     */
1008
7.04M
    const name_table *const int_nt = imemory->gs_lib_ctx->gs_name_table;
1009
1010
7.04M
#define set_error(ecode)\
1011
7.04M
  { ierror.code = ecode; ierror.line = __LINE__; }
1012
7.04M
#define return_with_error(ecode, objp)\
1013
7.04M
  { set_error(ecode); ierror.obj = objp; goto rwe; }
1014
7.04M
#define return_with_error_iref(ecode)\
1015
7.04M
  { set_error(ecode); goto rwei; }
1016
7.04M
#define return_with_code_iref()\
1017
7.04M
  { ierror.line = __LINE__; goto rweci; }
1018
7.04M
#define return_with_stackoverflow(objp)\
1019
7.04M
  { o_stack.requested = 1; return_with_error(gs_error_stackoverflow, objp); }
1020
7.04M
#define return_with_stackoverflow_iref()\
1021
7.04M
  { o_stack.requested = 1; return_with_error_iref(gs_error_stackoverflow); }
1022
/*
1023
 * If control reaches the special operators (x_add, etc.) as a result of
1024
 * interpreting an executable name, iref points to the name, not the
1025
 * operator, so the name rather than the operator becomes the error object,
1026
 * which is wrong.  We detect and handle this case explicitly when an error
1027
 * occurs, so as not to slow down the non-error case.
1028
 */
1029
7.04M
#define return_with_error_tx_op(err_code)\
1030
7.04M
  { if (r_has_type(IREF, t_name)) {\
1031
17
        return_with_error(err_code, pvalue);\
1032
306
    } else {\
1033
306
        return_with_error_iref(err_code);\
1034
0
    }\
1035
323
  }
1036
1037
7.04M
    int *ticks_left = &imemory_system->gs_lib_ctx->gcsignal;
1038
1039
7.04M
#if defined(DEBUG_TRACE_PS_OPERATORS) || defined(DEBUG)
1040
7.04M
    int (*call_operator_fn)(op_proc_t, i_ctx_t *) = do_call_operator;
1041
1042
7.04M
    if (gs_debug_c('!'))
1043
0
        call_operator_fn = do_call_operator_verbose;
1044
7.04M
#endif
1045
1046
7.04M
    *ticks_left = i_ctx_p->time_slice_ticks;
1047
1048
7.04M
     make_null(&ierror.full);
1049
7.04M
     ierror.obj = &ierror.full;
1050
7.04M
     make_null(&refnull);
1051
7.04M
     refnull.value.intval = 0;
1052
7.04M
     pvalue = &refnull;
1053
1054
    /*
1055
     * If we exceed the VMThreshold, set *ticks_left to -100
1056
     * to alert the interpreter that we need to garbage collect.
1057
     */
1058
7.04M
    set_gc_signal(i_ctx_p, -100);
1059
1060
7.04M
    esfile_clear_cache();
1061
    /*
1062
     * From here on, if icount > 0, iref and icount correspond
1063
     * to the top entry on the execution stack: icount is the count
1064
     * of sequential entries remaining AFTER the current one.
1065
     */
1066
7.04M
#define IREF_NEXT(ip)\
1067
1.57G
  ((const ref_packed *)((const ref *)(ip) + 1))
1068
7.04M
#define IREF_NEXT_EITHER(ip)\
1069
1.12G
  ( r_is_packed(ip) ? (ip) + 1 : IREF_NEXT(ip) )
1070
7.04M
#define store_state(ep)\
1071
449M
  ( icount > 0 ? (ep->value.const_refs = IREF + 1, r_set_size(ep, icount)) : 0 )
1072
7.04M
#define store_state_short(ep)\
1073
647M
  ( icount > 0 ? (ep->value.packed = iref_packed + 1, r_set_size(ep, icount)) : 0 )
1074
7.04M
#define store_state_either(ep)\
1075
248M
  ( icount > 0 ? (ep->value.packed = IREF_NEXT_EITHER(iref_packed), r_set_size(ep, icount)) : 0 )
1076
7.04M
#define next()\
1077
1.75G
  if ( --icount > 0 ) { iref_packed = IREF_NEXT(iref_packed); goto top; } else goto out
1078
7.04M
#define next_short()\
1079
1.62G
  if ( --icount <= 0 ) { if ( icount < 0 ) goto up; iesp--; }\
1080
1.62G
  ++iref_packed; goto top
1081
7.04M
#define next_either()\
1082
1.32G
  if ( --icount <= 0 ) { if ( icount < 0 ) goto up; iesp--; }\
1083
1.32G
  iref_packed = IREF_NEXT_EITHER(iref_packed); goto top
1084
1085
#if !PACKED_SPECIAL_OPS
1086
#  undef next_either
1087
#  define next_either() next()
1088
#  undef store_state_either
1089
#  define store_state_either(ep) store_state(ep)
1090
#endif
1091
1092
    /* We want to recognize executable arrays here, */
1093
    /* so we push the argument on the estack and enter */
1094
    /* the loop at the bottom. */
1095
7.04M
    if (iesp >= estop)
1096
7.04M
        return_with_error(gs_error_execstackoverflow, pref);
1097
7.04M
    ++iesp;
1098
7.04M
    ref_assign_inline(iesp, pref);
1099
7.04M
    goto bot;
1100
6.26G
  top:
1101
        /*
1102
         * This is the top of the interpreter loop.
1103
         * iref points to the ref being interpreted.
1104
         * Note that this might be an element of a packed array,
1105
         * not a real ref: we carefully arranged the first 16 bits of
1106
         * a ref and of a packed array element so they could be distinguished
1107
         * from each other.  (See ghost.h and packed.h for more detail.)
1108
         */
1109
6.26G
    INCR(top);
1110
#ifdef DEBUG
1111
    /* Do a little validation on the top o-stack entry. */
1112
    if (iosp >= osbot &&
1113
        (r_type(iosp) == t__invalid || r_type(iosp) >= tx_next_op)
1114
        ) {
1115
        mlprintf(imemory, "Invalid value on o-stack!\n");
1116
        return_with_error_iref(gs_error_Fatal);
1117
    }
1118
    if (gs_debug['I'] ||
1119
        (gs_debug['i'] &&
1120
         (r_is_packed(iref_packed) ?
1121
          r_packed_is_name(iref_packed) :
1122
          r_has_type(IREF, t_name)))
1123
        ) {
1124
        os_ptr save_osp = osp;  /* avoid side-effects */
1125
        es_ptr save_esp = esp;
1126
1127
        osp = iosp;
1128
        esp = iesp;
1129
        dmlprintf5(imemory, "d%u,e%u<%u>"PRI_INTPTR"(%d): ",
1130
                  ref_stack_count(&d_stack), ref_stack_count(&e_stack),
1131
                  ref_stack_count(&o_stack), (intptr_t)IREF, icount);
1132
        debug_print_ref(imemory, IREF);
1133
        if (iosp >= osbot) {
1134
            dmputs(imemory, " // ");
1135
            debug_print_ref(imemory, iosp);
1136
        }
1137
        dmputc(imemory, '\n');
1138
        osp = save_osp;
1139
        esp = save_esp;
1140
        dmflush(imemory);
1141
    }
1142
#endif
1143
/* Objects that have attributes (arrays, dictionaries, files, and strings) */
1144
/* use lit and exec; other objects use plain and plain_exec. */
1145
6.26G
#define lit(t) type_xe_value(t, a_execute)
1146
6.26G
#define exec(t) type_xe_value(t, a_execute + a_executable)
1147
6.26G
#define nox(t) type_xe_value(t, 0)
1148
6.26G
#define nox_exec(t) type_xe_value(t, a_executable)
1149
6.26G
#define plain(t) type_xe_value(t, 0)
1150
6.26G
#define plain_exec(t) type_xe_value(t, a_executable)
1151
    /*
1152
     * We have to populate enough cases of the switch statement to force
1153
     * some compilers to use a dispatch rather than a testing loop.
1154
     * What a nuisance!
1155
     */
1156
6.26G
    switch (r_type_xe(iref_packed)) {
1157
            /* Access errors. */
1158
0
#define cases_invalid()\
1159
0
  case plain(t__invalid): case plain_exec(t__invalid)
1160
0
          cases_invalid():
1161
0
            return_with_error_iref(gs_error_Fatal);
1162
0
#define cases_nox()\
1163
0
  case nox_exec(t_array): case nox_exec(t_dictionary):\
1164
0
  case nox_exec(t_file): case nox_exec(t_string):\
1165
0
  case nox_exec(t_mixedarray): case nox_exec(t_shortarray)
1166
0
          cases_nox():
1167
0
            return_with_error_iref(gs_error_invalidaccess);
1168
            /*
1169
             * Literal objects.  We have to enumerate all the types.
1170
             * In fact, we have to include some extra plain_exec entries
1171
             * just to populate the switch.  We break them up into groups
1172
             * to avoid overflowing some preprocessors.
1173
             */
1174
0
#define cases_lit_1()\
1175
15.8M
  case lit(t_array): case nox(t_array):\
1176
74.2M
  case plain(t_boolean): case plain_exec(t_boolean):\
1177
116M
  case lit(t_dictionary): case nox(t_dictionary)
1178
0
#define cases_lit_2()\
1179
116M
  case lit(t_file): case nox(t_file):\
1180
116M
  case plain(t_fontID): case plain_exec(t_fontID):\
1181
211M
  case plain(t_integer): case plain_exec(t_integer):\
1182
211M
  case plain(t_mark): case plain_exec(t_mark)
1183
0
#define cases_lit_3()\
1184
323M
  case plain(t_name):\
1185
362M
  case plain(t_null):\
1186
362M
  case plain(t_oparray):\
1187
362M
  case plain(t_operator)
1188
0
#define cases_lit_4()\
1189
389M
  case plain(t_real): case plain_exec(t_real):\
1190
389M
  case plain(t_save): case plain_exec(t_save):\
1191
428M
  case lit(t_string): case nox(t_string)
1192
0
#define cases_lit_5()\
1193
533M
  case lit(t_mixedarray): case nox(t_mixedarray):\
1194
533M
  case lit(t_shortarray): case nox(t_shortarray):\
1195
533M
  case plain(t_device): case plain_exec(t_device):\
1196
533M
  case plain(t_struct): case plain_exec(t_struct):\
1197
533M
  case plain(t_astruct): case plain_exec(t_astruct):\
1198
533M
  case plain(t_pdfctx): case plain_exec(t_pdfctx)
1199
            /* Executable arrays are treated as literals in direct execution. */
1200
0
#define cases_lit_array()\
1201
702M
  case exec(t_array): case exec(t_mixedarray): case exec(t_shortarray)
1202
359M
          cases_lit_1():
1203
1.11G
          cases_lit_2():
1204
1.30G
          cases_lit_3():
1205
2.22G
          cases_lit_4():
1206
2.22G
          cases_lit_5():
1207
502M
            INCR(lit);
1208
502M
            break;
1209
702M
          cases_lit_array():
1210
702M
            INCR(lit_array);
1211
702M
            break;
1212
            /* Special operators. */
1213
15.2M
        case plain_exec(tx_op_add):
1214
43.1M
x_add:      INCR(x_add);
1215
43.1M
            osp = iosp; /* sync o_stack */
1216
43.1M
            if ((code = zop_add(i_ctx_p)) < 0)
1217
43.1M
                return_with_error_tx_op(code);
1218
43.1M
            iosp--;
1219
43.1M
            next_either();
1220
1.91M
        case plain_exec(tx_op_def):
1221
18.0M
x_def:      INCR(x_def);
1222
18.0M
            osp = iosp; /* sync o_stack */
1223
18.0M
            if ((code = zop_def(i_ctx_p)) < 0)
1224
18.0M
                return_with_error_tx_op(code);
1225
18.0M
            iosp -= 2;
1226
18.0M
            next_either();
1227
30.6M
        case plain_exec(tx_op_dup):
1228
322M
x_dup:      INCR(x_dup);
1229
322M
            if (iosp < osbot)
1230
322M
                return_with_error_tx_op(gs_error_stackunderflow);
1231
322M
            if (iosp >= ostop) {
1232
0
                o_stack.requested = 1;
1233
0
                return_with_error_tx_op(gs_error_stackoverflow);
1234
0
            }
1235
322M
            iosp++;
1236
322M
            ref_assign_inline(iosp, iosp - 1);
1237
322M
            next_either();
1238
57.0M
        case plain_exec(tx_op_exch):
1239
237M
x_exch:     INCR(x_exch);
1240
237M
            if (iosp <= osbot)
1241
237M
                return_with_error_tx_op(gs_error_stackunderflow);
1242
237M
            ref_assign_inline(&token, iosp);
1243
237M
            ref_assign_inline(iosp, iosp - 1);
1244
237M
            ref_assign_inline(iosp - 1, &token);
1245
237M
            next_either();
1246
52.5M
        case plain_exec(tx_op_if):
1247
166M
x_if:       INCR(x_if);
1248
166M
            if (!r_is_proc(iosp))
1249
166M
                return_with_error_tx_op(check_proc_failed(iosp));
1250
166M
            if (!r_has_type(iosp - 1, t_boolean))
1251
1
                return_with_error_tx_op((iosp <= osbot ?
1252
166M
                                        gs_error_stackunderflow : gs_error_typecheck));
1253
166M
            if (!iosp[-1].value.boolval) {
1254
130M
                iosp -= 2;
1255
130M
                next_either();
1256
130M
            }
1257
36.4M
            if (iesp >= estop)
1258
36.4M
                return_with_error_tx_op(gs_error_execstackoverflow);
1259
36.4M
            store_state_either(iesp);
1260
36.4M
            whichp = iosp;
1261
36.4M
            iosp -= 2;
1262
36.4M
            goto ifup;
1263
42.5M
        case plain_exec(tx_op_ifelse):
1264
211M
x_ifelse:   INCR(x_ifelse);
1265
211M
            if (!r_is_proc(iosp))
1266
211M
                return_with_error_tx_op(check_proc_failed(iosp));
1267
211M
            if (!r_is_proc(iosp - 1))
1268
211M
                return_with_error_tx_op(check_proc_failed(iosp - 1));
1269
211M
            if (!r_has_type(iosp - 2, t_boolean))
1270
0
                return_with_error_tx_op((iosp < osbot + 2 ?
1271
211M
                                        gs_error_stackunderflow : gs_error_typecheck));
1272
211M
            if (iesp >= estop)
1273
211M
                return_with_error_tx_op(gs_error_execstackoverflow);
1274
211M
            store_state_either(iesp);
1275
211M
            whichp = (iosp[-2].value.boolval ? iosp - 1 : iosp);
1276
211M
            iosp -= 3;
1277
            /* Open code "up" for the array case(s) */
1278
248M
          ifup:if ((icount = r_size(whichp) - 1) <= 0) {
1279
73.7M
                if (icount < 0)
1280
0
                    goto up;    /* 0-element proc */
1281
73.7M
                SET_IREF(whichp->value.refs);   /* 1-element proc */
1282
73.7M
                if (--(*ticks_left) > 0)
1283
73.7M
                    goto top;
1284
73.7M
            }
1285
174M
            ++iesp;
1286
            /* Do a ref_assign, but also set iref. */
1287
174M
            iesp->tas = whichp->tas;
1288
174M
            SET_IREF(iesp->value.refs = whichp->value.refs);
1289
174M
            if (--(*ticks_left) > 0)
1290
174M
                goto top;
1291
24.4k
            goto slice;
1292
6.33M
        case plain_exec(tx_op_index):
1293
166M
x_index:    INCR(x_index);
1294
166M
            osp = iosp; /* zindex references o_stack */
1295
166M
            if ((code = zindex(i_ctx_p)) < 0)
1296
166M
                return_with_error_tx_op(code);
1297
166M
            next_either();
1298
77.9M
        case plain_exec(tx_op_pop):
1299
288M
x_pop:      INCR(x_pop);
1300
288M
            if (iosp < osbot)
1301
288M
                return_with_error_tx_op(gs_error_stackunderflow);
1302
288M
            iosp--;
1303
288M
            next_either();
1304
25.5M
        case plain_exec(tx_op_roll):
1305
112M
x_roll:     INCR(x_roll);
1306
112M
            osp = iosp; /* zroll references o_stack */
1307
112M
            if ((code = zroll(i_ctx_p)) < 0)
1308
112M
                return_with_error_tx_op(code);
1309
112M
            iosp -= 2;
1310
112M
            next_either();
1311
5.11M
        case plain_exec(tx_op_sub):
1312
8.63M
x_sub:      INCR(x_sub);
1313
8.63M
            osp = iosp; /* sync o_stack */
1314
8.63M
            if ((code = zop_sub(i_ctx_p)) < 0)
1315
8.63M
                return_with_error_tx_op(code);
1316
8.63M
            iosp--;
1317
8.63M
            next_either();
1318
            /* Executable types. */
1319
629k
        case plain_exec(t_null):
1320
629k
            goto bot;
1321
37.9M
        case plain_exec(t_oparray):
1322
            /* Replace with the definition and go again. */
1323
37.9M
            INCR(exec_array);
1324
37.9M
            opindex = op_index(IREF);
1325
37.9M
            pvalue = (ref *)IREF->value.const_refs;
1326
85.1M
          opst:         /* Prepare to call a t_oparray procedure in *pvalue. */
1327
85.1M
            store_state(iesp);
1328
195M
          oppr:         /* Record the stack depths in case of failure. */
1329
195M
            if (iesp >= estop - 4)
1330
195M
                return_with_error_iref(gs_error_execstackoverflow);
1331
195M
            iesp += 5;
1332
195M
            osp = iosp;         /* ref_stack_count_inline needs this */
1333
195M
            make_mark_estack(iesp - 4, es_other, oparray_cleanup);
1334
195M
            make_int(iesp - 3, opindex); /* for .errorexec effect */
1335
195M
            make_int(iesp - 2, ref_stack_count_inline(&o_stack));
1336
195M
            make_int(iesp - 1, ref_stack_count_inline(&d_stack));
1337
195M
            make_op_estack(iesp, oparray_pop);
1338
195M
            goto pr;
1339
30.4M
          prst:         /* Prepare to call the procedure (array) in *pvalue. */
1340
30.4M
            store_state(iesp);
1341
256M
          pr:                   /* Call the array in *pvalue.  State has been stored. */
1342
            /* We want to do this check before assigning icount so icount is correct
1343
             * in the event of a gs_error_execstackoverflow
1344
             */
1345
256M
            if (iesp >= estop) {
1346
0
                return_with_error_iref(gs_error_execstackoverflow);
1347
0
            }
1348
256M
            if ((icount = r_size(pvalue) - 1) <= 0) {
1349
4.08M
                if (icount < 0)
1350
14.3k
                    goto up;    /* 0-element proc */
1351
4.06M
                SET_IREF(pvalue->value.refs);   /* 1-element proc */
1352
4.06M
                if (--(*ticks_left) > 0)
1353
4.06M
                    goto top;
1354
4.06M
            }
1355
251M
            ++iesp;
1356
            /* Do a ref_assign, but also set iref. */
1357
251M
            iesp->tas = pvalue->tas;
1358
251M
            SET_IREF(iesp->value.refs = pvalue->value.refs);
1359
251M
            if (--(*ticks_left) > 0)
1360
251M
                goto top;
1361
1.24k
            goto slice;
1362
842M
        case plain_exec(t_operator):
1363
842M
            INCR(exec_operator);
1364
842M
            if (--(*ticks_left) <= 0) {    /* The following doesn't work, */
1365
                /* and I can't figure out why. */
1366
/****** goto sst; ******/
1367
21.3k
            }
1368
842M
            esp = iesp;         /* save for operator */
1369
842M
            osp = iosp;         /* ditto */
1370
            /* Operator routines take osp as an argument. */
1371
            /* This is just a convenience, since they adjust */
1372
            /* osp themselves to reflect the results. */
1373
            /* Operators that (net) push information on the */
1374
            /* operand stack must check for overflow: */
1375
            /* this normally happens automatically through */
1376
            /* the push macro (in oper.h). */
1377
            /* Operators that do not typecheck their operands, */
1378
            /* or take a variable number of arguments, */
1379
            /* must check explicitly for stack underflow. */
1380
            /* (See oper.h for more detail.) */
1381
            /* Note that each case must set iosp = osp: */
1382
            /* this is so we can switch on code without having to */
1383
            /* store it and reload it (for dumb compilers). */
1384
842M
            switch (code = call_operator(real_opproc(IREF), i_ctx_p)) {
1385
419M
                case 0: /* normal case */
1386
421M
                case 1: /* alternative success case */
1387
421M
                    iosp = osp;
1388
421M
                    next();
1389
205M
                case o_push_estack:     /* store the state and go to up */
1390
205M
                    store_state(iesp);
1391
302M
                  opush:iosp = osp;
1392
302M
                    iesp = esp;
1393
302M
                    if (--(*ticks_left) > 0)
1394
302M
                        goto up;
1395
10.6k
                    goto slice;
1396
215M
                case o_pop_estack:      /* just go to up */
1397
216M
                  opop:iosp = osp;
1398
216M
                    if (esp == iesp)
1399
319k
                        goto bot;
1400
215M
                    iesp = esp;
1401
215M
                    goto up;
1402
0
                case gs_error_Remap_Color:
1403
0
oe_remap:           store_state(iesp);
1404
0
remap:              if (iesp + 2 >= estop) {
1405
0
                        esp = iesp;
1406
0
                        code = ref_stack_extend(&e_stack, 2);
1407
0
                        if (code < 0)
1408
0
                            return_with_error_iref(code);
1409
0
                        iesp = esp;
1410
0
                    }
1411
0
                    packed_get(imemory, iref_packed, iesp + 1);
1412
0
                    make_oper(iesp + 2, 0,
1413
0
                              r_ptr(&istate->remap_color_info,
1414
0
                                    int_remap_color_info_t)->proc);
1415
0
                    iesp += 2;
1416
0
                    goto up;
1417
842M
            }
1418
321k
            iosp = osp;
1419
321k
            iesp = esp;
1420
321k
            return_with_code_iref();
1421
223M
        case plain_exec(t_name):
1422
223M
            INCR(exec_name);
1423
223M
            pvalue = IREF->value.pname->pvalue;
1424
223M
            if (!pv_valid(pvalue)) {
1425
209M
                uint nidx = names_index(int_nt, IREF);
1426
209M
                uint htemp = 0;
1427
1428
209M
                INCR(find_name);
1429
209M
                if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0)
1430
209M
                    return_with_error_iref(gs_error_undefined);
1431
209M
            }
1432
            /* Dispatch on the type of the value. */
1433
            /* Again, we have to over-populate the switch. */
1434
223M
            switch (r_type_xe(pvalue)) {
1435
0
                  cases_invalid():
1436
0
                    return_with_error_iref(gs_error_Fatal);
1437
0
                  cases_nox():  /* access errors */
1438
0
                    return_with_error_iref(gs_error_invalidaccess);
1439
52.7M
                  cases_lit_1():
1440
193M
                  cases_lit_2():
1441
193M
                  cases_lit_3():
1442
184M
                  cases_lit_4():
1443
370M
                  cases_lit_5():
1444
370M
                      INCR(name_lit);
1445
                    /* Just push the value */
1446
370M
                    if (iosp >= ostop)
1447
30.8M
                        return_with_stackoverflow(pvalue);
1448
30.8M
                    ++iosp;
1449
30.8M
                    ref_assign_inline(iosp, pvalue);
1450
30.8M
                    next();
1451
6.74M
                case exec(t_array):
1452
27.0M
                case exec(t_mixedarray):
1453
30.4M
                case exec(t_shortarray):
1454
30.4M
                    INCR(name_proc);
1455
                    /* This is an executable procedure, execute it. */
1456
30.4M
                    goto prst;
1457
982k
                case plain_exec(tx_op_add):
1458
982k
                    goto x_add;
1459
12.3M
                case plain_exec(tx_op_def):
1460
12.3M
                    goto x_def;
1461
1.63M
                case plain_exec(tx_op_dup):
1462
1.63M
                    goto x_dup;
1463
3.25M
                case plain_exec(tx_op_exch):
1464
3.25M
                    goto x_exch;
1465
1.38M
                case plain_exec(tx_op_if):
1466
1.38M
                    goto x_if;
1467
611k
                case plain_exec(tx_op_ifelse):
1468
611k
                    goto x_ifelse;
1469
491k
                case plain_exec(tx_op_index):
1470
491k
                    goto x_index;
1471
2.48M
                case plain_exec(tx_op_pop):
1472
2.48M
                    goto x_pop;
1473
403k
                case plain_exec(tx_op_roll):
1474
403k
                    goto x_roll;
1475
433k
                case plain_exec(tx_op_sub):
1476
433k
                    goto x_sub;
1477
0
                case plain_exec(t_null):
1478
0
                    goto bot;
1479
47.2M
                case plain_exec(t_oparray):
1480
47.2M
                    INCR(name_oparray);
1481
47.2M
                    opindex = op_index(pvalue);
1482
47.2M
                    pvalue = (ref *)pvalue->value.const_refs;
1483
47.2M
                    goto opst;
1484
90.5M
                case plain_exec(t_operator):
1485
90.5M
                    INCR(name_operator);
1486
90.5M
                    {           /* Shortcut for operators. */
1487
                        /* See above for the logic. */
1488
90.5M
                        if (--(*ticks_left) <= 0) {        /* The following doesn't work, */
1489
                            /* and I can't figure out why. */
1490
/****** goto sst; ******/
1491
1.03k
                        }
1492
90.5M
                        esp = iesp;
1493
90.5M
                        osp = iosp;
1494
90.5M
                        switch (code = call_operator(real_opproc(pvalue),
1495
90.5M
                                                     i_ctx_p)
1496
90.5M
                                ) {
1497
85.7M
                            case 0:     /* normal case */
1498
86.5M
                            case 1:     /* alternative success case */
1499
86.5M
                                iosp = osp;
1500
86.5M
                                next();
1501
3.69M
                            case o_push_estack:
1502
3.69M
                                store_state(iesp);
1503
3.69M
                                goto opush;
1504
238k
                            case o_pop_estack:
1505
238k
                                goto opop;
1506
0
                            case gs_error_Remap_Color:
1507
0
                                goto oe_remap;
1508
90.5M
                        }
1509
10.0k
                        iosp = osp;
1510
10.0k
                        iesp = esp;
1511
10.0k
                        return_with_error(code, pvalue);
1512
0
                    }
1513
0
                case plain_exec(t_name):
1514
0
                case exec(t_file):
1515
0
                case exec(t_string):
1516
42.2k
                default:
1517
                    /* Not a procedure, reinterpret it. */
1518
42.2k
                    store_state(iesp);
1519
42.2k
                    icount = 0;
1520
42.2k
                    SET_IREF(pvalue);
1521
42.2k
                    goto top;
1522
223M
            }
1523
124M
        case exec(t_file):
1524
124M
            {   /* Executable file.  Read the next token and interpret it. */
1525
124M
                stream *s;
1526
124M
                scanner_state sstate;
1527
1528
124M
                check_read_known_file(i_ctx_p, s, IREF, return_with_error_iref);
1529
351M
            rt:
1530
351M
                if (iosp >= ostop)      /* check early */
1531
350M
                    return_with_stackoverflow_iref();
1532
350M
                osp = iosp;     /* gs_scan_token uses ostack */
1533
350M
                gs_scanner_init_options(&sstate, IREF, i_ctx_p->scanner_options);
1534
350M
            again:
1535
350M
                code = gs_scan_token(i_ctx_p, &token, &sstate);
1536
350M
                iosp = osp;     /* ditto */
1537
350M
                switch (code) {
1538
350M
                    case 0:     /* read a token */
1539
                        /* It's worth checking for literals, which make up */
1540
                        /* the majority of input tokens, before storing the */
1541
                        /* state on the e-stack.  Note that because of //, */
1542
                        /* the token may have *any* type and attributes. */
1543
                        /* Note also that executable arrays aren't executed */
1544
                        /* at the top level -- they're treated as literals. */
1545
350M
                        if (!r_has_attr(&token, a_executable) ||
1546
350M
                            r_is_array(&token)
1547
350M
                            ) { /* If gs_scan_token used the o-stack, */
1548
                            /* we know we can do a push now; if not, */
1549
                            /* the pre-check is still valid. */
1550
226M
                            iosp++;
1551
226M
                            ref_assign_inline(iosp, &token);
1552
                            /* With a construct like /f currentfile def //f we can
1553
                               end up here with IREF == &token which can go badly wrong,
1554
                               so find the current file we're interpeting on the estack
1555
                               and have IREF point to that ref, rather than "token"
1556
                             */
1557
226M
                            if (IREF == &token) {
1558
0
                                ref *st;
1559
0
                                int code2 = z_current_file(i_ctx_p, &st);
1560
0
                                if (code2 < 0 || st == NULL) {
1561
0
                                    ierror.code = gs_error_Fatal;
1562
0
                                    goto rweci;
1563
0
                                }
1564
0
                                SET_IREF(st);
1565
0
                            }
1566
226M
                            goto rt;
1567
226M
                        }
1568
123M
                        store_state(iesp);
1569
                        /* Push the file on the e-stack */
1570
123M
                        if (iesp >= estop)
1571
123M
                            return_with_error_iref(gs_error_execstackoverflow);
1572
123M
                        esfile_set_cache(++iesp);
1573
123M
                        ref_assign_inline(iesp, IREF);
1574
123M
                        SET_IREF(&token);
1575
123M
                        icount = 0;
1576
123M
                        goto top;
1577
20
                    case gs_error_undefined:   /* //name undefined */
1578
20
                        gs_scanner_error_object(i_ctx_p, &sstate, &token);
1579
20
                        return_with_error(code, &token);
1580
78.3k
                    case scan_EOF:      /* end of file */
1581
78.3k
                        esfile_clear_cache();
1582
78.3k
                        goto bot;
1583
2.12k
                    case scan_BOS:
1584
                        /* Binary object sequences */
1585
                        /* ARE executed at the top level. */
1586
2.12k
                        store_state(iesp);
1587
                        /* Push the file on the e-stack */
1588
2.12k
                        if (iesp >= estop)
1589
2.12k
                            return_with_error_iref(gs_error_execstackoverflow);
1590
2.12k
                        esfile_set_cache(++iesp);
1591
2.12k
                        ref_assign_inline(iesp, IREF);
1592
2.12k
                        pvalue = &token;
1593
2.12k
                        goto pr;
1594
137k
                    case scan_Refill:
1595
137k
                        store_state(iesp);
1596
                        /* iref may point into the exec stack; */
1597
                        /* save its referent now. */
1598
137k
                        ref_assign_inline(&token, IREF);
1599
                        /* Push the file on the e-stack */
1600
137k
                        if (iesp >= estop)
1601
137k
                            return_with_error_iref(gs_error_execstackoverflow);
1602
137k
                        ++iesp;
1603
137k
                        ref_assign_inline(iesp, &token);
1604
137k
                        esp = iesp;
1605
137k
                        osp = iosp;
1606
137k
                        code = gs_scan_handle_refill(i_ctx_p, &sstate, true,
1607
137k
                                                     ztokenexec_continue);
1608
141k
                scan_cont:
1609
141k
                        iosp = osp;
1610
141k
                        iesp = esp;
1611
141k
                        switch (code) {
1612
41.2k
                            case 0:
1613
41.2k
                                iesp--;         /* don't push the file */
1614
41.2k
                                goto again;     /* stacks are unchanged */
1615
100k
                            case o_push_estack:
1616
100k
                                esfile_clear_cache();
1617
100k
                                if (--(*ticks_left) > 0)
1618
100k
                                    goto up;
1619
4
                                goto slice;
1620
141k
                        }
1621
                        /* must be an error */
1622
80
                        iesp--; /* don't push the file */
1623
80
                        return_with_code_iref();
1624
0
                    case scan_Comment:
1625
4.37k
                    case scan_DSC_Comment: {
1626
                        /* See scan_Refill above for comments. */
1627
4.37k
                        ref file_token;
1628
1629
4.37k
                        store_state(iesp);
1630
4.37k
                        ref_assign_inline(&file_token, IREF);
1631
4.37k
                        if (iesp >= estop)
1632
4.37k
                            return_with_error_iref(gs_error_execstackoverflow);
1633
4.37k
                        ++iesp;
1634
4.37k
                        ref_assign_inline(iesp, &file_token);
1635
4.37k
                        esp = iesp;
1636
4.37k
                        osp = iosp;
1637
4.37k
                        code = ztoken_handle_comment(i_ctx_p,
1638
4.37k
                                                     &sstate, &token,
1639
4.37k
                                                     code, true, true,
1640
4.37k
                                                     ztokenexec_continue);
1641
4.37k
                    }
1642
0
                        goto scan_cont;
1643
1.23k
                    default:    /* error */
1644
1.23k
                        ref_assign_inline(&token, IREF);
1645
1.23k
                        gs_scanner_error_object(i_ctx_p, &sstate, &token);
1646
1.23k
                        return_with_error(code, &token);
1647
350M
                }
1648
350M
            }
1649
57.4k
        case exec(t_string):
1650
57.4k
            {                   /* Executable string.  Read a token and interpret it. */
1651
57.4k
                stream ss;
1652
57.4k
                scanner_state sstate;
1653
1654
57.4k
                s_init(&ss, NULL);
1655
57.4k
                sread_string(&ss, IREF->value.bytes, r_size(IREF));
1656
57.4k
                gs_scanner_init_stream_options(&sstate, &ss, SCAN_FROM_STRING);
1657
57.4k
                osp = iosp;     /* gs_scan_token uses ostack */
1658
57.4k
                code = gs_scan_token(i_ctx_p, &token, &sstate);
1659
57.4k
                iosp = osp;     /* ditto */
1660
57.4k
                switch (code) {
1661
57.4k
                    case 0:     /* read a token */
1662
57.4k
                    case scan_BOS:      /* binary object sequence */
1663
57.4k
                        store_state(iesp);
1664
                        /* If the updated string isn't empty, push it back */
1665
                        /* on the e-stack. */
1666
57.4k
                        {
1667
                            /* This is just the available buffer size, so
1668
                               a signed int is plenty big
1669
                             */
1670
57.4k
                            int size = sbufavailable(&ss);
1671
1672
57.4k
                            if (size > 0) {
1673
0
                                if (iesp >= estop)
1674
0
                                    return_with_error_iref(gs_error_execstackoverflow);
1675
0
                                ++iesp;
1676
0
                                iesp->tas.type_attrs = IREF->tas.type_attrs;
1677
0
                                iesp->value.const_bytes = sbufptr(&ss);
1678
0
                                r_set_size(iesp, size);
1679
0
                            }
1680
57.4k
                        }
1681
57.4k
                        if (code == 0) {
1682
57.4k
                            SET_IREF(&token);
1683
57.4k
                            icount = 0;
1684
57.4k
                            goto top;
1685
57.4k
                        }
1686
                        /* Handle BOS specially */
1687
0
                        pvalue = &token;
1688
0
                        goto pr;
1689
0
                    case scan_EOF:      /* end of string */
1690
0
                        goto bot;
1691
0
                    case scan_Refill:   /* error */
1692
0
                        code = gs_note_error(gs_error_syntaxerror);
1693
                        /* fall through */
1694
0
                    default:    /* error */
1695
0
                        ref_assign_inline(&token, IREF);
1696
0
                        gs_scanner_error_object(i_ctx_p, &sstate, &token);
1697
0
                        return_with_error(code, &token);
1698
57.4k
                }
1699
57.4k
            }
1700
            /* Handle packed arrays here by re-dispatching. */
1701
            /* This also picks up some anomalous cases of non-packed arrays. */
1702
3.52G
        default:
1703
3.52G
            {
1704
3.52G
                uint index;
1705
1706
3.52G
                switch (*iref_packed >> r_packed_type_shift) {
1707
42.2k
                    case pt_full_ref:
1708
42.2k
                    case pt_full_ref + 1:
1709
42.2k
                        INCR(p_full);
1710
42.2k
                        if (iosp >= ostop)
1711
42.2k
                            return_with_stackoverflow_iref();
1712
                        /* We know this can't be an executable object */
1713
                        /* requiring special handling, so we just push it. */
1714
42.2k
                        ++iosp;
1715
                        /* We know that refs are properly aligned: */
1716
                        /* see packed.h for details. */
1717
42.2k
                        ref_assign_inline(iosp, IREF);
1718
42.2k
                        next();
1719
2.30G
                    case pt_executable_operator:
1720
2.30G
                        index = *iref_packed & packed_value_mask;
1721
2.30G
                        if (--(*ticks_left) <= 0) {        /* The following doesn't work, */
1722
                            /* and I can't figure out why. */
1723
/****** goto sst_short; ******/
1724
104k
                        }
1725
2.30G
                        if (!op_index_is_operator(index)) {
1726
110M
                            INCR(p_exec_oparray);
1727
110M
                            store_state_short(iesp);
1728
110M
                            opindex = index;
1729
                            /* Call the operator procedure. */
1730
110M
                            index -= op_def_count;
1731
110M
                            pvalue = (ref *)
1732
110M
                                (index < r_size(&i_ctx_p->op_array_table_global.table) ?
1733
110M
                                 i_ctx_p->op_array_table_global.table.value.const_refs +
1734
110M
                                 index :
1735
110M
                                 i_ctx_p->op_array_table_local.table.value.const_refs +
1736
0
                                 (index - r_size(&i_ctx_p->op_array_table_global.table)));
1737
110M
                            goto oppr;
1738
110M
                        }
1739
2.30G
                        INCR(p_exec_operator);
1740
                        /* See the main plain_exec(t_operator) case */
1741
                        /* for details of what happens here. */
1742
2.19G
#if PACKED_SPECIAL_OPS
1743
                        /*
1744
                         * We arranged in iinit.c that the special ops
1745
                         * have operator indices starting at 1.
1746
                         *
1747
                         * The (int) cast in the next line is required
1748
                         * because some compilers don't allow arithmetic
1749
                         * involving two different enumerated types.
1750
                         */
1751
2.19G
#  define case_xop(xop) case xop - (int)tx_op + 1
1752
2.19G
                        switch (index) {
1753
26.9M
                              case_xop(tx_op_add):goto x_add;
1754
3.77M
                              case_xop(tx_op_def):goto x_def;
1755
289M
                              case_xop(tx_op_dup):goto x_dup;
1756
177M
                              case_xop(tx_op_exch):goto x_exch;
1757
112M
                              case_xop(tx_op_if):goto x_if;
1758
168M
                              case_xop(tx_op_ifelse):goto x_ifelse;
1759
159M
                              case_xop(tx_op_index):goto x_index;
1760
207M
                              case_xop(tx_op_pop):goto x_pop;
1761
86.5M
                              case_xop(tx_op_roll):goto x_roll;
1762
3.08M
                              case_xop(tx_op_sub):goto x_sub;
1763
0
                            case 0:     /* for dumb compilers */
1764
959M
                            default:
1765
959M
                                ;
1766
2.19G
                        }
1767
959M
#  undef case_xop
1768
959M
#endif
1769
2.19G
                        INCR(p_exec_non_x_operator);
1770
959M
                        esp = iesp;
1771
959M
                        osp = iosp;
1772
959M
                        switch (code = call_operator(op_index_proc(index), i_ctx_p)) {
1773
851M
                            case 0:
1774
851M
                            case 1:
1775
851M
                                iosp = osp;
1776
851M
                                next_short();
1777
93.2M
                            case o_push_estack:
1778
93.2M
                                store_state_short(iesp);
1779
93.2M
                                goto opush;
1780
8.30M
                            case o_pop_estack:
1781
8.30M
                                iosp = osp;
1782
8.30M
                                if (esp == iesp) {
1783
369k
                                    next_short();
1784
369k
                                }
1785
7.93M
                                iesp = esp;
1786
7.93M
                                goto up;
1787
0
                            case gs_error_Remap_Color:
1788
0
                                store_state_short(iesp);
1789
0
                                goto remap;
1790
959M
                        }
1791
6.39M
                        iosp = osp;
1792
6.39M
                        iesp = esp;
1793
6.39M
                        return_with_code_iref();
1794
622M
                    case pt_integer:
1795
622M
                        INCR(p_integer);
1796
622M
                        if (iosp >= ostop)
1797
622M
                            return_with_stackoverflow_iref();
1798
622M
                        ++iosp;
1799
622M
                        make_int(iosp,
1800
622M
                                 ((int)*iref_packed & packed_int_mask) +
1801
622M
                                 packed_min_intval);
1802
622M
                        next_short();
1803
130M
                    case pt_literal_name:
1804
130M
                        INCR(p_lit_name);
1805
130M
                        {
1806
130M
                            uint nidx = *iref_packed & packed_value_mask;
1807
1808
130M
                            if (iosp >= ostop)
1809
130M
                                return_with_stackoverflow_iref();
1810
130M
                            ++iosp;
1811
130M
                            name_index_ref_inline(int_nt, nidx, iosp);
1812
130M
                            next_short();
1813
130M
                        }
1814
461M
                    case pt_executable_name:
1815
461M
                        INCR(p_exec_name);
1816
461M
                        {
1817
461M
                            uint nidx = *iref_packed & packed_value_mask;
1818
1819
461M
                            pvalue = name_index_ptr_inline(int_nt, nidx)->pvalue;
1820
461M
                            if (!pv_valid(pvalue)) {
1821
439M
                                uint htemp = 0;
1822
1823
439M
                                INCR(p_find_name);
1824
439M
                                if ((pvalue = dict_find_name_by_index_inline(nidx, htemp)) == 0) {
1825
0
                                    names_index_ref(int_nt, nidx, &token);
1826
0
                                    return_with_error(gs_error_undefined, &token);
1827
0
                                }
1828
439M
                            }
1829
461M
                            if (r_has_masked_attrs(pvalue, a_execute, a_execute + a_executable)) {      /* Literal, push it. */
1830
23.3M
                                INCR(p_name_lit);
1831
23.3M
                                if (iosp >= ostop)
1832
23.3M
                                    return_with_stackoverflow_iref();
1833
23.3M
                                ++iosp;
1834
23.3M
                                ref_assign_inline(iosp, pvalue);
1835
23.3M
                                next_short();
1836
23.3M
                            }
1837
437M
                            if (r_is_proc(pvalue)) {    /* This is an executable procedure, */
1838
                                /* execute it. */
1839
30.0M
                                INCR(p_name_proc);
1840
30.0M
                                store_state_short(iesp);
1841
30.0M
                                goto pr;
1842
30.0M
                            }
1843
                            /* Not a literal or procedure, reinterpret it. */
1844
407M
                            store_state_short(iesp);
1845
407M
                            icount = 0;
1846
407M
                            SET_IREF(pvalue);
1847
407M
                            goto top;
1848
437M
                        }
1849
                        /* default can't happen here */
1850
3.52G
                }
1851
3.52G
            }
1852
6.26G
    }
1853
    /* Literal type, just push it. */
1854
1.20G
    if (iosp >= ostop)
1855
1.20G
        return_with_stackoverflow_iref();
1856
1.20G
    ++iosp;
1857
1.20G
    ref_assign_inline(iosp, IREF);
1858
1.21G
  bot:next();
1859
684M
  out:                          /* At most 1 more token in the current procedure. */
1860
    /* (We already decremented icount.) */
1861
684M
    if (!icount) {
1862
        /* Pop the execution stack for tail recursion. */
1863
340M
        iesp--;
1864
340M
        iref_packed = IREF_NEXT(iref_packed);
1865
340M
        goto top;
1866
340M
    }
1867
1.37G
  up:if (--(*ticks_left) < 0)
1868
11.7k
        goto slice;
1869
    /* See if there is anything left on the execution stack. */
1870
1.37G
    if (!r_is_proc(iesp)) {
1871
512M
        SET_IREF(iesp--);
1872
512M
        icount = 0;
1873
512M
        goto top;
1874
512M
    }
1875
866M
    SET_IREF(iesp->value.refs); /* next element of array */
1876
866M
    icount = r_size(iesp) - 1;
1877
866M
    if (icount <= 0) {          /* <= 1 more elements */
1878
144M
        iesp--;                 /* pop, or tail recursion */
1879
144M
        if (icount < 0)
1880
3.54M
            goto up;
1881
144M
    }
1882
863M
    goto top;
1883
863M
  sched:                        /* We've just called a scheduling procedure. */
1884
    /* The interpreter state is in memory; iref is not current. */
1885
48.1k
    if (code < 0) {
1886
0
        set_error(code);
1887
        /*
1888
         * We need a real object to return as the error object.
1889
         * (It only has to last long enough to store in
1890
         * *perror_object.)
1891
         */
1892
0
        make_null_proc(&ierror.full);
1893
0
        SET_IREF(ierror.obj = &ierror.full);
1894
0
        goto error_exit;
1895
0
    }
1896
    /* Reload state information from memory. */
1897
48.1k
    iosp = osp;
1898
48.1k
    iesp = esp;
1899
48.1k
    goto up;
1900
#if 0                           /****** ****** ***** */
1901
  sst:                          /* Time-slice, but push the current object first. */
1902
    store_state(iesp);
1903
    if (iesp >= estop)
1904
        return_with_error_iref(gs_error_execstackoverflow);
1905
    iesp++;
1906
    ref_assign_inline(iesp, iref);
1907
#endif /****** ****** ***** */
1908
48.1k
  slice:                        /* It's time to time-slice or garbage collect. */
1909
    /* iref is not live, so we don't need to do a store_state. */
1910
48.1k
    osp = iosp;
1911
48.1k
    esp = iesp;
1912
    /* If *ticks_left <= -100, we need to GC now. */
1913
48.1k
    if ((*ticks_left) <= -100) {   /* We need to garbage collect now. */
1914
1.00k
        *pi_ctx_p = i_ctx_p;
1915
1.00k
        code = interp_reclaim(pi_ctx_p, -1);
1916
1.00k
        i_ctx_p = *pi_ctx_p;
1917
1.00k
    } else
1918
47.1k
        code = 0;
1919
48.1k
    *ticks_left = i_ctx_p->time_slice_ticks;
1920
48.1k
    set_code_on_interrupt(imemory, &code);
1921
48.1k
    goto sched;
1922
1923
    /* Error exits. */
1924
1925
6.72M
  rweci:
1926
6.72M
    ierror.code = code;
1927
7.03M
  rwei:
1928
7.03M
    ierror.obj = IREF;
1929
7.04M
  rwe:
1930
7.04M
    if (!r_is_packed(iref_packed))
1931
633k
        store_state(iesp);
1932
6.40M
    else {
1933
        /*
1934
         * We need a real object to return as the error object.
1935
         * (It only has to last long enough to store in *perror_object.)
1936
         */
1937
6.40M
        packed_get(imemory, (const ref_packed *)ierror.obj, &ierror.full);
1938
6.40M
        store_state_short(iesp);
1939
6.40M
        if (IREF == ierror.obj)
1940
6.40M
            SET_IREF(&ierror.full);
1941
6.40M
        ierror.obj = &ierror.full;
1942
6.40M
    }
1943
7.04M
  error_exit:
1944
7.04M
    if (GS_ERROR_IS_INTERRUPT(ierror.code)) {      /* We must push the current object being interpreted */
1945
        /* back on the e-stack so it will be re-executed. */
1946
        /* Currently, this is always an executable operator, */
1947
        /* but it might be something else someday if we check */
1948
        /* for interrupts in the interpreter loop itself. */
1949
0
        if (iesp >= estop)
1950
0
            ierror.code = gs_error_execstackoverflow;
1951
0
        else {
1952
0
            iesp++;
1953
0
            ref_assign_inline(iesp, IREF);
1954
0
        }
1955
0
    }
1956
7.04M
    esp = iesp;
1957
7.04M
    osp = iosp;
1958
7.04M
    ref_assign_inline(perror_object, ierror.obj);
1959
#ifdef DEBUG
1960
    if (ierror.code == gs_error_InterpreterExit) {
1961
        /* Do not call gs_log_error to reduce the noise. */
1962
        return gs_error_InterpreterExit;
1963
    }
1964
#endif
1965
7.04M
    return gs_log_error(ierror.code, __FILE__, ierror.line);
1966
7.04M
}
1967
1968
/* Pop the bookkeeping information for a normal exit from a t_oparray. */
1969
static int
1970
oparray_pop(i_ctx_t *i_ctx_p)
1971
189M
{
1972
189M
    esp -= 4;
1973
189M
    return o_pop_estack;
1974
189M
}
1975
1976
/* Restore the stack pointers after an error inside a t_oparray procedure. */
1977
/* This procedure is called only from pop_estack. */
1978
static int
1979
oparray_cleanup(i_ctx_t *i_ctx_p)
1980
6.19M
{                               /* esp points just below the cleanup procedure. */
1981
6.19M
    es_ptr ep = esp;
1982
6.19M
    uint ocount_old = (uint) ep[3].value.intval;
1983
6.19M
    uint dcount_old = (uint) ep[4].value.intval;
1984
6.19M
    uint ocount = ref_stack_count(&o_stack);
1985
6.19M
    uint dcount = ref_stack_count(&d_stack);
1986
1987
6.19M
    if (ocount > ocount_old)
1988
44.7k
        ref_stack_pop(&o_stack, ocount - ocount_old);
1989
6.19M
    if (dcount > dcount_old) {
1990
43.5k
        ref_stack_pop(&d_stack, dcount - dcount_old);
1991
43.5k
        dict_set_top();
1992
43.5k
    }
1993
6.19M
    return 0;
1994
6.19M
}
1995
1996
/* Don't restore the stack pointers. */
1997
static int
1998
oparray_no_cleanup(i_ctx_t *i_ctx_p)
1999
0
{
2000
0
    return 0;
2001
0
}
2002
2003
/* Find the innermost oparray. */
2004
static ref *
2005
oparray_find(i_ctx_t *i_ctx_p)
2006
38.3k
{
2007
38.3k
    long i;
2008
38.3k
    ref *ep;
2009
2010
517k
    for (i = 0; (ep = ref_stack_index(&e_stack, i)) != 0; ++i) {
2011
517k
        if (r_is_estack_mark(ep) &&
2012
517k
            (ep->value.opproc == oparray_cleanup ||
2013
76.6k
             ep->value.opproc == oparray_no_cleanup)
2014
517k
            )
2015
38.3k
            return ep;
2016
517k
    }
2017
0
    return 0;
2018
38.3k
}
2019
2020
/* <errorobj> <obj> .errorexec ... */
2021
/* Execute an object, substituting errorobj for the 'command' if an error */
2022
/* occurs during the execution.  Cf .execfile (in zfile.c). */
2023
static int
2024
zerrorexec(i_ctx_t *i_ctx_p)
2025
14.5M
{
2026
14.5M
    os_ptr op = osp;
2027
14.5M
    int code;
2028
2029
14.5M
    check_op(2);
2030
14.5M
    check_estack(4);            /* mark/cleanup, errobj, pop, obj */
2031
14.5M
    push_mark_estack(es_other, errorexec_cleanup);
2032
14.5M
    *++esp = op[-1];
2033
14.5M
    push_op_estack(errorexec_pop);
2034
14.5M
    code = zexec(i_ctx_p);
2035
14.5M
    if (code >= 0)
2036
14.5M
        pop(1);
2037
0
    else
2038
0
        esp -= 3;               /* undo our additions to estack */
2039
14.5M
    return code;
2040
14.5M
}
2041
2042
/* - .finderrorobject <errorobj> true */
2043
/* - .finderrorobject false */
2044
/* If we are within an .errorexec or oparray, return the error object */
2045
/* and true, otherwise return false. */
2046
static int
2047
zfinderrorobject(i_ctx_t *i_ctx_p)
2048
43.3k
{
2049
43.3k
    os_ptr op = osp;
2050
43.3k
    ref errobj;
2051
2052
43.3k
    if (errorexec_find(i_ctx_p, &errobj)) {
2053
43.3k
        push(2);
2054
43.3k
        op[-1] = errobj;
2055
43.3k
        make_true(op);
2056
43.3k
    } else {
2057
0
        push(1);
2058
0
        make_false(op);
2059
0
    }
2060
43.3k
    return 0;
2061
43.3k
}
2062
2063
/*
2064
 * Find the innermost .errorexec or oparray.  If there is an oparray, or a
2065
 * .errorexec with errobj != null, store it in *perror_object and return 1,
2066
 * otherwise return 0;
2067
 */
2068
int
2069
errorexec_find(i_ctx_t *i_ctx_p, ref *perror_object)
2070
7.11M
{
2071
7.11M
    long i;
2072
7.11M
    const ref *ep;
2073
2074
124M
    for (i = 0; (ep = ref_stack_index(&e_stack, i)) != 0; ++i) {
2075
124M
        if (r_is_estack_mark(ep)) {
2076
20.5M
            if (ep->value.opproc == oparray_cleanup) {
2077
                /* See oppr: above. */
2078
6.78M
                uint opindex = (uint)ep[1].value.intval;
2079
6.78M
                if (opindex == 0) /* internal operator, ignore */
2080
0
                    continue;
2081
6.78M
                op_index_ref(imemory, opindex, perror_object);
2082
6.78M
                return 1;
2083
6.78M
            }
2084
13.7M
            if (ep->value.opproc == oparray_no_cleanup)
2085
0
                return 0;       /* protection disabled */
2086
13.7M
            if (ep->value.opproc == errorexec_cleanup) {
2087
182k
                if (r_has_type(ep + 1, t_null))
2088
34.8k
                    return 0;
2089
147k
                *perror_object = ep[1]; /* see .errorexec above */
2090
147k
                return 1;
2091
182k
            }
2092
13.7M
        }
2093
124M
    }
2094
143k
    return 0;
2095
7.11M
}
2096
2097
/* Pop the bookkeeping information on a normal exit from .errorexec. */
2098
static int
2099
errorexec_pop(i_ctx_t *i_ctx_p)
2100
14.4M
{
2101
14.4M
    esp -= 2;
2102
14.4M
    return o_pop_estack;
2103
14.4M
}
2104
2105
/* Clean up when unwinding the stack on an error.  (No action needed.) */
2106
static int
2107
errorexec_cleanup(i_ctx_t *i_ctx_p)
2108
46.3k
{
2109
46.3k
    return 0;
2110
46.3k
}
2111
2112
/* <bool> .setstackprotect - */
2113
/* Set whether to protect the stack for the innermost oparray. */
2114
static int
2115
zsetstackprotect(i_ctx_t *i_ctx_p)
2116
38.3k
{
2117
38.3k
    os_ptr op = osp;
2118
38.3k
    ref *ep = oparray_find(i_ctx_p);
2119
2120
38.3k
    check_op(1);
2121
38.3k
    check_type(*op, t_boolean);
2122
38.3k
    if (ep == 0)
2123
0
        return_error(gs_error_rangecheck);
2124
38.3k
    ep->value.opproc =
2125
38.3k
        (op->value.boolval ? oparray_cleanup : oparray_no_cleanup);
2126
38.3k
    pop(1);
2127
38.3k
    return 0;
2128
38.3k
}
2129
2130
/* - .currentstackprotect <bool> */
2131
/* Return the stack protection status. */
2132
static int
2133
zcurrentstackprotect(i_ctx_t *i_ctx_p)
2134
0
{
2135
0
    os_ptr op = osp;
2136
0
    ref *ep = oparray_find(i_ctx_p);
2137
2138
0
    if (ep == 0)
2139
0
        return_error(gs_error_rangecheck);
2140
0
    push(1);
2141
0
    make_bool(op, ep->value.opproc == oparray_cleanup);
2142
0
    return 0;
2143
0
}
2144
2145
static int
2146
zactonuel(i_ctx_t *i_ctx_p)
2147
9.57k
{
2148
9.57k
    os_ptr op = osp;
2149
2150
9.57k
    push(1);
2151
9.57k
    make_bool(op, !!gs_lib_ctx_get_act_on_uel((gs_memory_t *)(i_ctx_p->memory.current)));
2152
9.57k
    return 0;
2153
9.57k
}