Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/gs/src/zgeneric.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | 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: zgeneric.c,v 1.8 2004/08/04 19:36:13 stefan Exp $ */
18
/* Array/string/dictionary generic operators for PostScript */
19
#include "memory_.h"
20
#include "ghost.h"
21
#include "gsstruct.h"		/* for st_bytes */
22
#include "oper.h"
23
#include "dstack.h"		/* for systemdict */
24
#include "estack.h"		/* for forall */
25
#include "iddict.h"
26
#include "iname.h"
27
#include "ipacked.h"
28
#include "ivmspace.h"
29
#include "store.h"
30
 
31
/* This file implements copy, get, put, getinterval, putinterval, */
32
/* length, and forall, which apply generically to */
33
/* arrays, strings, and dictionaries.  (Copy also has a special */
34
/* meaning for copying the top N elements of the stack.) */
35
 
36
/* See the comment in opdef.h for an invariant which allows */
37
/* more efficient implementation of forall. */
38
 
39
/* Forward references */
40
private int zcopy_integer(i_ctx_t *);
41
private int zcopy_interval(i_ctx_t *);
42
private int copy_interval(i_ctx_t *, os_ptr, uint, os_ptr, client_name_t);
43
 
44
/* <various1> <various2> copy <various> */
45
/* <obj1> ... <objn> <int> copy <obj1> ... <objn> <obj1> ... <objn> */
46
/* Note that this implements copy for arrays and strings, */
47
/* but not for dictionaries (see zcopy_dict in zdict.c). */
48
int
49
zcopy(i_ctx_t *i_ctx_p)
50
{
51
    os_ptr op = osp;
52
    int type = r_type(op);
53
 
54
    if (type == t_integer)
55
	return zcopy_integer(i_ctx_p);
56
    check_op(2);
57
    switch (type) {
58
	case t_array:
59
	case t_string:
60
	    return zcopy_interval(i_ctx_p);
61
	case t_dictionary:
62
	    return zcopy_dict(i_ctx_p);
63
	default:
64
	    return_op_typecheck(op);
65
    }
66
}
67
 
68
/* <obj1> ... <objn> <int> copy <obj1> ... <objn> <obj1> ... <objn> */
69
private int
70
zcopy_integer(i_ctx_t *i_ctx_p)
71
{
72
    os_ptr op = osp;
73
    os_ptr op1 = op - 1;
74
    int count, i;
75
    int code;
76
 
77
    if ((ulong) op->value.intval > op - osbot) {
78
	/* There might be enough elements in other blocks. */
79
	check_int_ltu(*op, ref_stack_count(&o_stack));
80
	count = op->value.intval;
81
    } else if (op1 + (count = op->value.intval) <= ostop) {
82
	/* Fast case. */
83
	memcpy((char *)op, (char *)(op - count), count * sizeof(ref));
84
	push(count - 1);
85
	return 0;
86
    }
87
    /* Do it the slow, general way. */
88
    code = ref_stack_push(&o_stack, count - 1);
89
    if (code < 0)
90
	return code;
91
    for (i = 0; i < count; i++)
92
	*ref_stack_index(&o_stack, i) =
93
	    *ref_stack_index(&o_stack, i + count);
94
    return 0;
95
}
96
 
97
/* <array1> <array2> copy <subarray2> */
98
/* <string1> <string2> copy <substring2> */
99
private int
100
zcopy_interval(i_ctx_t *i_ctx_p)
101
{
102
    os_ptr op = osp;
103
    os_ptr op1 = op - 1;
104
    int code = copy_interval(i_ctx_p, op, 0, op1, "copy");
105
 
106
    if (code < 0)
107
	return code;
108
    r_set_size(op, r_size(op1));
109
    *op1 = *op;
110
    pop(1);
111
    return 0;
112
}
113
 
