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