/src/ghostpdl/psi/iinit.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (C) 2001-2024 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 | 9.22k | # 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 | 18.4k | # define OP_ARRAY_TABLE_SIZE 300 |
74 | | #endif |
75 | | #ifndef OP_ARRAY_TABLE_GLOBAL_SIZE |
76 | 9.22k | # define OP_ARRAY_TABLE_GLOBAL_SIZE OP_ARRAY_TABLE_SIZE |
77 | | #endif |
78 | | #ifndef OP_ARRAY_TABLE_LOCAL_SIZE |
79 | 9.22k | # 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 | 5.50M | { |
95 | 5.50M | int code = idict_put_string(pdict, nstr, pref); |
96 | | |
97 | 5.50M | if (code < 0) |
98 | 0 | lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n", |
99 | 5.50M | code, nstr, dict_length(pdict), dict_maxlength(pdict)); |
100 | 5.50M | return code; |
101 | 5.50M | } |
102 | | int |
103 | | i_initial_enter_name(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref) |
104 | 193k | { |
105 | 193k | return i_initial_enter_name_in(i_ctx_p, systemdict, nstr, pref); |
106 | 193k | } |
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 | 138k | { |
113 | 138k | int code = idict_put_string_copy(pdict, nstr, pref); |
114 | | |
115 | 138k | if (code < 0) |
116 | 0 | lprintf4("initial_enter failed (%d), entering /%s in -dict:%u/%u-\n", |
117 | 138k | code, nstr, dict_length(pdict), dict_maxlength(pdict)); |
118 | 138k | return code; |
119 | 138k | } |
120 | | int |
121 | | i_initial_enter_name_copy(i_ctx_t *i_ctx_p, const char *nstr, const ref * pref) |
122 | 138k | { |
123 | 138k | return i_initial_enter_name_copy_in(i_ctx_p, systemdict, nstr, pref); |
124 | 138k | } |
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 | 9.22k | #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 | 18.4k | { |
184 | 18.4k | const op_def *const *tptr; |
185 | 18.4k | int level = 1; |
186 | | |
187 | 1.89M | for (tptr = op_defs_all; *tptr != 0; ++tptr) { |
188 | 1.88M | const op_def *def; |
189 | | |
190 | 14.4M | for (def = *tptr; def->oname != 0; ++def) |
191 | 12.5M | if (op_def_is_begin_dict(def)) { |
192 | 516k | if (!strcmp(def->oname, "level2dict")) |
193 | 276k | level = max(level, 2); |
194 | 239k | else if (!strcmp(def->oname, "ll3dict")) |
195 | 73.7k | level = max(level, 3); |
196 | 516k | } |
197 | 1.88M | } |
198 | 18.4k | return level; |
199 | 18.4k | } |
200 | | bool |
201 | | gs_have_level2(void) |
202 | 9.22k | { |
203 | 9.22k | return (gs_op_language_level() >= 2); |
204 | 9.22k | } |
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 | 267k | { |
210 | 267k | int i; |
211 | | |
212 | | /* systemdict was created specially. */ |
213 | 267k | if (!strcmp(iname, "systemdict")) |
214 | 9.22k | return systemdict; |
215 | 617k | for (i = 0; i < countof(initial_dictionaries); i++) { |
216 | 617k | const char *dname = initial_dictionaries[i].name; |
217 | 617k | const int dsize = initial_dictionaries[i].size; |
218 | | |
219 | 617k | if (!strcmp(iname, dname)) { |
220 | 258k | ref *dref = &idicts[i]; |
221 | | |
222 | 258k | if (r_has_type(dref, t_null)) { |
223 | 36.8k | gs_ref_memory_t *mem = |
224 | 36.8k | (initial_dictionaries[i].local ? |
225 | 27.6k | iimemory_local : iimemory_global); |
226 | 36.8k | int code = dict_alloc(mem, dsize, dref); |
227 | | |
228 | 36.8k | if (code < 0) |
229 | 0 | return 0; /* disaster */ |
230 | 36.8k | } |
231 | 258k | return dref; |
232 | 258k | } |
233 | 617k | } |
234 | | |
235 | | /* |
236 | | * Name mentioned in some op_def, but not in initial_dictionaries. |
237 | | * Punt. |
238 | | */ |
239 | 0 | return 0; |
240 | 258k | } |
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 | 9.22k | { |
247 | 9.22k | int level = gs_op_language_level(); |
248 | 9.22k | ref system_dict; |
249 | 9.22k | i_ctx_t *i_ctx_p; |
250 | 9.22k | int code; |
251 | | |
252 | | /* |
253 | | * Create systemdict. The context machinery requires that |
254 | | * we do this before initializing the interpreter. |
255 | | */ |
256 | 9.22k | code = dict_alloc(idmem->space_global, |
257 | 9.22k | (level >= 3 ? SYSTEMDICT_LL3_SIZE : |
258 | 9.22k | level >= 2 ? SYSTEMDICT_LEVEL2_SIZE : SYSTEMDICT_SIZE), |
259 | 9.22k | &system_dict); |
260 | 9.22k | if (code < 0) |
261 | 0 | return code; |
262 | | |
263 | | /* Initialize the interpreter. */ |
264 | 9.22k | code = gs_interp_init(pi_ctx_p, &system_dict, idmem); |
265 | 9.22k | if (code < 0) |
266 | 0 | return code; |
267 | 9.22k | i_ctx_p = *pi_ctx_p; |
268 | | |
269 | 9.22k | { |
270 | 55.3k | #define icount countof(initial_dictionaries) |
271 | 9.22k | ref idicts[icount]; |
272 | 9.22k | int i; |
273 | 9.22k | const op_def *const *tptr; |
274 | | |
275 | 9.22k | min_dstack_size = MIN_DSTACK_SIZE; |
276 | | |
277 | 9.22k | refset_null(idicts, icount); |
278 | | |
279 | | /* Put systemdict on the dictionary stack. */ |
280 | 9.22k | if (level >= 2) { |
281 | 9.22k | dsp += 2; |
282 | | /* |
283 | | * For the moment, let globaldict be an alias for systemdict. |
284 | | */ |
285 | 9.22k | dsp[-1] = system_dict; |
286 | 9.22k | min_dstack_size++; |
287 | 9.22k | } else { |
288 | 0 | ++dsp; |
289 | 0 | } |
290 | 9.22k | *dsp = system_dict; |
291 | | |
292 | | /* Create dictionaries which are to be homes for operators. */ |
293 | 949k | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
294 | 940k | const op_def *def; |
295 | | |
296 | 7.23M | for (def = *tptr; def->oname != 0; def++) |
297 | 6.29M | if (op_def_is_begin_dict(def)) { |
298 | 258k | if (make_initial_dict(i_ctx_p, def->oname, idicts) == 0) |
299 | 0 | return_error(gs_error_VMerror); |
300 | 258k | } |
301 | 940k | } |
302 | | |
303 | | /* Set up the initial dstack. */ |
304 | 18.4k | for (i = 0; i < countof(initial_dstack); i++) { |
305 | 9.22k | const char *dname = initial_dstack[i]; |
306 | 9.22k | ref *r; |
307 | | |
308 | 9.22k | ++dsp; |
309 | 9.22k | if (!strcmp(dname, "userdict")) |
310 | 9.22k | dstack_userdict_index = dsp - dsbot; |
311 | 9.22k | r = make_initial_dict(i_ctx_p, dname, idicts); |
312 | 9.22k | if (r == NULL) |
313 | 0 | return_error(gs_error_VMerror); |
314 | 9.22k | ref_assign(dsp, r); |
315 | 9.22k | } |
316 | | |
317 | | /* Enter names of referenced initial dictionaries into systemdict. */ |
318 | 9.22k | i_initial_enter_name(i_ctx_p, "systemdict", systemdict); |
319 | 55.3k | for (i = 0; i < icount; i++) { |
320 | 46.1k | ref *idict = &idicts[i]; |
321 | | |
322 | 46.1k | 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 | 36.8k | uint save_space = r_space(systemdict); |
333 | | |
334 | 36.8k | r_set_space(systemdict, avm_local); |
335 | 36.8k | code = i_initial_enter_name(i_ctx_p, initial_dictionaries[i].name, |
336 | 36.8k | idict); |
337 | 36.8k | r_set_space(systemdict, save_space); |
338 | 36.8k | if (code < 0) |
339 | 0 | return code; |
340 | 36.8k | } |
341 | 46.1k | } |
342 | 9.22k | #undef icount |
343 | 9.22k | } |
344 | | |
345 | 9.22k | gs_interp_reset(i_ctx_p); |
346 | | |
347 | 9.22k | { |
348 | 9.22k | #ifdef PACIFY_VALGRIND |
349 | 9.22k | ref vnull = { 0 }, vtrue = { 0 }, vfalse = { 0 }; |
350 | | #else |
351 | | ref vnull, vtrue, vfalse; |
352 | | #endif |
353 | | |
354 | 9.22k | make_null(&vnull); |
355 | 9.22k | make_true(&vtrue); |
356 | 9.22k | make_false(&vfalse); |
357 | 9.22k | if ((code = i_initial_enter_name(i_ctx_p, "null", &vnull)) < 0 || |
358 | 9.22k | (code = i_initial_enter_name(i_ctx_p, "true", &vtrue)) < 0 || |
359 | 9.22k | (code = i_initial_enter_name(i_ctx_p, "false", &vfalse)) < 0 |
360 | 9.22k | ) |
361 | 0 | return code; |
362 | 9.22k | } |
363 | | |
364 | | /* Create the error name table */ |
365 | 9.22k | { |
366 | 9.22k | int n = countof(gs_error_names); |
367 | 9.22k | int i; |
368 | 9.22k | ref era; |
369 | | |
370 | 9.22k | code = ialloc_ref_array(&era, a_readonly, n, "ErrorNames"); |
371 | 9.22k | if (code < 0) |
372 | 0 | return code; |
373 | 304k | for (i = 0; i < n; i++) |
374 | 295k | if ((code = name_enter_string(imemory, (const char *)gs_error_names[i], |
375 | 295k | era.value.refs + i)) < 0) |
376 | 0 | return code; |
377 | 9.22k | return i_initial_enter_name(i_ctx_p, "ErrorNames", &era); |
378 | 9.22k | } |
379 | 9.22k | } |
380 | | |
381 | | /* Run the initialization procedures of the individual operator files. */ |
382 | | int |
383 | | zop_init(i_ctx_t *i_ctx_p) |
384 | 9.22k | { |
385 | 9.22k | const op_def *const *tptr; |
386 | 9.22k | 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 | 9.22k | const op_def *def; |
391 | | |
392 | 949k | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
393 | 7.23M | for (def = *tptr; def->oname != 0; def++) |
394 | 6.29M | DO_NOTHING; |
395 | 940k | if (def->proc != 0) { |
396 | 36.8k | code = def->proc(i_ctx_p); |
397 | 36.8k | if (code < 0) { |
398 | | #ifdef DEBUG |
399 | | lprintf2("op_init proc "PRI_INTPTR" returned error %d!\n", |
400 | | (intptr_t)def->proc, code); |
401 | | #else |
402 | 0 | lprintf("op_init proc returned error !\n"); |
403 | 0 | #endif |
404 | 0 | return code; |
405 | 0 | } |
406 | 36.8k | } |
407 | 940k | } |
408 | | |
409 | | /* Initialize the predefined names other than operators. */ |
410 | | /* Do this here in case op_init changed any of them. */ |
411 | 9.22k | { |
412 | 9.22k | ref vcr, vpr, vpf, vre, vrd, vres; |
413 | | |
414 | 9.22k | make_const_string(&vcr, a_readonly | avm_foreign, |
415 | 9.22k | strlen(gs_copyright), (const byte *)gs_copyright); |
416 | 9.22k | make_const_string(&vpr, a_readonly | avm_foreign, |
417 | 9.22k | strlen(gs_product), (const byte *)gs_product); |
418 | 9.22k | make_const_string(&vpf, a_readonly | avm_foreign, |
419 | 9.22k | strlen(gs_productfamily), |
420 | 9.22k | (const byte *)gs_productfamily); |
421 | 9.22k | make_const_string(&vres, a_readonly | avm_foreign, |
422 | 9.22k | strlen(GS_STRINGIZE(GS_DOT_VERSION)), |
423 | 9.22k | (const byte *)GS_STRINGIZE(GS_DOT_VERSION)); |
424 | 9.22k | make_int(&vre, gs_revision); |
425 | 9.22k | make_int(&vrd, gs_revisiondate); |
426 | 9.22k | if ((code = i_initial_enter_name(i_ctx_p, "copyright", &vcr)) < 0 || |
427 | 9.22k | (code = i_initial_enter_name(i_ctx_p, "product", &vpr)) < 0 || |
428 | 9.22k | (code = i_initial_enter_name(i_ctx_p, "productfamily", &vpf)) < 0 || |
429 | 9.22k | (code = i_initial_enter_name(i_ctx_p, "revision", &vre)) < 0 || |
430 | 9.22k | (code = i_initial_enter_name(i_ctx_p, "revisiondate", &vrd)) < 0 || |
431 | 9.22k | (code = i_initial_enter_name(i_ctx_p, ".revisionstring", &vres)) < 0) |
432 | 0 | return code; |
433 | 9.22k | } |
434 | | |
435 | 9.22k | return 0; |
436 | 9.22k | } |
437 | | |
438 | | /* Create an op_array table. */ |
439 | | static int |
440 | | alloc_op_array_table(i_ctx_t *i_ctx_p, uint size, uint space, |
441 | | op_array_table *opt) |
442 | 18.4k | { |
443 | 18.4k | uint save_space = ialloc_space(idmemory); |
444 | 18.4k | int code; |
445 | | |
446 | 18.4k | ialloc_set_space(idmemory, space); |
447 | 18.4k | code = ialloc_ref_array(&opt->table, a_readonly, size, |
448 | 18.4k | "op_array table"); |
449 | 18.4k | ialloc_set_space(idmemory, save_space); |
450 | 18.4k | if (code < 0) |
451 | 0 | return code; |
452 | 18.4k | refset_null(opt->table.value.refs, size); |
453 | 18.4k | opt->nx_table = |
454 | 18.4k | (ushort *) ialloc_byte_array(size, sizeof(ushort), |
455 | 18.4k | "op_array nx_table"); |
456 | 18.4k | if (opt->nx_table == 0) |
457 | 0 | return_error(gs_error_VMerror); |
458 | 18.4k | opt->count = 0; |
459 | 18.4k | opt->attrs = space | a_executable; |
460 | 18.4k | return 0; |
461 | 18.4k | } |
462 | | |
463 | | /* Initialize the operator table. */ |
464 | | int |
465 | | op_init(i_ctx_t *i_ctx_p) |
466 | 9.22k | { |
467 | 9.22k | const op_def *const *tptr; |
468 | 9.22k | int code; |
469 | | |
470 | | /* Enter each operator into the appropriate dictionary. */ |
471 | | |
472 | 949k | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
473 | 940k | ref *pdict = systemdict; |
474 | 940k | const op_def *def; |
475 | 940k | const char *nstr; |
476 | | |
477 | 7.23M | for (def = *tptr; (nstr = def->oname) != 0; def++) |
478 | 6.29M | if (op_def_is_begin_dict(def)) { |
479 | 258k | ref nref; |
480 | | |
481 | 258k | code = name_ref(imemory, (const byte *)nstr, strlen(nstr), &nref, -1); |
482 | 258k | if (code < 0) |
483 | 0 | return code; |
484 | 258k | if (!dict_find(systemdict, &nref, &pdict)) |
485 | 0 | return_error(gs_error_Fatal); |
486 | 258k | if (!r_has_type(pdict, t_dictionary)) |
487 | 0 | return_error(gs_error_Fatal); |
488 | 6.03M | } else { |
489 | 6.03M | ref oper; |
490 | 6.03M | uint index_in_table = def - *tptr; |
491 | 6.03M | uint opidx = (tptr - op_defs_all) * OP_DEFS_MAX_SIZE + |
492 | 6.03M | index_in_table; |
493 | | |
494 | 6.03M | if (index_in_table >= OP_DEFS_MAX_SIZE) { |
495 | 0 | lprintf1("opdef overrun! %s\n", def->oname); |
496 | 0 | return_error(gs_error_Fatal); |
497 | 0 | } |
498 | 6.03M | gs_interp_make_oper(&oper, def->proc, opidx); |
499 | | /* The first character of the name is a digit */ |
500 | | /* giving the minimum acceptable number of operands. */ |
501 | | /* Check to make sure it's within bounds. */ |
502 | 6.03M | if (*nstr - '0' > gs_interp_max_op_num_args) |
503 | 0 | return_error(gs_error_Fatal); |
504 | 6.03M | nstr++; |
505 | | /* |
506 | | * Skip internal operators, and the second occurrence of |
507 | | * operators with special indices. |
508 | | */ |
509 | 6.03M | if (*nstr != '%' && r_size(&oper) == opidx) { |
510 | 5.31M | code = |
511 | 5.31M | i_initial_enter_name_in(i_ctx_p, pdict, nstr, &oper); |
512 | 5.31M | if (code < 0) |
513 | 0 | return code; |
514 | 5.31M | } |
515 | 6.03M | } |
516 | 940k | } |
517 | | /* Allocate the tables for `operator' procedures. */ |
518 | | /* Make one of them local so we can have local operators. */ |
519 | 9.22k | if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_GLOBAL_SIZE, |
520 | 9.22k | avm_global, |
521 | 9.22k | &i_ctx_p->op_array_table_global) < 0)) |
522 | 0 | return code; |
523 | 9.22k | i_ctx_p->op_array_table_global.base_index = op_def_count; |
524 | 9.22k | if ((code = alloc_op_array_table(i_ctx_p, OP_ARRAY_TABLE_LOCAL_SIZE, |
525 | 9.22k | avm_local, |
526 | 9.22k | &i_ctx_p->op_array_table_local) < 0)) |
527 | 0 | return code; |
528 | 9.22k | i_ctx_p->op_array_table_local.base_index = |
529 | 9.22k | i_ctx_p->op_array_table_global.base_index + |
530 | 9.22k | r_size(&i_ctx_p->op_array_table_global.table); |
531 | | |
532 | 9.22k | return 0; |
533 | 9.22k | } |
534 | | |
535 | | #if defined(DEBUG_TRACE_PS_OPERATORS) || defined(DEBUG) |
536 | | static const char *unknown_op_name = "unknown_op"; |
537 | | |
538 | | const char * |
539 | | op_get_name_string(op_proc_t opproc) |
540 | | { |
541 | | const op_def *const *tptr; |
542 | | |
543 | | for (tptr = op_defs_all; *tptr != 0; tptr++) { |
544 | | const op_def *def; |
545 | | |
546 | | for (def = *tptr; def->oname != 0; def++) |
547 | | if (!op_def_is_begin_dict(def)) { |
548 | | if (def->proc == opproc) |
549 | | return def->oname; |
550 | | } |
551 | | } |
552 | | return unknown_op_name; |
553 | | } |
554 | | #endif |
555 | | |
556 | | int |
557 | | i_iodev_init(gs_dual_memory_t *dmem) |
558 | 9.22k | { |
559 | 9.22k | int i; |
560 | 9.22k | int code; |
561 | 9.22k | gs_memory_t *mem = (gs_memory_t *)dmem->current; |
562 | | |
563 | 9.22k | code = gs_iodev_init(mem); |
564 | | |
565 | 73.7k | for (i = 0; i < i_io_device_table_count && code >= 0; i++) { |
566 | 64.5k | code = gs_iodev_register_dev(mem, i_io_device_table[i]); |
567 | 64.5k | } |
568 | | |
569 | 9.22k | return code; |
570 | 9.22k | } |
571 | | |
572 | | void |
573 | | i_iodev_finit(gs_dual_memory_t *dmem) |
574 | 9.22k | { |
575 | 9.22k | gs_iodev_finit((gs_memory_t *)dmem->current); |
576 | 9.22k | } |