Coverage Report

Created: 2025-04-22 06:20

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