114
/* <array|dict|name|packedarray|string> length <int> */
115
private int
116
zlength(i_ctx_t *i_ctx_p)
117
{
118
    os_ptr op = osp;
119
    switch (r_type(op)) {
120
	case t_array:
121
	case t_string:
122
	case t_mixedarray:
123
	case t_shortarray:
124
	    check_read(*op);
125
	    make_int(op, r_size(op));
126
	    return 0;
127
	case t_dictionary:
128
	    check_dict_read(*op);
129
	    make_int(op, dict_length(op));
130
	    return 0;
131
	case t_name: {
132
	    ref str;
133
 
134
	    name_string_ref(imemory, op, &str);
135
	    make_int(op, r_size(&str));
136
	    return 0;
137
	}
138
	case t_astruct:
139
	    if (gs_object_type(imemory, op->value.pstruct) != &st_bytes)
140
		return_error(e_typecheck);
141
	    check_read(*op);
142
	    make_int(op, gs_object_size(imemory, op->value.pstruct));
143
	    return 0;
144
	default:
145
	    return_op_typecheck(op);
146
    }
147
}
148
 
149
/* <array|packedarray|string> <index> get <obj> */
150
/* <dict> <key> get <obj> */
151
private int
152
zget(i_ctx_t *i_ctx_p)
153
{
154
    os_ptr op = osp;
155
    os_ptr op1 = op - 1;
156
    ref *pvalue;
157
 
158
    switch (r_type(op1)) {
159
	case t_dictionary:
160
	    check_dict_read(*op1);
161
	    if (dict_find(op1, op, &pvalue) <= 0)
162
		return_error(e_undefined);
163
	    op[-1] = *pvalue;
164
	    break;
165
	case t_string:
166
	    check_read(*op1);
167
	    check_int_ltu(*op, r_size(op1));
168
	    make_int(op1, op1->value.bytes[(uint) op->value.intval]);
169
	    break;
170
	default: {
171
	    int code;
172
 
173
	    check_type(*op, t_integer);
174
	    check_read(*op1);
175
	    code = array_get(imemory, op1, op->value.intval, op1);
176
	    if (code < 0) {	/* Might be a stackunderflow reported as typecheck. */
177
		if (code == e_typecheck)
178
		    return_op_typecheck(op1);
179
		else
180
		    return code;
181
	    }
182
	}
183
    }
184
    pop(1);
185
    return 0;
186
}
187
 
188
/* <array> <index> <obj> put - */
189
/* <dict> <key> <value> put - */
190
/* <string> <index> <int> put - */
191
private int
192
zput(i_ctx_t *i_ctx_p)
193
{
194
    os_ptr op = osp;
195
    os_ptr op1 = op - 1;
196
    os_ptr op2 = op1 - 1;
197
    byte *sdata;
198
    uint ssize;
199
 
200
    switch (r_type(op2)) {
201
	case t_dictionary:
202
	    if (i_ctx_p->in_superexec == 0)
203
	    check_dict_write(*op2);
204
	    {
205
		int code = idict_put(op2, op1, op);
206
 
207
		if (code < 0)
208
		    return code;	/* error */
209
	    }
210
	    break;
211
	case t_array:
212
	    check_write(*op2);
213
	    check_int_ltu(*op1, r_size(op2));
214
	    store_check_dest(op2, op);
215
	    {
216
		ref *eltp = op2->value.refs + (uint) op1->value.intval;
217
 
218
		ref_assign_old(op2, eltp, op, "put");
219
	    }
220
	    break;
221
	case t_mixedarray:	/* packed arrays are read-only */
222
	case t_shortarray:
223
	    return_error(e_invalidaccess);
224
	case t_string:
225
	    sdata = op2->value.bytes;
226
	    ssize = r_size(op2);
227
str:	    check_write(*op2);
228
	    check_int_ltu(*op1, ssize);
229
	    check_int_leu(*op, 0xff);
230
	    sdata[(uint)op1->value.intval] = (byte)op->value.intval;
231
	    break;
232
	case t_astruct:
233
	    if (gs_object_type(imemory, op2->value.pstruct) != &st_bytes)
234
		return_error(e_typecheck);
235
	    sdata = r_ptr(op2, byte);
236
	    ssize = gs_object_size(imemory, op2->value.pstruct);
237
	    goto str;
238
	default:
239
	    return_op_typecheck(op2);
240
    }
241
    pop(3);
242
    return 0;
243
}
244
 
