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