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
i_initial_enter_name_in(i_ctx_t * i_ctx_p,ref * pdict,const char * nstr,const ref * pref)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
i_initial_enter_name(i_ctx_t * i_ctx_p,const char * nstr,const ref * pref)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
i_initial_remove_name(i_ctx_t * i_ctx_p,const char * nstr)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
gs_op_language_level(void)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
gs_have_level2(void)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 *
make_initial_dict(i_ctx_t * i_ctx_p,const char * iname,ref idicts[])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
obj_init(i_ctx_t ** pi_ctx_p,gs_dual_memory_t * idmem)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
zop_init(i_ctx_t * i_ctx_p)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
alloc_op_array_table(i_ctx_t * i_ctx_p,uint size,uint space,op_array_table * opt)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
op_init(i_ctx_t * i_ctx_p)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 }
518