245
/* <array> <index> <obj> .forceput - */
246
/* <dict> <key> <value> .forceput - */
247
/*
248
 * This forces a "put" even if the object is not writable, and (if the
249
 * object is systemdict or the save level is 0) even if the value is in
250
 * local VM.  It is meant to be used only for replacing the value of
251
 * FontDirectory in systemdict when switching between local and global VM,
252
 * and a few similar applications.  After initialization, this operator
253
 * should no longer be accessible by name.
254
 */
255
private int
256
zforceput(i_ctx_t *i_ctx_p)
257
{
258
    os_ptr op = osp;
259
    os_ptr op1 = op - 1;
260
    os_ptr op2 = op - 2;
261
    int code;
262
 
263
    switch (r_type(op2)) {
264
    case t_array:
265
	check_int_ltu(*op1, r_size(op2));
266
	if (r_space(op2) > r_space(op)) {
267
	    if (imemory_save_level(iimemory))
268
		return_error(e_invalidaccess);
269
	}
270
	{
271
	    ref *eltp = op2->value.refs + (uint) op1->value.intval;
272
 
273
	    ref_assign_old(op2, eltp, op, "put");
274
	}
275
	break;
276
    case t_dictionary:
277
	if (op2->value.pdict == systemdict->value.pdict ||
278
	    !imemory_save_level(iimemory)
279
	    ) {
280
	    uint space = r_space(op2);
281
 
282
	    r_set_space(op2, avm_local);
283
	    code = idict_put(op2, op1, op);
284
	    r_set_space(op2, space);
285
	} else
286
	    code = idict_put(op2, op1, op);
287
	if (code < 0)
288
	    return code;
289
	break;
290
    default:
291
	return_error(e_typecheck);
292
    }
293
    pop(3);
294
    return 0;
295
}
296
 
297
/* <seq:array|packedarray|string> <index> <count> getinterval <subseq> */
298
private int
299
zgetinterval(i_ctx_t *i_ctx_p)
300
{
301
    os_ptr op = osp;
302
    os_ptr op1 = op - 1;
303
    os_ptr op2 = op1 - 1;
304
    uint index;
305
    uint count;
306
 
307
    switch (r_type(op2)) {
308
	default:
309
	    return_op_typecheck(op2);
310
	case t_array:
311
	case t_string:
312
	case t_mixedarray:
313
	case t_shortarray:;
314
    }
315
    check_read(*op2);
316
    check_int_leu(*op1, r_size(op2));
317
    index = op1->value.intval;
318
    check_int_leu(*op, r_size(op2) - index);
319
    count = op->value.intval;
320
    switch (r_type(op2)) {
321
	case t_array:
322
	    op2->value.refs += index;
323
	    break;
324
	case t_string:
325
	    op2->value.bytes += index;
326
	    break;
327
	case t_mixedarray: {
328
	    const ref_packed *packed = op2->value.packed;
329
 
330
	    for (; index--;)
331
		packed = packed_next(packed);
332
	    op2->value.packed = packed;
333
	    break;
334
	}
335
	case t_shortarray:
336
	    op2->value.packed += index;
337
	    break;
338
    }
339
    r_set_size(op2, count);
340
    pop(2);
341
    return 0;
342
}
343
 
344
/* <array1> <index> <array2|packedarray2> putinterval - */
345
/* <string1> <index> <string2> putinterval - */
346
/* <bytestring1> <index> <string2> putinterval - */
347
private int
348
zputinterval(i_ctx_t *i_ctx_p)
349
{
350
    os_ptr op = osp;
351
    os_ptr opindex = op - 1;
352
    os_ptr opto = opindex - 1;
353
    int code;
354
 
355
    switch (r_type(opto)) {
356
	default:
357
	    return_op_typecheck(opto);
358
	case t_mixedarray:
359
	case t_shortarray:
360
	    return_error(e_invalidaccess);
361
	case t_array:
362
	case t_string:
363
	    check_write(*opto);
364
	    check_int_leu(*opindex, r_size(opto));
365
	    code = copy_interval(i_ctx_p, opto, (uint)(opindex->value.intval),
366
				 op, "putinterval");
367
	    break;
368
	case t_astruct: {
369
	    uint dsize, ssize, index;
370
 
371
	    check_write(*opto);
372
	    if (gs_object_type(imemory, opto->value.pstruct) != &st_bytes)
373
		return_error(e_typecheck);
374
	    dsize = gs_object_size(imemory, opto->value.pstruct);
375
	    check_int_leu(*opindex, dsize);
376
	    index = (uint)opindex->value.intval;
377
	    check_read_type(*op, t_string);
378
	    ssize = r_size(op);
379
	    if (ssize > dsize - index)
380
		return_error(e_rangecheck);
381
	    memcpy(r_ptr(opto, byte) + index, op->value.const_bytes, ssize);
382
	    code = 0;
383
	    break;
384
	}
385
    }
386
    if (code >= 0)
387
	pop(3);
388
    return code;
389
}
390
 
