1 /* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved.
2
3 This software is provided AS-IS with no warranty, either express or
4 implied.
5
6 This software is distributed under license and may not be copied,
7 modified or distributed except as expressly authorized under the terms
8 of the license contained in the file LICENSE in this distribution.
9
10 For more information about licensing, please refer to
11 http://www.ghostscript.com/licensing/. For information on
12 commercial licensing, go to http://www.artifex.com/licensing/ or
13 contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14 San Rafael, CA 94903, U.S.A., +1(415)492-9861.
15 */
16
17 /* $Id: zdict.c,v 1.6 2004/08/04 19:36:13 stefan Exp $ */
18 /* Dictionary operators */
19 #include "ghost.h"
20 #include "oper.h"
21 #include "iddict.h"
22 #include "dstack.h"
23 #include "ilevel.h" /* for [count]dictstack */
24 #include "iname.h" /* for dict_find_name */
25 #include "ipacked.h" /* for inline dict lookup */
26 #include "ivmspace.h"
27 #include "store.h"
28
29 /* <int> dict <dict> */
30 int
zdict(i_ctx_t * i_ctx_p)31 zdict(i_ctx_t *i_ctx_p)
32 {
33 os_ptr op = osp;
34
35 check_type(*op, t_integer);
36 #if arch_sizeof_int < arch_sizeof_long
37 check_int_leu(*op, max_uint);
38 #else
39 if (op->value.intval < 0)
40 return_error(e_rangecheck);
41 #endif
42 return dict_create((uint) op->value.intval, op);
43 }
44
45 /* <dict> maxlength <int> */
46 private int
zmaxlength(i_ctx_t * i_ctx_p)47 zmaxlength(i_ctx_t *i_ctx_p)
48 {
49 os_ptr op = osp;
50
51 check_type(*op, t_dictionary);
52 check_dict_read(*op);
53 make_int(op, dict_maxlength(op));
54 return 0;
55 }
56
57 /* <dict> begin - */
58 int
zbegin(i_ctx_t * i_ctx_p)59 zbegin(i_ctx_t *i_ctx_p)
60 {
61 os_ptr op = osp;
62
63 check_type(*op, t_dictionary);
64 check_dict_read(*op);
65 if (dsp == dstop)
66 return_error(e_dictstackoverflow);
67 ++dsp;
68 ref_assign(dsp, op);
69 dict_set_top();
70 pop(1);
71 return 0;
72 }
73
74 /* - end - */
75 int
zend(i_ctx_t * i_ctx_p)76 zend(i_ctx_t *i_ctx_p)
77 {
78 if (ref_stack_count_inline(&d_stack) == min_dstack_size) {
79 /* We would underflow the d-stack. */
80 return_error(e_dictstackunderflow);
81 }
82 while (dsp == dsbot) {
83 /* We would underflow the current block. */
84 ref_stack_pop_block(&d_stack);
85 }
86 dsp--;
87 dict_set_top();
88 return 0;
89 }
90
91 /* <key> <value> def - */
92 /*
93 * We make this into a separate procedure because
94 * the interpreter will almost always call it directly.
95 */
96 int
zop_def(i_ctx_t * i_ctx_p)97 zop_def(i_ctx_t *i_ctx_p)
98 {
99 os_ptr op = osp;
100 os_ptr op1 = op - 1;
101 ref *pvslot;
102
103 /* The following combines a check_op(2) with a type check. */
104 switch (r_type(op1)) {
105 case t_name: {
106 /* We can use the fast single-probe lookup here. */
107 uint nidx = name_index(imemory, op1);
108 uint htemp;
109
110 if_dict_find_name_by_index_top(nidx, htemp, pvslot) {
111 if (dtop_can_store(op))
112 goto ra;
113 }
114 break; /* handle all slower cases */
115 }
116 case t_null:
117 return_error(e_typecheck);
118 case t__invalid:
119 return_error(e_stackunderflow);
120 }
121 /*
122 * Combine the check for a writable top dictionary with
123 * the global/local store check. See dstack.h for details.
124 */
125 if (!dtop_can_store(op)) {
126 check_dict_write(*dsp);
127 /*
128 * If the dictionary is writable, the problem must be
129 * an invalid store.
130 */
131 return_error(e_invalidaccess);
132 }
133 /*
134 * Save a level of procedure call in the common (redefinition)
135 * case. With the current interfaces, we pay a double lookup
136 * in the uncommon case.
137 */
138 if (dict_find(dsp, op1, &pvslot) <= 0)
139 return idict_put(dsp, op1, op);
140 ra:
141 ref_assign_old_inline(&dsp->value.pdict->values, pvslot, op,
142 "dict_put(value)");
143 return 0;
144 }
145 int
zdef(i_ctx_t * i_ctx_p)146 zdef(i_ctx_t *i_ctx_p)
147 {
148 int code = zop_def(i_ctx_p);
149
150 if (code >= 0) {
151 pop(2);
152 }
153 return code;
154 }
155
156 /* <key> load <value> */
157 private int
zload(i_ctx_t * i_ctx_p)158 zload(i_ctx_t *i_ctx_p)
159 {
160 os_ptr op = osp;
161 ref *pvalue;
162
163 switch (r_type(op)) {
164 case t_name:
165 /* Use the fast lookup. */
166 if ((pvalue = dict_find_name(op)) == 0)
167 return_error(e_undefined);
168 ref_assign(op, pvalue);
169 return 0;
170 case t_null:
171 return_error(e_typecheck);
172 case t__invalid:
173 return_error(e_stackunderflow);
174 default: {
175 /* Use an explicit loop. */
176 uint size = ref_stack_count(&d_stack);
177 uint i;
178
179 for (i = 0; i < size; i++) {
180 ref *dp = ref_stack_index(&d_stack, i);
181
182 check_dict_read(*dp);
183 if (dict_find(dp, op, &pvalue) > 0) {
184 ref_assign(op, pvalue);
185 return 0;
186 }
187 }
188 return_error(e_undefined);
189 }
190 }
191 }
192
193 /* get - implemented in zgeneric.c */
194
195 /* put - implemented in zgeneric.c */
196
197 /* <dict> <key> .undef - */
198 /* <dict> <key> undef - */
199 private int
zundef(i_ctx_t * i_ctx_p)200 zundef(i_ctx_t *i_ctx_p)
201 {
202 os_ptr op = osp;
203
204 check_type(op[-1], t_dictionary);
205 check_dict_write(op[-1]);
206 idict_undef(op - 1, op); /* ignore undefined error */
207 pop(2);
208 return 0;
209 }
210
211 /* <dict> <key> known <bool> */
212 private int
zknown(i_ctx_t * i_ctx_p)213 zknown(i_ctx_t *i_ctx_p)
214 {
215 os_ptr op = osp;
216 register os_ptr op1 = op - 1;
217 ref *pvalue;
218
219 check_type(*op1, t_dictionary);
220 check_dict_read(*op1);
221 make_bool(op1, (dict_find(op1, op, &pvalue) > 0 ? 1 : 0));
222 pop(1);
223 return 0;
224 }
225
226 /* <key> where <dict> true */
227 /* <key> where false */
228 int
zwhere(i_ctx_t * i_ctx_p)229 zwhere(i_ctx_t *i_ctx_p)
230 {
231 os_ptr op = osp;
232 ref_stack_enum_t rsenum;
233
234 check_op(1);
235 ref_stack_enum_begin(&rsenum, &d_stack);
236 do {
237 const ref *const bot = rsenum.ptr;
238 const ref *pdref = bot + rsenum.size;
239 ref *pvalue;
240
241 while (pdref-- > bot) {
242 check_dict_read(*pdref);
243 if (dict_find(pdref, op, &pvalue) > 0) {
244 push(1);
245 ref_assign(op - 1, pdref);
246 make_true(op);
247 return 0;
248 }
249 }
250 } while (ref_stack_enum_next(&rsenum));
251 make_false(op);
252 return 0;
253 }
254
255 /* copy for dictionaries -- called from zcopy in zgeneric.c. */
256 /* Only the type of *op has been checked. */
257 int
zcopy_dict(i_ctx_t * i_ctx_p)258 zcopy_dict(i_ctx_t *i_ctx_p)
259 {
260 os_ptr op = osp;
261 os_ptr op1 = op - 1;
262 int code;
263
264 check_type(*op1, t_dictionary);
265 check_dict_read(*op1);
266 check_dict_write(*op);
267 if (!imemory->gs_lib_ctx->dict_auto_expand &&
268 (dict_length(op) != 0 || dict_maxlength(op) < dict_length(op1))
269 )
270 return_error(e_rangecheck);
271 code = idict_copy(op1, op);
272 if (code < 0)
273 return code;
274 /*
275 * In Level 1 systems, we must copy the access attributes too.
276 * The only possible effect this can have is to make the
277 * copy read-only if the original dictionary is read-only.
278 */
279 if (!level2_enabled)
280 r_copy_attrs(dict_access_ref(op), a_write, dict_access_ref(op1));
281 ref_assign(op1, op);
282 pop(1);
283 return 0;
284 }
285
286 /* - currentdict <dict> */
287 private int
zcurrentdict(i_ctx_t * i_ctx_p)288 zcurrentdict(i_ctx_t *i_ctx_p)
289 {
290 os_ptr op = osp;
291
292 push(1);
293 ref_assign(op, dsp);
294 return 0;
295 }
296
297 /* - countdictstack <int> */
298 private int
zcountdictstack(i_ctx_t * i_ctx_p)299 zcountdictstack(i_ctx_t *i_ctx_p)
300 {
301 os_ptr op = osp;
302 uint count = ref_stack_count(&d_stack);
303
304 push(1);
305 if (!level2_enabled)
306 count--; /* see dstack.h */
307 make_int(op, count);
308 return 0;
309 }
310
311 /* <array> dictstack <subarray> */
312 private int
zdictstack(i_ctx_t * i_ctx_p)313 zdictstack(i_ctx_t *i_ctx_p)
314 {
315 os_ptr op = osp;
316 uint count = ref_stack_count(&d_stack);
317
318 check_write_type(*op, t_array);
319 if (!level2_enabled)
320 count--; /* see dstack.h */
321 return ref_stack_store(&d_stack, op, count, 0, 0, true, idmemory,
322 "dictstack");
323 }
324
325 /* - cleardictstack - */
326 private int
zcleardictstack(i_ctx_t * i_ctx_p)327 zcleardictstack(i_ctx_t *i_ctx_p)
328 {
329 while (zend(i_ctx_p) >= 0)
330 DO_NOTHING;
331 return 0;
332 }
333
334 /* ------ Extensions ------ */
335
336 /* <dict1> <dict2> .dictcopynew <dict2> */
337 private int
zdictcopynew(i_ctx_t * i_ctx_p)338 zdictcopynew(i_ctx_t *i_ctx_p)
339 {
340 os_ptr op = osp;
341 os_ptr op1 = op - 1;
342 int code;
343
344 check_type(*op1, t_dictionary);
345 check_dict_read(*op1);
346 check_type(*op, t_dictionary);
347 check_dict_write(*op);
348 /* This is only recognized in Level 2 mode. */
349 if (!imemory->gs_lib_ctx->dict_auto_expand)
350 return_error(e_undefined);
351 code = idict_copy_new(op1, op);
352 if (code < 0)
353 return code;
354 ref_assign(op1, op);
355 pop(1);
356 return 0;
357 }
358
359 /* -mark- <key0> <value0> <key1> <value1> ... .dicttomark <dict> */
360 /* This is the Level 2 >> operator. */
361 private int
zdicttomark(i_ctx_t * i_ctx_p)362 zdicttomark(i_ctx_t *i_ctx_p)
363 {
364 uint count2 = ref_stack_counttomark(&o_stack);
365 ref rdict;
366 int code;
367 uint idx;
368
369 if (count2 == 0)
370 return_error(e_unmatchedmark);
371 count2--;
372 if ((count2 & 1) != 0)
373 return_error(e_rangecheck);
374 code = dict_create(count2 >> 1, &rdict);
375 if (code < 0)
376 return code;
377 /* << /a 1 /a 2 >> => << /a 1 >>, i.e., */
378 /* we must enter the keys in top-to-bottom order. */
379 for (idx = 0; idx < count2; idx += 2) {
380 code = idict_put(&rdict,
381 ref_stack_index(&o_stack, idx + 1),
382 ref_stack_index(&o_stack, idx));
383 if (code < 0) { /* There's no way to free the dictionary -- too bad. */
384 return code;
385 }
386 }
387 ref_stack_pop(&o_stack, count2);
388 ref_assign(osp, &rdict);
389 return code;
390 }
391
392 /* <dict> <key> .forceundef - */
393 /*
394 * This forces an "undef" even if the dictionary is not writable.
395 * Like .forceput, it is meant to be used only in a few special situations,
396 * and should not be accessible by name after initialization.
397 */
398 private int
zforceundef(i_ctx_t * i_ctx_p)399 zforceundef(i_ctx_t *i_ctx_p)
400 {
401 os_ptr op = osp;
402
403 check_type(op[-1], t_dictionary);
404 /* Don't check_dict_write */
405 idict_undef(op - 1, op); /* ignore undefined error */
406 pop(2);
407 return 0;
408 }
409
410 /* <dict> <key> .knownget <value> true */
411 /* <dict> <key> .knownget false */
412 private int
zknownget(i_ctx_t * i_ctx_p)413 zknownget(i_ctx_t *i_ctx_p)
414 {
415 os_ptr op = osp;
416 register os_ptr op1 = op - 1;
417 ref *pvalue;
418
419 check_type(*op1, t_dictionary);
420 check_dict_read(*op1);
421 if (dict_find(op1, op, &pvalue) <= 0) {
422 make_false(op1);
423 pop(1);
424 } else {
425 ref_assign(op1, pvalue);
426 make_true(op);
427 }
428 return 0;
429 }
430
431 /* <dict> <key> .knownundef <bool> */
432 private int
zknownundef(i_ctx_t * i_ctx_p)433 zknownundef(i_ctx_t *i_ctx_p)
434 {
435 os_ptr op = osp;
436 os_ptr op1 = op - 1;
437 int code;
438
439 check_type(*op1, t_dictionary);
440 check_dict_write(*op1);
441 code = idict_undef(op1, op);
442 make_bool(op1, code == 0);
443 pop(1);
444 return 0;
445 }
446
447 /* <dict> <int> .setmaxlength - */
448 private int
zsetmaxlength(i_ctx_t * i_ctx_p)449 zsetmaxlength(i_ctx_t *i_ctx_p)
450 {
451 os_ptr op = osp;
452 os_ptr op1 = op - 1;
453 uint new_size;
454 int code;
455
456 check_type(*op1, t_dictionary);
457 check_dict_write(*op1);
458 check_type(*op, t_integer);
459 #if arch_sizeof_int < arch_sizeof_long
460 check_int_leu(*op, max_uint);
461 #else
462 if (op->value.intval < 0)
463 return_error(e_rangecheck);
464 #endif
465 new_size = (uint) op->value.intval;
466 if (dict_length(op - 1) > new_size)
467 return_error(e_dictfull);
468 code = idict_resize(op - 1, new_size);
469 if (code >= 0)
470 pop(2);
471 return code;
472 }
473
474 /* ------ Initialization procedure ------ */
475
476 /* We need to split the table because of the 16-element limit. */
477 const op_def zdict1_op_defs[] = {
478 {"0cleardictstack", zcleardictstack},
479 {"1begin", zbegin},
480 {"0countdictstack", zcountdictstack},
481 {"0currentdict", zcurrentdict},
482 {"2def", zdef},
483 {"1dict", zdict},
484 {"0dictstack", zdictstack},
485 {"0end", zend},
486 {"2known", zknown},
487 {"1load", zload},
488 {"1maxlength", zmaxlength},
489 {"2.undef", zundef}, /* we need this even in Level 1 */
490 {"1where", zwhere},
491 op_def_end(0)
492 };
493 const op_def zdict2_op_defs[] = {
494 /* Extensions */
495 {"2.dictcopynew", zdictcopynew},
496 {"1.dicttomark", zdicttomark},
497 {"2.forceundef", zforceundef},
498 {"2.knownget", zknownget},
499 {"1.knownundef", zknownundef},
500 {"2.setmaxlength", zsetmaxlength},
501 op_def_end(0)
502 };
503