Coverage Report

Created: 2025-06-10 06:56

/src/ghostpdl/psi/iinit.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
/* Initialize internally known objects for Ghostscript interpreter */
18
#include "string_.h"
19
#include "ghost.h"
20
#include "gscdefs.h"
21
#include "gsexit.h"
22
#include "gsstruct.h"
23
#include "ierrors.h"
24
#include "ialloc.h"
25
#include "iddict.h"
26
#include "dstack.h"
27
#include "ilevel.h"
28
#include "iinit.h"
29
#include "iname.h"
30
#include "interp.h"
31
#include "ipacked.h"
32
#include "iparray.h"
33
#include "iutil.h"
34
#include "ivmspace.h"
35
#include "opdef.h"
36
#include "store.h"
37
#include "iconf.h"
38
#include "gxiodev.h"
39
40
/* Implementation parameters. */
41
/*
42
 * Define the (initial) sizes of the various system dictionaries.  We want
43
 * the sizes to be prime numbers large enough to cover all the operators,
44
 * plus everything in the init files, even if all the optional features are
45
 * selected.  Note that these sizes must be large enough to get us through
46
 * initialization, since we start up in Level 1 mode where dictionaries
47
 * don't expand automatically.
48
 */
49
/* The size of systemdict can be set in the makefile. */
50
#ifndef SYSTEMDICT_SIZE
51
0
#  define SYSTEMDICT_SIZE 631
52
#endif
53
#ifndef SYSTEMDICT_LEVEL2_SIZE
54
0
#  define SYSTEMDICT_LEVEL2_SIZE 983
55
#endif
56
#ifndef SYSTEMDICT_LL3_SIZE
57
1.78k
#  define SYSTEMDICT_LL3_SIZE 1123
58
#endif
59
/* The size of level2dict, if applicable, can be set in the makefile. */
60
#ifndef LEVEL2DICT_SIZE
61
#  define LEVEL2DICT_SIZE 251
62
#endif
63
/* Ditto the size of ll3dict. */
64
#ifndef LL3DICT_SIZE
65
#  define LL3DICT_SIZE 43
66
#endif
67
/* Ditto the size of filterdict. */
68
#ifndef FILTERDICT_SIZE
69
#  define FILTERDICT_SIZE 43
70
#endif
71
/* Define an arbitrary size for the operator procedure tables. */
72
#ifndef OP_ARRAY_TABLE_SIZE
73
3.56k
#  define OP_ARRAY_TABLE_SIZE 300
74
#endif
75
#ifndef OP_ARRAY_TABLE_GLOBAL_SIZE
76
1.78k
#  define OP_ARRAY_TABLE_GLOBAL_SIZE OP_ARRAY_TABLE_SIZE
77
#endif
78
#ifndef OP_ARRAY_TABLE_LOCAL_SIZE
79
1.78k
#  define OP_ARRAY_TABLE_LOCAL_SIZE (OP_ARRAY_TABLE_SIZE / 2)
80
#endif
81
#define OP_ARRAY_TABLE_TOTAL_SIZE\
82
  (OP_ARRAY_TABLE_GLOBAL_SIZE + OP_ARRAY_TABLE_LOCAL_SIZE)
83
84
/* Define the list of error names. */
85
const char *const gs_error_names[] =
86
{
87
    ERROR_NAMES
88
};
89
90
/* Enter a name and value into a dictionary. */
91
static int
92
i_initial_enter_name_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr,
93
                        const ref * pref)
94
1.06M
{
95
1.06M
    int code = idict_put_string(pdict, nstr, pref);
96
97
1.06M
    if (code < 0)
98
0
        lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n",
99
1.06M
                 code, nstr, dict_length(pdict), dict_maxlength(pdict));
100
1.06M
    return code;
101
1.06M
}
102
int
103
i_initial_enter_name(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref)
104
37.4k
{
105
37.4k
    return i_initial_enter_name_in(i_ctx_p, systemdict, nstr, pref);
106
37.4k
}
107
108
/* Enter a name and value into a dictionary. */
109
static int
110
i_initial_enter_name_copy_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr,
111
                             const ref * pref)