391
/* <array|packedarray|string> <<element> proc> forall - */
392
/* <dict> <<key> <value> proc> forall - */
393
private int
394
    array_continue(i_ctx_t *),
395
    dict_continue(i_ctx_t *),
396
    string_continue(i_ctx_t *),
397
    packedarray_continue(i_ctx_t *);
398
private int forall_cleanup(i_ctx_t *);
399
private int
400
zforall(i_ctx_t *i_ctx_p)
401
{
402
    os_ptr op = osp;
403
    os_ptr obj = op - 1;
404
    es_ptr ep = esp;
405
    es_ptr cproc = ep + 4;
406
 
407
    check_estack(6);
408
    switch (r_type(obj)) {
409
	default:
410
	    return_op_typecheck(obj);
411
	case t_array:
412
	    check_read(*obj);
413
	    make_op_estack(cproc, array_continue);
414
	    break;
415
	case t_dictionary:
416
	    check_dict_read(*obj);
417
	    make_int(cproc, dict_first(obj));
418
	    ++cproc;
419
	    make_op_estack(cproc, dict_continue);
420
	    break;
421
	case t_string:
422
	    check_read(*obj);
423
	    make_op_estack(cproc, string_continue);
424
	    break;
425
	case t_mixedarray:
426
	case t_shortarray:
427
	    check_read(*obj);
428
	    make_op_estack(cproc, packedarray_continue);
429
	    break;
430
    }
431
    check_proc(*op);
432
    /*
433
     * Push:
434
     *   - a mark;
435
     *   - the composite object;
436
     *   - the procedure;
437
     *   - the iteration index (only for dictionaries, done above);
438
     * and invoke the continuation operator.
439
     */
440
    make_mark_estack(ep + 1, es_for, forall_cleanup);
441
    ep[2] = *obj;
442
    ep[3] = *op;
443
    esp = cproc - 1;
444
    pop(2);
445
    return (*real_opproc(cproc))(i_ctx_p);
446
}
447
/* Continuation operator for arrays */
448
private int
449
array_continue(i_ctx_t *i_ctx_p)
450
{
451
    os_ptr op = osp;
452
    es_ptr obj = esp - 1;
453
 
454
    if (r_size(obj)) {		/* continue */
455
	push(1);
456
	r_dec_size(obj, 1);
457
	*op = *obj->value.refs;
458
	obj->value.refs++;
459
	esp += 2;
460
	*esp = obj[1];
461
	return o_push_estack;
462
    } else {			/* done */
463
	esp -= 3;		/* pop mark, object, proc */
464
	return o_pop_estack;
465
    }
466
}
467
/* Continuation operator for dictionaries */
468
private int
469
dict_continue(i_ctx_t *i_ctx_p)
470
{
471
    os_ptr op = osp;
472
    es_ptr obj = esp - 2;
473
    int index = (int)esp->value.intval;
474
 
475
    push(2);			/* make room for key and value */
476
    if ((index = dict_next(obj, index, op - 1)) >= 0) {	/* continue */
477
	esp->value.intval = index;
478
	esp += 2;
479
	*esp = obj[1];
480
	return o_push_estack;
481
    } else {			/* done */
482
	pop(2);			/* undo push */
483
	esp -= 4;		/* pop mark, object, proc, index */
484
	return o_pop_estack;
485
    }
486
}
487
/* Continuation operator for strings */
488
private int
489
string_continue(i_ctx_t *i_ctx_p)
490
{
491
    os_ptr op = osp;
492
    es_ptr obj = esp - 1;
493
 
494
    if (r_size(obj)) {		/* continue */
495
	r_dec_size(obj, 1);
496
	push(1);
497
	make_int(op, *obj->value.bytes);
498
	obj->value.bytes++;
499
	esp += 2;
500
	*esp = obj[1];
501
	return o_push_estack;
502
    } else {			/* done */
503
	esp -= 3;		/* pop mark, object, proc */
504
	return o_pop_estack;
505
    }
506
}
507
/* Continuation operator for packed arrays */
508
private int
509
packedarray_continue(i_ctx_t *i_ctx_p)
510
{
511
    os_ptr op = osp;
512
    es_ptr obj = esp - 1;
513
 
514
    if (r_size(obj)) {		/* continue */
515
	const ref_packed *packed = obj->value.packed;
516
 
517
	r_dec_size(obj, 1);
518
	push(1);
519
	packed_get(imemory, packed, op);
520
	obj->value.packed = packed_next(packed);
521
	esp += 2;
522
	*esp = obj[1];
523
	return o_push_estack;
524
    } else {			/* done */
525
	esp -= 3;		/* pop mark, object, proc */
526
	return o_pop_estack;
527
    }
528
}
529
/* Vacuous cleanup procedure */
530
private int
531
forall_cleanup(i_ctx_t *i_ctx_p)
532
{
533
    return 0;
534
}
535
 
