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