112
26.7k
{
113
26.7k
    int code = idict_put_string_copy(pdict, nstr, pref);
114
115
26.7k
    if (code < 0)
116
0
        lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n",
117
26.7k
                 code, nstr, dict_length(pdict), dict_maxlength(pdict));
118
26.7k
    return code;
119
26.7k
}
120
int
121
i_initial_enter_name_copy(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref)
122
26.7k
{
123
26.7k
    return i_initial_enter_name_copy_in(i_ctx_p, systemdict, nstr, pref);
124
26.7k
}
125
126
/* Remove a name from systemdict. */
127
void
128
i_initial_remove_name(i_ctx_t *i_ctx_p, const char *nstr)
129
0
{
130
0
    ref nref;
131
132
0
    if (name_ref(imemory, (const byte *)nstr, strlen(nstr), &nref, -1) >= 0)
133
0
        idict_undef(systemdict, &nref);
134
0
}
135
136
/* Define the names and sizes of the initial dictionaries. */
137
/* The names are used to create references in systemdict. */
138
const struct {
139
    const char *name;
140
    uint size;
141
    bool local;
142
} initial_dictionaries[] = {
143
#ifdef INITIAL_DICTIONARIES
144
    INITIAL_DICTIONARIES
145
#else
146
    /* systemdict is created and named automagically */
147
    {
148
        "level2dict", LEVEL2DICT_SIZE, false
149
    },
150
    {
151
        "ll3dict", LL3DICT_SIZE, false
152
    },
153
    {
154
        "globaldict", 0, false
155
    },
156
    {
157
        "userdict", 0, true
158
    },
159
    {
160
        "filterdict", FILTERDICT_SIZE, false
161
    },
162
#endif
163
};
164
/* systemdict and globaldict are magically inserted at the bottom */
165
const char *const initial_dstack[] =
166
{
167
#ifdef INITIAL_DSTACK
168
    INITIAL_DSTACK
169
#else
170
    "userdict"
171
#endif
172
};
173
174
1.78k
#define MIN_DSTACK_SIZE (countof(initial_dstack) + 1)   /* +1 for systemdict */
175
176
/*
177
 * Detect whether we have any Level 2 or LanguageLevel 3 operators.
178
 * We export this for gs_init1 in imain.c.
179
 * This is slow, but we only call it a couple of times.
180
 */