536
/* ------ Initialization procedure ------ */
537
 
538
const op_def zgeneric_op_defs[] =
539
{
540
    {"1copy", zcopy},
541
    {"2forall", zforall},
542
    {"3.forceput", zforceput},
543
    {"2get", zget},
544
    {"3getinterval", zgetinterval},
545
    {"1length", zlength},
546
    {"3put", zput},
547
    {"3putinterval", zputinterval},
548
		/* Internal operators */
549
    {"0%array_continue", array_continue},
550
    {"0%dict_continue", dict_continue},
551
    {"0%packedarray_continue", packedarray_continue},
552
    {"0%string_continue", string_continue},
553
    op_def_end(0)
554
};
555
 
556
/* ------ Shared routines ------ */
557
 
558
/* Copy an interval from one operand to another. */
559
/* This is used by both putinterval and string/array copy. */
560
/* The destination is known to be an array or string, */
561
/* and the starting index is known to be less than or equal to */
562
/* its length; nothing else has been checked. */
563
private int
564
copy_interval(i_ctx_t *i_ctx_p /* for ref_assign_old */, os_ptr prto,
565
	      uint index, os_ptr prfrom, client_name_t cname)
566
{
567
    int fromtype = r_type(prfrom);
568
    uint fromsize = r_size(prfrom);
569
 
570
    if (!(fromtype == r_type(prto) ||
571
	  ((fromtype == t_shortarray || fromtype == t_mixedarray) &&
572
	   r_type(prto) == t_array))
573
	)
574
	return_op_typecheck(prfrom);
575
    check_read(*prfrom);
576
    check_write(*prto);
577
    if (fromsize > r_size(prto) - index)
578
	return_error(e_rangecheck);
579
    switch (fromtype) {
580
	case t_array:
581
	    {			/* We have to worry about aliasing, */
582
		/* but refcpy_to_old takes care of it for us. */
583
		return refcpy_to_old(prto, index, prfrom->value.refs,
584
				     fromsize, idmemory, cname);
585
	    }
586
	case t_string:
587
	    {	/* memmove takes care of aliasing. */
588
		memmove(prto->value.bytes + index, prfrom->value.bytes,
589
			fromsize);
590
	    }
591
	    break;
592
	case t_mixedarray:
593
	case t_shortarray:
594
	    {	/* We don't have to worry about aliasing, because */
595
		/* packed arrays are read-only and hence the destination */
596
		/* can't be a packed array. */
597
		int i;
598
		const ref_packed *packed = prfrom->value.packed;
599
		ref *pdest = prto->value.refs + index;
600
		ref elt;
601
 
602
		for (i = 0; i < fromsize; i++, pdest++) {
603
		    packed_get(imemory, packed, &elt);
604
		    ref_assign_old(prto, pdest, &elt, cname);
605
		    packed = packed_next(packed);
606
		}
607
	    }
608
	    break;
609
    }
610
    return 0;
611
}