/src/ghostpdl/psi/iinit.c
Line | Count | Source |
1 | | /* Copyright (C) 2001-2026 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 | 154k | # 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 userdict. */ |
68 | | #ifndef USERDICT_SIZE |
69 | | # define USERDICT_SIZE 211 |
70 | | #endif |
71 | | /* Ditto the size of $error. */ |
72 | | #ifndef DOLLARERROR_SIZE |
73 | | # define DOLLARERROR_SIZE 43 |
74 | | #endif |
75 | | /* Ditto the size of errordict. */ |
76 | | #ifndef ERRORDICT_SIZE |
77 | | # define ERRORDICT_SIZE 43 |
78 | | #endif |
79 | | #ifndef STATUSDICT_SIZE |
80 | | # define STATUSDICT_SIZE 91 |
81 | | #endif |
82 | | #ifndef SERVERDICT_SIZE |
83 | | # define SERVERDICT_SIZE 11 |
84 | | #endif |
85 | | /* Ditto the size of FontDirectory. */ |
86 | | #ifndef FONTDIRECTORY_SIZE |
87 | | # define FONTDIRECTORY_SIZE 101 |
88 | | #endif |
89 | | /* Ditto the size of filterdict. */ |
90 | | #ifndef FILTERDICT_SIZE |
91 | | # define FILTERDICT_SIZE 43 |
92 | | #endif |
93 | | /* Define an arbitrary size for the operator procedure tables. */ |
94 | | #ifndef OP_ARRAY_TABLE_SIZE |
95 | 308k | # define OP_ARRAY_TABLE_SIZE 300 |
96 | | #endif |
97 | | #ifndef OP_ARRAY_TABLE_GLOBAL_SIZE |
98 | 154k | # define OP_ARRAY_TABLE_GLOBAL_SIZE OP_ARRAY_TABLE_SIZE |
99 | | #endif |
100 | | #ifndef OP_ARRAY_TABLE_LOCAL_SIZE |
101 | 154k | # define OP_ARRAY_TABLE_LOCAL_SIZE (OP_ARRAY_TABLE_SIZE / 2) |
102 | | #endif |
103 | | #define OP_ARRAY_TABLE_TOTAL_SIZE\ |
104 | | (OP_ARRAY_TABLE_GLOBAL_SIZE + OP_ARRAY_TABLE_LOCAL_SIZE) |
105 | | |
106 | | /* Define the list of error names. */ |
107 | | const char *const gs_error_names[] = |
108 | | { |
109 | | ERROR_NAMES |
110 | | }; |
111 | | |
112 | | /* Enter a name and value into a dictionary. */ |
113 | | static int |
114 | | i_initial_enter_name_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr, |
115 | | const ref * pref) |
116 | 92.9M | { |
117 | 92.9M | int code = idict_put_string(pdict, nstr, pref); |
118 | | |
119 | 92.9M | if (code < 0) |
120 | 0 | lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n", |
121 | 92.9M | code, nstr, dict_length(pdict), dict_maxlength(pdict)); |
122 | 92.9M | return code; |
123 | 92.9M | } |
124 | | int |
125 | | i_initial_enter_name(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref) |
126 | 4.01M | { |
127 | 4.01M | return i_initial_enter_name_in(i_ctx_p, systemdict, nstr, pref); |
128 | 4.01M | } |
129 | | |
130 | | /* Enter a name and value into a dictionary. */ |
131 | | static int |
132 | | i_initial_enter_name_copy_in(i_ctx_t *i_ctx_p, ref *pdict, const char *nstr, |
133 | | const ref * pref) |
134 | 2.25M | { |
135 | 2.25M | int code = idict_put_string_copy(pdict, nstr, pref); |
136 | | |
137 | 2.25M | if (code < 0) |
138 | 0 | lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n", |
139 | 2.25M | code, nstr, dict_length(pdict), dict_maxlength(pdict)); |
140 | 2.25M | return code; |
141 | 2.25M | } |
142 | | int |
143 | | i_initial_enter_name_copy(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref) |
144 | 2.25M | { |
145 | 2.25M | return i_initial_enter_name_copy_in(i_ctx_p, systemdict, nstr, pref); |
146 | 2.25M | } |
147 | | |
148 | | /* Remove a name from systemdict. */ |
149 | | void |
150 | | i_initial_remove_name(i_ctx_t *i_ctx_p, const char *nstr) |
151 | 0 | { |
152 | 0 | ref nref; |
153 | |
|
154 | 0 | if (name_ref(imemory, (const byte *)nstr, strlen(nstr), &nref, -1) >= 0) |
155 | 0 | idict_undef(systemdict, &nref); |
156 | 0 | } |
157 | | |
158 | | /* Define the names and sizes of the initial dictionaries. */ |
159 | | /* The names are used to create references in systemdict. */ |
160 | | const struct { |
161 | | const char *name; |
162 | | uint size; |
163 | | bool local; |
164 | | } initial_dictionaries[] = { |
165 | | #ifdef INITIAL_DICTIONARIES |
166 | | INITIAL_DICTIONARIES |
167 | | #else |
168 | | /* systemdict is created and named automagically */ |
169 | | { |
170 | | "level2dict", LEVEL2DICT_SIZE, false |
171 | | }, |
172 | | { |
173 | | "ll3dict", LL3DICT_SIZE, false |
174 | | }, |
175 | | { |
176 | | "globaldict", 0, false |
177 | | }, |
178 | | { |
179 | | "userdict", USERDICT_SIZE, true |
180 | | }, |
181 | | { |
182 | | "$error", DOLLARERROR_SIZE, true |
183 | | }, |
184 | | { |
185 | | "errordict", ERRORDICT_SIZE, true |
186 | | }, |
187 | | { |
188 | | "FontDirectory", FONTDIRECTORY_SIZE, true |
189 | | }, |
190 | | { |
191 | | "statusdict", STATUSDICT_SIZE, true |
192 | | }, |
193 | | { |
194 | | "serverdict", SERVERDICT_SIZE, true |
195 | | }, |
196 | | { |
197 | | "filterdict", FILTERDICT_SIZE, false |
198 | | }, |
199 | | #endif |
200 | | }; |
201 | | const char *const initial_referred[] = |
202 | | { |
203 | | #ifdef INITIAL_REFERRED |
204 | | INITIAL_REFERRED |
205 | | #else |
206 | | "$error", |
207 | | "errordict", |
208 | | "FontDirectory", |
209 | | "statusdict", |
210 | | "serverdict" |
211 | | #endif |
212 | | }; |
213 | | /* systemdict and globaldict are magically inserted at the bottom */ |
214 | | const char *const initial_dstack[] = |
215 | | { |
216 | | #ifdef INITIAL_DSTACK |
217 | | INITIAL_DSTACK |
218 | | #else |
219 | | "userdict" |
220 | | #endif |
221 | | }; |
222 | | |
223 | 154k | #define MIN_DSTACK_SIZE (countof(initial_dstack) + 1) /* +1 for systemdict */ |
224 | | |
225 | | /* |
226 | | * Detect whether we have any Level 2 or LanguageLevel 3 operators. |
227 | | * We export this for gs_init1 in imain.c. |
228 | | * This is slow, but we only call it a couple of times. |
229 | | */ |
230 | | static int |
231 | | gs_op_language_level(void) |
232 | 308k | { |
233 | 308k | const op_def *const *tptr; |
234 | 308k | int level = 1; |
235 | | |
236 | 31.8M | for (tptr = op_defs_all; *tptr != 0; ++tptr) { |
237 | 31.4M | const op_def *def; |
238 | | |
239 | 242M | for (def = *tptr; def->oname != 0; ++def) |
240 | 210M | if (op_def_is_begin_dict(def)) { |
241 | 8.64M | if (!strcmp(def->oname, "level2dict")) |
242 | 4.63M | level = max(level, 2); |
243 | 4.01M | else if (!strcmp(def->oname, "ll3dict")) |
244 | 1.23M | level = max(level, 3); |
245 | 8.64M | } |
246 | 31.4M | } |
247 | 308k | return level; |
248 | 308k | } |
249 | | bool |
250 | | gs_have_level2(void) |
251 | 154k | { |
252 | 154k | return (gs_op_language_level() >= 2); |
253 | 154k | } |
254 | | |
255 | | /* Create an initial dictionary if necessary. */ |
256 | | static ref * |
257 | | make_initial_dict(i_ctx_t *i_ctx_p, const char *iname, ref idicts[]) |
258 | 5.24M | { |
259 | 5.24M | int i; |
260 | | |
261 | | /* systemdict was created specially. */ |
262 | 5.24M | if (!strcmp(iname, "systemdict")) |
263 | 154k | return systemdict; |
264 | 21.9M | for (i = 0; i < countof(initial_dictionaries); i++) { |
265 | 21.9M | const char *dname = initial_dictionaries[i].name; |
266 | 21.9M | const int dsize = initial_dictionaries[i].size; |
267 | | |
268 | 21.9M | if (!strcmp(iname, dname)) { |
269 | 5.09M | ref *dref = &idicts[i]; |
270 | | |
271 | 5.09M | if (r_has_type(dref, t_null)) { |
272 | 1.38M | gs_ref_memory_t *mem = |
273 | 1.38M | (initial_dictionaries[i].local ? |
274 | 926k | iimemory_local : iimemory_global); |
275 | 1.38M | int code = dict_alloc(mem, dsize, dref); |
276 | | |
277 | 1.38M | if (code < 0) |
278 | 0 | return 0; /* disaster */ |
279 | 1.38M | } |
280 | 5.09M | return dref; |
281 | 5.09M | } |
282 | 21.9M | } |
283 | | |
284 | | /* |
285 | | * Name mentioned in some op_def, but not in initial_dictionaries. |
286 | | * Punt. |
287 | | */ |
288 | 0 | return 0; |
289 | 5.09M | } |
290 | | |
291 | | /* Initialize objects other than operators. In particular, */ |
292 | | /* initialize the dictionaries that hold operator definitions. */ |
293 | | int |
294 | | obj_init(i_ctx_t **pi_ctx_p, gs_dual_memory_t *idmem) |
295 | 154k | { |
296 | 154k | int level = gs_op_language_level(); |
297 | 154k | ref system_dict; |
298 | 154k | i_ctx_t *i_ctx_p; |
299 | 154k | int code; |
300 | | |
301 | | /* |
302 | | * Create systemdict. The context machinery requires that |
303 | | * we do this before initializing the interpreter. |
304 | | */ |
305 | 154k | code = dict_alloc(idmem->space_global, |
306 | 154k | (level >= 3 ? SYSTEMDICT_LL3_SIZE : |
307 | 154k | level >= 2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE), |
308 | 154k | &system_dict); |
309 | 154k | if (code < 0) |
310 | 0 | return code; |
311 | | |
312 | | /* Initialize the interpreter. */ |
313 | 154k | code = gs_interp_init(pi_ctx_p, &system_dict, idmem); |
314 | 154k | if (code < 0) |
315 | 0 | return code; |
316 | 154k | i_ctx_p = *pi_ctx_p; |
317 | | |
318 | 154k | { |
319 | 1.69M | #define icount countof(initial_dictionaries) |
320 | 154k | ref idicts[icount]; |
321 | 154k | int i; |
322 | 154k | const op_def *const *tptr; |
323 | | |
324 | 154k | min_dstack_size = MIN_DSTACK_SIZE; |
325 | | |
326 | 154k | refset_null(idicts, icount); |
327 | | |
328 | | /* Put systemdict on the dictionary stack. */ |
329 | 154k | if (level >= 2) { |
330 | 154k | dsp += 2; |
331 | | /* |
332 | | * For the moment, let globaldict be an alias for systemdict. |
333 | | */ |
334 | 154k | dsp[-1] = system_dict; |
335 | 154k | min_dstack_size++; |
336 | 154k | } else { |
337 | 0 | ++dsp; |
338 | 0 | } |
339 | 154k | *dsp = system_dict; |
340 | | |
341 | | /* Create dictionaries which are to be homes for operators. */ |
342 | 15.9M | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
343 | 15.7M | const op_def *def; |
344 | | |
345 | 121M | for (def = *tptr; def->oname != 0; def++) |
346 | 105M | if (op_def_is_begin_dict(def)) { |
347 | 4.32M | if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0) |
348 | 0 | return_error(gs_error_VMerror); |
349 | 4.32M | } |
350 | 15.7M | } |
351 | | |
352 | | /* Create dictionaries which are stored inside systemdict, but in local VM |
353 | | * (apart from userdict, which additionally needs to be on the initial |
354 | | * dictionary stack). This used to be done in PostScript in gs_init.ps, but |
355 | | * that required the use of .forceput. |
356 | | * This is all complicated by the intention to potentially build the interpreter |
357 | | * supporting only lower versions of PostScript. This could all be simplified |
358 | | * now, since we don't really support that any more. |
359 | | */ |
360 | 926k | for (i = 0; i < countof(initial_referred); i++) { |
361 | 771k | const char *dname = initial_referred[i]; |
362 | 771k | ref *r; |
363 | | |
364 | 771k | r = make_initial_dict(i_ctx_p, dname, idicts); |
365 | 771k | if (r == NULL) |
366 | 0 | return_error(gs_error_VMerror); |
367 | 771k | } |
368 | | |
369 | | /* Set up the initial dstack. */ |
370 | 308k | for (i = 0; i < countof(initial_dstack); i++) { |
371 | 154k | const char *dname = initial_dstack[i]; |
372 | 154k | ref *r; |
373 | | |
374 | 154k | ++dsp; |
375 | 154k | if (!strcmp(dname, "userdict")) |
376 | 154k | dstack_userdict_index = dsp - dsbot; |
377 | 154k | r = make_initial_dict(i_ctx_p, dname, idicts); |
378 | 154k | if (r == NULL) |
379 | 0 | return_error(gs_error_VMerror); |
380 | 154k | ref_assign(dsp, r); |
381 | 154k | } |
382 | | |
383 | | /* Enter names of referenced initial dictionaries into systemdict. */ |
384 | 154k | i_initial_enter_name(i_ctx_p, "systemdict", systemdict); |
385 | 1.69M | for (i = 0; i < icount; i++) { |
386 | 1.54M | ref *idict = &idicts[i]; |
387 | | |
388 | 1.54M | if (!r_has_type(idict, t_null)) { |
389 | | /* |
390 | | * Note that we enter the dictionary in systemdict |
391 | | * even if it is in local VM. There is a special |
392 | | * provision in the garbage collector for this: |
393 | | * see ivmspace.h for more information. |
394 | | * In order to do this, we must temporarily |
395 | | * identify systemdict as local, so that the |
396 | | * store check in dict_put won't fail. |
397 | | */ |
398 | 1.38M | uint save_space = r_space(systemdict); |
399 | | |
400 | 1.38M | r_set_space(systemdict, avm_local); |
401 | 1.38M | code = i_initial_enter_name(i_ctx_p, initial_dictionaries[i].name, |
402 | 1.38M | idict); |
403 | 1.38M | r_set_space(systemdict, save_space); |
404 | 1.38M | if (code < 0) |
405 | 0 | return code; |
406 | 1.38M | } |
407 | 1.54M | } |
408 | 154k | #undef icount |
409 | 154k | } |
410 | | |
411 | 154k | gs_interp_reset(i_ctx_p); |
412 | | |
413 | 154k | { |
414 | 154k | #ifdef PACIFY_VALGRIND |
415 | 154k | ref vnull = { 0 }, vtrue = { 0 }, vfalse = { 0 }; |
416 | | #else |
417 | | ref vnull, vtrue, vfalse; |
418 | | #endif |
419 | | |
420 | 154k | make_null(&vnull); |
421 | 154k | make_true(&vtrue); |
422 | 154k | make_false(&vfalse); |
423 | 154k | if ((code = i_initial_enter_name(i_ctx_p, "null", &vnull)) < 0 || |
424 | 154k | (code = i_initial_enter_name(i_ctx_p, "true", &vtrue)) < 0 || |
425 | 154k | (code = i_initial_enter_name(i_ctx_p, "false", &vfalse)) < 0 |
426 | 154k | ) |
427 | 0 | return code; |
428 | 154k | } |
429 | | |
430 | | /* Create the error name table */ |
431 | 154k | { |
432 | 154k | int n = countof(gs_error_names); |
433 | 154k | int i; |
434 | 154k | ref era; |
435 | | |
436 | 154k | code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames"); |
437 | 154k | if (code < 0) |
438 | 0 | return code; |
439 | 5.09M | for (i = 0; i < n; i++) |
440 | 4.93M | if ((code = name_enter_string(imemory, (const char *)gs_error_names[i], |
441 | 4.93M | era.value.refs + i)) < 0) |
442 | 0 | return code; |
443 | 154k | return i_initial_enter_name(i_ctx_p, "ErrorNames", &era); |
444 | 154k | } |
445 | 154k | } |
446 | | |
447 | | /* Run the initialization procedures of the individual operator files. */ |
448 | | int |
449 | | zop_init(i_ctx_t *i_ctx_p) |
450 | 154k | { |
451 | 154k | const op_def *const *tptr; |
452 | 154k | int code; |
453 | | |
454 | | /* Because of a bug in Sun's SC1.0 compiler, */ |
455 | | /* we have to spell out the typedef for op_def_ptr here: */ |
456 | 154k | const op_def *def; |
457 | | |
458 | 15.9M | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
459 | 121M | for (def = *tptr; def->oname != 0; def++) |
460 | 105M | DO_NOTHING; |
461 | 15.7M | if (def->proc != 0) { |
462 | 617k | code = def->proc(i_ctx_p); |
463 | 617k | if (code < 0) { |
464 | | #ifdef DEBUG |
465 | | lprintf2("op_init proc "PRI_INTPTR" returned error %d!\n", |
466 | | (intptr_t)def->proc, code); |
467 | | #else |
468 | 0 | lprintf("op_init proc returned error !\n"); |
469 | 0 | #endif |
470 | 0 | return code; |
471 | 0 | } |
472 | 617k | } |
473 | 15.7M | } |
474 | | |
475 | | /* Initialize the predefined names other than operators. */ |
476 | | /* Do this here in case op_init changed any of them. */ |
477 | 154k | { |
478 | 154k | ref vcr, vpr, vpf, vre, vrd, vres; |
479 | | |
480 | 154k | make_const_string(&vcr, a_readonly | avm_foreign, |
481 | 154k | strlen(gs_copyright), (const byte *)gs_copyright); |
482 | 154k | make_const_string(&vpr, a_readonly | avm_foreign, |
483 | 154k | strlen(gs_product), (const byte *)gs_product); |
484 | 154k | make_const_string(&vpf, a_readonly | avm_foreign, |
485 | 154k | strlen(gs_productfamily), |
486 | 154k | (const byte *)gs_productfamily); |
487 | 154k | make_const_string(&vres, a_readonly | avm_foreign, |
488 | 154k | strlen(GS_STRINGIZE(GS_DOT_VERSION)), |
489 | 154k | (const byte *)GS_STRINGIZE(GS_DOT_VERSION)); |
490 | 154k | make_int(&vre, gs_revision); |
491 | 154k | make_int(&vrd, gs_revisiondate); |
492 | 154k | if ((code = i_initial_enter_name(i_ctx_p, "copyright", &vcr)) < 0 || |
493 | 154k | (code = i_initial_enter_name(i_ctx_p, "product", &vpr)) < 0 || |
494 | 154k | (code = i_initial_enter_name(i_ctx_p, "productfamily", &vpf)) < 0 || |
495 | 154k | (code = i_initial_enter_name(i_ctx_p, "revision", &vre)) < 0 || |
496 | 154k | (code = i_initial_enter_name(i_ctx_p, "revisiondate", &vrd)) < 0 || |
497 | 154k | (code = i_initial_enter_name(i_ctx_p, ".revisionstring", &vres)) < 0) |
498 | 0 | return code; |
499 | 154k | } |
500 | | |
501 | 154k | return 0; |
502 | 154k | } |
503 | | |
504 | | /* Create an op_array table. */ |
505 | | static int |
506 | | alloc_op_array_table(i_ctx_t *i_ctx_p, uint size, uint space, |
507 | | op_array_table *opt) |
508 | 308k | { |
509 | 308k | uint save_space = ialloc_space(idmemory); |
510 | 308k | int code; |
511 | | |
512 | 308k | ialloc_set_space(idmemory, space); |
513 | 308k | code = ialloc_ref_array(&opt->table, a_readonly, size, |
514 | 308k | "op_array table"); |
515 | 308k | ialloc_set_space(idmemory, save_space); |
516 | 308k | if (code < 0) |
517 | 0 | return code; |
518 | 308k | refset_null(opt->table.value.refs, size); |
519 | 308k | opt->nx_table = |
520 | 308k | (ushort *) ialloc_byte_array(size, sizeof(ushort), |
521 | 308k | "op_array nx_table"); |
522 | 308k | if (opt->nx_table == 0) |
523 | 0 | return_error(gs_error_VMerror); |
524 | 308k | opt->count = 0; |
525 | 308k | opt->attrs = space | a_executable; |
526 | 308k | return 0; |
527 | 308k | } |
528 | | |
529 | | /* Initialize the operator table. */ |
530 | | int |
531 | | op_init(i_ctx_t *i_ctx_p) |
532 | 154k | { |
533 | 154k | const op_def *const *tptr; |
534 | 154k | int code; |
535 | | |
536 | | /* Enter each operator into the appropriate dictionary. */ |
537 | | |
538 | 15.9M | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
539 | 15.7M | ref *pdict = systemdict; |
540 | 15.7M | const op_def *def; |
541 | 15.7M | const char *nstr; |
542 | | |
543 | 121M | for (def = *tptr; (nstr = def->oname) != 0; def++) |
544 | 105M | if (op_def_is_begin_dict(def)) { |
545 | 4.32M | ref nref; |
546 | | |
547 | 4.32M | code = name_ref(imemory, (const byte *)nstr, strlen(nstr), &nref, -1); |
548 | 4.32M | if (code < 0) |
549 | 0 | return code; |
550 | 4.32M | if (!dict_find(systemdict, &nref, &pdict)) |
551 | 0 | return_error(gs_error_Fatal); |
552 | 4.32M | if (!r_has_type(pdict, t_dictionary)) |
553 | 0 | return_error(gs_error_Fatal); |
554 | 101M | } else { |
555 | 101M | ref oper; |
556 | 101M | uint index_in_table = def - *tptr; |
557 | 101M | uint opidx = (tptr - op_defs_all) * OP_DEFS_MAX_SIZE + |
558 | 101M | index_in_table; |
559 | | |
560 | 101M | if (index_in_table >= OP_DEFS_MAX_SIZE) { |
561 | 0 | lprintf1("opdef overrun! %s\n", def->oname); |
562 | 0 | return_error(gs_error_Fatal); |
563 | 0 | } |
564 | 101M | gs_interp_make_oper(&oper, def->proc, opidx); |
565 | | /* The first character of the name is a digit */ |
566 | | /* giving the minimum acceptable number of operands. */ |
567 | | /* Check to make sure it's within bounds. */ |
568 | 101M | if (*nstr - '0' > gs_interp_max_op_num_args) |
569 | 0 | return_error(gs_error_Fatal); |
570 | 101M | nstr++; |
571 | | /* |
572 | | * Skip internal operators, and the second occurrence of |
573 | | * operators with special indices. |
574 | | */ |
575 | 101M | if (*nstr != '%' && r_size(&oper) == opidx) { |
576 | 88.9M | code = |
577 | 88.9M | i_initial_enter_name_in(i_ctx_p, pdict, nstr, &oper); |
578 | 88.9M | if (code < 0) |
579 | 0 | return code; |
580 | 88.9M | } |
581 | 101M | } |
582 | 15.7M | } |
583 | | /* Allocate the tables for `operator' procedures. */ |
584 | | /* Make one of them local so we can have local operators. */ |
585 | 154k | if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_GLOBAL_SIZE, |
586 | 154k | avm_global, |
587 | 154k | &i_ctx_p->op_array_table_global) < 0)) |
588 | 0 | return code; |
589 | 154k | i_ctx_p->op_array_table_global.base_index = op_def_count; |
590 | 154k | if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_LOCAL_SIZE, |
591 | 154k | avm_local, |
592 | 154k | &i_ctx_p->op_array_table_local) < 0)) |
593 | 0 | return code; |
594 | 154k | i_ctx_p->op_array_table_local.base_index = |
595 | 154k | i_ctx_p->op_array_table_global.base_index + |
596 | 154k | r_size(&i_ctx_p->op_array_table_global.table); |
597 | | |
598 | 154k | return 0; |
599 | 154k | } |
600 | | |
601 | | #if defined(DEBUG_TRACE_PS_OPERATORS) || defined(DEBUG) |
602 | | static const char *unknown_op_name = "unknown_op"; |
603 | | |
604 | | const char * |
605 | | op_get_name_string(op_proc_t opproc) |
606 | | { |
607 | | const op_def *const *tptr; |
608 | | |
609 | | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
610 | | const op_def *def; |
611 | | |
612 | | for (def = *tptr; def->oname != 0; def++) |
613 | | if (!op_def_is_begin_dict(def)) { |
614 | | if (def->proc == opproc) |
615 | | return def->oname; |
616 | | } |
617 | | } |
618 | | return unknown_op_name; |
619 | | } |
620 | | #endif |
621 | | |
622 | | int |
623 | | i_iodev_init(gs_dual_memory_t *dmem) |
624 | 154k | { |
625 | 154k | int i; |
626 | 154k | int code; |
627 | 154k | gs_memory_t *mem = (gs_memory_t *)dmem->current; |
628 | | |
629 | 154k | code = gs_iodev_init(mem); |
630 | | |
631 | 1.23M | for (i = 0; i < i_io_device_table_count && code >= 0; i++) { |
632 | 1.08M | code = gs_iodev_register_dev(mem, i_io_device_table[i]); |
633 | 1.08M | } |
634 | | |
635 | 154k | return code; |
636 | 154k | } |
637 | | |
638 | | void |
639 | | i_iodev_finit(gs_dual_memory_t *dmem) |
640 | 154k | { |
641 | 154k | gs_iodev_finit((gs_memory_t *)dmem->current); |
642 | 154k | } |