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