Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
};