Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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