181
static int
182
gs_op_language_level(void)
183
3.56k
{
184
3.56k
    const op_def *const *tptr;
185
3.56k
    int level = 1;
186
187
367k
    for (tptr = op_defs_all; *tptr != 0; ++tptr) {
188
363k
        const op_def *def;
189
190
2.80M
        for (def = *tptr; def->oname != 0; ++def)
191
2.43M
            if (op_def_is_begin_dict(def)) {
192
99.9k
                if (!strcmp(def->oname, "level2dict"))
193
53.5k
                    level = max(level, 2);
194
46.3k
                else if (!strcmp(def->oname, "ll3dict"))
195
14.2k
                    level = max(level, 3);
196
99.9k
            }
197
363k
    }
198
3.56k
    return level;
199
3.56k
}
200
bool
201
gs_have_level2(void)
202
1.78k
{
203
1.78k
    return (gs_op_language_level() >= 2);
204
1.78k
}
205
206
/* Create an initial dictionary if necessary. */
207
static ref *
208
make_initial_dict(i_ctx_t *i_ctx_p, const char *iname, ref idicts[])
209
51.7k
{
210
51.7k
    int i;
211
212
    /* systemdict was created specially. */
213
51.7k
    if (!strcmp(iname, "systemdict"))
214
1.78k
        return systemdict;
215
119k
    for (i = 0; i < countof(initial_dictionaries); i++) {
216
119k
        const char *dname = initial_dictionaries[i].name;
217
119k
        const int dsize = initial_dictionaries[i].size;
218
219
119k
        if (!strcmp(iname, dname)) {
220
49.9k
            ref *dref = &idicts[i];
221
222
49.9k
            if (r_has_type(dref, t_null)) {
223
7.13k
                gs_ref_memory_t *mem =
224
7.13k
                    (initial_dictionaries[i].local ?
225
5.35k
                     iimemory_local : iimemory_global);
226
7.13k
                int code = dict_alloc(mem, dsize, dref);
227
228
7.13k
                if (code < 0)
229
0
                    return 0;   /* disaster */
230
7.13k
            }
231
49.9k
            return dref;
232
49.9k
        }
233
119k
    }
234
235
    /*
236
     * Name mentioned in some op_def, but not in initial_dictionaries.
237
     * Punt.
238
     */
239
0
    return 0;
240
49.9k
}
241
242
/* Initialize objects other than operators.  In particular, */
243
/* initialize the dictionaries that hold operator definitions. */
244
int
245
obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem)
246
1.78k
{
247
1.78k
    int level = gs_op_language_level();
248
1.78k
    ref system_dict;
249
1.78k
    i_ctx_t *i_ctx_p;
250
1.78k
    int code;
251
252
    /*
253
     * Create systemdict.  The context machinery requires that
254
     * we do this before initializing the interpreter.
255
     */
256
1.78k
    code = dict_alloc(idmem->space_global,
257
1.78k
                      (level >= 3 ? SYSTEMDICT_LL3_SIZE :
258
1.78k
                       level >= 2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE),
259
1.78k
                      &system_dict);
260
1.78k
    if (code < 0)
261
0
        return code;
262
263
    /* Initialize the interpreter. */
264
1.78k
    code = gs_interp_init(pi_ctx_p, &system_dict, idmem);
265
1.78k
    if (code < 0)
266
0
        return code;
267
1.78k
    i_ctx_p = *pi_ctx_p;
268
269
1.78k
    {
270
10.7k
#define icount countof(initial_dictionaries)
271
1.78k
        ref idicts[icount];
272
1.78k
        int i;
273
1.78k
        const op_def *const *tptr;
274
275
1.78k
        min_dstack_size = MIN_DSTACK_SIZE;
276
277
1.78k
        refset_null(idicts, icount);
278
279
        /* Put systemdict on the dictionary stack. */
280
1.78k
        if (level >= 2) {
281
1.78k
            dsp += 2;
282
            /*
283
             * For the moment, let globaldict be an alias for systemdict.
284
             */
285
1.78k
            dsp[-1] = system_dict;
286
1.78k
            min_dstack_size++;
287
1.78k
        } else {
288
0
            ++dsp;
289
0
        }
290
1.78k
        *dsp = system_dict;
291
292
        /* Create dictionaries which are to be homes for operators. */
293
183k
        for (tptr = op_defs_all; *tptr != 0; tptr++) {
294
181k
            const op_def *def;
295
296
1.40M
            for (def = *tptr; def->oname != 0; def++)
297
1.21M
                if (op_def_is_begin_dict(def)) {
298
49.9k
                    if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0)
299
0
                        return_error(gs_error_VMerror);
300
49.9k
                }
301
181k
        }
302
303
        /* Set up the initial dstack. */
304
3.56k
        for (i = 0; i < countof(initial_dstack); i++) {
305
1.78k
            const char *dname = initial_dstack[i];
306
1.78k
            ref *r;
307
308
1.78k
            ++dsp;
309
1.78k
            if (!strcmp(dname, "userdict"))
310
1.78k
                dstack_userdict_index = dsp - dsbot;
311
1.78k
            r = make_initial_dict(i_ctx_p, dname, idicts);
312
1.78k
            if (r == NULL)
313
0
                return_error(gs_error_VMerror);
314
1.78k
            ref_assign(dsp, r);
315
1.78k
        }
316
317
        /* Enter names of referenced initial dictionaries into systemdict. */
318
1.78k
        i_initial_enter_name(i_ctx_p, "systemdict", systemdict);
319
10.7k
        for (i = 0; i < icount; i++) {
320
8.92k
            ref *idict = &idicts[i];
321
322
8.92k
            if (!r_has_type(idict, t_null)) {
323
                /*
324
                 * Note that we enter the dictionary in systemdict
325
                 * even if it is in local VM.  There is a special
326
                 * provision in the garbage collector for this:
327
                 * see ivmspace.h for more information.
328
                 * In order to do this, we must temporarily
329
                 * identify systemdict as local, so that the
330
                 * store check in dict_put won't fail.
331
                 */
332
7.13k
                uint save_space = r_space(systemdict);
333
334
7.13k
                r_set_space(systemdict, avm_local);
335
7.13k
                code = i_initial_enter_name(i_ctx_p, initial_dictionaries[i].name,
336
7.13k
                                            idict);
337
7.13k
                r_set_space(systemdict, save_space);
338
7.13k
                if (code < 0)
339
0
                    return code;
340
7.13k
            }
341
8.92k
        }
342
1.78k
#undef icount
343
1.78k
    }
344
345
1.78k
    gs_interp_reset(i_ctx_p);
346
347
1.78k
    {
348
1.78k
#ifdef PACIFY_VALGRIND
349
1.78k
        ref vnull = { 0 }, vtrue = { 0 }, vfalse = { 0 };
350
#else
351
        ref vnull, vtrue, vfalse;
352
#endif
353
354
1.78k
        make_null(&vnull);
355
1.78k
        make_true(&vtrue);
356
1.78k
        make_false(&vfalse);
357
1.78k
        if ((code = i_initial_enter_name(i_ctx_p, "null", &vnull)) < 0 ||
358
1.78k
            (code = i_initial_enter_name(i_ctx_p, "true", &vtrue)) < 0 ||
359
1.78k
            (code = i_initial_enter_name(i_ctx_p, "false", &vfalse)) < 0
360
1.78k
            )
361
0
            return code;
362
1.78k
    }
363
364
    /* Create the error name table */
365
1.78k
    {
366
1.78k
        int n = countof(gs_error_names);
367
1.78k
        int i;
368
1.78k
        ref era;
369
370
1.78k
        code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames");
371
1.78k
        if (code < 0)
372
0
            return code;
373
58.8k
        for (i = 0; i < n; i++)
374
57.0k
          if ((code = name_enter_string(imemory, (const char *)gs_error_names[i],
375
57.0k
                                          era.value.refs + i)) < 0)
376
0
                return code;
377
1.78k
        return i_initial_enter_name(i_ctx_p, "ErrorNames", &era);
378
1.78k
    }
379
1.78k
}
380
381
/* Run the initialization procedures of the individual operator files. */
382
int
383
zop_init(i_ctx_t *i_ctx_p)
384
1.78k
{
385
1.78k
    const op_def *const *tptr;
386
1.78k
    int code;
387
388
    /* Because of a bug in Sun's SC1.0 compiler, */
389
    /* we have to spell out the typedef for op_def_ptr here: */
390
1.78k
    const op_def *def;
391
392
183k
    for (tptr = op_defs_all; *tptr != 0; tptr++) {
393
1.40M
        for (def = *tptr; def->oname != 0; def++)
394
1.21M
            DO_NOTHING;
395
181k
        if (def->proc != 0) {
396
7.13k
            code = def->proc(i_ctx_p);
397
7.13k
            if (code < 0) {
398
#ifdef DEBUG
399
                lprintf2("op_init proc "PRI_INTPTR" returned error %d!\n",
400
                         (intptr_t)def->proc, code);
401
#else
402
0
                lprintf("op_init proc returned error !\n");
403
0
#endif
404
0
                return code;
405
0
            }
406
7.13k
        }
407
181k
    }
408
409
    /* Initialize the predefined names other than operators. */
410
    /* Do this here in case op_init changed any of them. */
411
1.78k
    {
412
1.78k
        ref vcr, vpr, vpf, vre, vrd, vres;
413
414
1.78k
        make_const_string(&vcr, a_readonly | avm_foreign,
415
1.78k
                          strlen(gs_copyright), (const byte *)gs_copyright);
416
1.78k
        make_const_string(&vpr, a_readonly | avm_foreign,
417
1.78k
                          strlen(gs_product), (const byte *)gs_product);
418
1.78k
        make_const_string(&vpf, a_readonly | avm_foreign,
419
1.78k
                          strlen(gs_productfamily),
420
1.78k
                          (const byte *)gs_productfamily);
421
1.78k
        make_const_string(&vres, a_readonly | avm_foreign,
422
1.78k
                          strlen(GS_STRINGIZE(GS_DOT_VERSION)),
423
1.78k
                          (const byte *)GS_STRINGIZE(GS_DOT_VERSION));
424
1.78k
        make_int(&vre, gs_revision);
425
1.78k
        make_int(&vrd, gs_revisiondate);
426
1.78k
        if ((code = i_initial_enter_name(i_ctx_p, "copyright", &vcr)) < 0 ||
427
1.78k
            (code = i_initial_enter_name(i_ctx_p, "product", &vpr)) < 0 ||
428
1.78k
            (code = i_initial_enter_name(i_ctx_p, "productfamily", &vpf)) < 0 ||
429
1.78k
            (code = i_initial_enter_name(i_ctx_p, "revision", &vre)) < 0 ||
430
1.78k
            (code = i_initial_enter_name(i_ctx_p, "revisiondate", &vrd)) < 0 ||
431
1.78k
            (code = i_initial_enter_name(i_ctx_p, ".revisionstring", &vres)) < 0)
432
0
            return code;
433
1.78k
    }
434
435
1.78k
    return 0;
436
1.78k
}
437
438
/* Create an op_array table. */
439
static int
440
alloc_op_array_table(i_ctx_t *i_ctx_p, uint size, uint space,
441
                     op_array_table *opt)
442
3.56k
{
443
3.56k
    uint save_space = ialloc_space(idmemory);
444
3.56k
    int code;
445
446
3.56k
    ialloc_set_space(idmemory, space);
447
3.56k
    code = ialloc_ref_array(&opt->table, a_readonly, size,
448
3.56k
                            "op_array table");
449
3.56k
    ialloc_set_space(idmemory, save_space);
450
3.56k
    if (code < 0)
451
0
        return code;
452
3.56k
    refset_null(opt->table.value.refs, size);
453
3.56k
    opt->nx_table =
454
3.56k
        (ushort *) ialloc_byte_array(size, sizeof(ushort),
455
3.56k
                                     "op_array nx_table");
456
3.56k
    if (opt->nx_table == 0)
457
0
        return_error(gs_error_VMerror);
458
3.56k
    opt->count = 0;
459
3.56k
    opt->attrs = space | a_executable;
460
3.56k
    return 0;
461
3.56k
}
462
463
/* Initialize the operator table. */
464
int
465
op_init(i_ctx_t *i_ctx_p)
466
1.78k
{
467
1.78k
    const op_def *const *tptr;
468
1.78k
    int code;
469
470
    /* Enter each operator into the appropriate dictionary. */
471
472
183k
    for (tptr = op_defs_all; *tptr != 0; tptr++) {
473
181k
        ref *pdict = systemdict;
474
181k
        const op_def *def;
475
181k
        const char *nstr;
476
477
1.40M
        for (def = *tptr; (nstr = def->oname) != 0; def++)
478
1.21M
            if (op_def_is_begin_dict(def)) {
479
49.9k
                ref nref;
480
481
49.9k
                code = name_ref(imemory, (const byte *)nstr, strlen(nstr), &nref, -1);
482
49.9k
                if (code < 0)
483
0
                    return code;
484
49.9k
                if (!dict_find(systemdict, &nref, &pdict))
485
0
                    return_error(gs_error_Fatal);
486
49.9k
                if (!r_has_type(pdict, t_dictionary))
487
0
                    return_error(gs_error_Fatal);
488
1.16M
            } else {
489
1.16M
                ref oper;
490
1.16M
                uint index_in_table = def - *tptr;
491
1.16M
                uint opidx = (tptr - op_defs_all) * OP_DEFS_MAX_SIZE +
492
1.16M
                    index_in_table;
493
494
1.16M
                if (index_in_table >= OP_DEFS_MAX_SIZE) {
495
0
                    lprintf1("opdef overrun! %s\n", def->oname);
496
0
                    return_error(gs_error_Fatal);
497
0
                }
498
1.16M
                gs_interp_make_oper(&oper, def->proc, opidx);
499
                /* The first character of the name is a digit */
500
                /* giving the minimum acceptable number of operands. */
501
                /* Check to make sure it's within bounds. */
502
1.16M
                if (*nstr - '0' > gs_interp_max_op_num_args)
503
0
                    return_error(gs_error_Fatal);
504
1.16M
                nstr++;
505
                /*
506
                 * Skip internal operators, and the second occurrence of
507
                 * operators with special indices.
508
                 */
509
1.16M
                if (*nstr != '%' && r_size(&oper) == opidx) {
510
1.02M
                    code =
511
1.02M
                        i_initial_enter_name_in(i_ctx_p, pdict, nstr, &oper);
512
1.02M
                    if (code < 0)
513
0
                        return code;
514
1.02M
                }
515
1.16M
            }
516
181k
    }
517
    /* Allocate the tables for `operator' procedures. */
518
    /* Make one of them local so we can have local operators. */
519
1.78k
    if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_GLOBAL_SIZE,
520
1.78k
                                     avm_global,
521
1.78k
                                     &i_ctx_p->op_array_table_global) < 0))
522
0
        return code;
523
1.78k
    i_ctx_p->op_array_table_global.base_index = op_def_count;
524
1.78k
    if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_LOCAL_SIZE,
525
1.78k
                                     avm_local,
526
1.78k
                                     &i_ctx_p->op_array_table_local) < 0))
527
0
        return code;
528
1.78k
    i_ctx_p->op_array_table_local.base_index =
529
1.78k
        i_ctx_p->op_array_table_global.base_index +
530
1.78k
        r_size(&i_ctx_p->op_array_table_global.table);
531
532
1.78k
    return 0;
533
1.78k
}
534
535
#if defined(DEBUG_TRACE_PS_OPERATORS) || defined(DEBUG)
536
static const char *unknown_op_name = "unknown_op";
537
538
const char *
539
op_get_name_string(op_proc_t opproc)
540
{
541
    const op_def *const *tptr;
542
543
    for (tptr = op_defs_all; *tptr != 0; tptr++) {
544
        const op_def *def;
545
546
        for (def = *tptr; def->oname != 0; def++)
547
            if (!op_def_is_begin_dict(def)) {
548
                if (def->proc == opproc)
549
                    return def->oname;
550
            }
551
    }
552
    return unknown_op_name;
553
}
554
#endif
555
556
int
557
i_iodev_init(gs_dual_memory_t *dmem)
558
1.78k
{
559
1.78k
    int i;
560
1.78k
    int code;
561
1.78k
    gs_memory_t *mem = (gs_memory_t *)dmem->current;
562
563
1.78k
    code = gs_iodev_init(mem);
564
565
14.2k
    for (i = 0; i < i_io_device_table_count && code >= 0; i++) {
566
12.4k
        code = gs_iodev_register_dev(mem, i_io_device_table[i]);
567
12.4k
    }
568
569
1.78k
    return code;
570
1.78k
}
571
572
void
573
i_iodev_finit(gs_dual_memory_t *dmem)
574
1.78k
{
575
1.78k
    gs_iodev_finit((gs_memory_t *)dmem->current);
576
1.78k
}