xref: /plan9/sys/src/cmd/gs/src/zarray.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1989, 1992, 1993, 1999 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: zarray.c,v 1.5 2004/08/04 19:36:13 stefan Exp $ */
18 /* Array operators */
19 #include "memory_.h"
20 #include "ghost.h"
21 #include "ialloc.h"
22 #include "ipacked.h"
23 #include "oper.h"
24 #include "store.h"
25 
26 /* The generic operators (copy, get, put, getinterval, putinterval, */
27 /* length, and forall) are implemented in zgeneric.c. */
28 
29 /* <int> array <array> */
30 int
zarray(i_ctx_t * i_ctx_p)31 zarray(i_ctx_t *i_ctx_p)
32 {
33     os_ptr op = osp;
34     uint size;
35     int code;
36 
37     check_int_leu(*op, max_array_size);
38     size = op->value.intval;
39     code = ialloc_ref_array((ref *)op, a_all, size, "array");
40     if (code < 0)
41 	return code;
42     refset_null(op->value.refs, size);
43     return 0;
44 }
45 
46 /* <array> aload <obj_0> ... <obj_n-1> <array> */
47 private int
zaload(i_ctx_t * i_ctx_p)48 zaload(i_ctx_t *i_ctx_p)
49 {
50     os_ptr op = osp;
51     ref aref;
52     uint asize;
53 
54     ref_assign(&aref, op);
55     if (!r_is_array(&aref))
56 	return_op_typecheck(op);
57     check_read(aref);
58     asize = r_size(&aref);
59     if (asize > ostop - op) {	/* Use the slow, general algorithm. */
60 	int code = ref_stack_push(&o_stack, asize);
61 	uint i;
62 	const ref_packed *packed = aref.value.packed;
63 
64 	if (code < 0)
65 	    return code;
66 	for (i = asize; i > 0; i--, packed = packed_next(packed))
67 	    packed_get(imemory, packed, ref_stack_index(&o_stack, i));
68 	*osp = aref;
69 	return 0;
70     }
71     if (r_has_type(&aref, t_array))
72 	memcpy(op, aref.value.refs, asize * sizeof(ref));
73     else {
74 	uint i;
75 	const ref_packed *packed = aref.value.packed;
76 	os_ptr pdest = op;
77 
78 	for (i = 0; i < asize; i++, pdest++, packed = packed_next(packed))
79 	    packed_get(imemory, packed, pdest);
80     }
81     push(asize);
82     ref_assign(op, &aref);
83     return 0;
84 }
85 
86 /* <obj_0> ... <obj_n-1> <array> astore <array> */
87 private int
zastore(i_ctx_t * i_ctx_p)88 zastore(i_ctx_t *i_ctx_p)
89 {
90     os_ptr op = osp;
91     uint size;
92     int code;
93 
94     check_write_type(*op, t_array);
95     size = r_size(op);
96     if (size > op - osbot) {
97 	/* The store operation might involve other stack segments. */
98 	ref arr;
99 
100 	if (size >= ref_stack_count(&o_stack))
101 	    return_error(e_stackunderflow);
102 	arr = *op;
103 	code = ref_stack_store(&o_stack, &arr, size, 1, 0, true, idmemory,
104 			       "astore");
105 	if (code < 0)
106 	    return code;
107 	ref_stack_pop(&o_stack, size);
108 	*ref_stack_index(&o_stack, 0) = arr;
109     } else {
110 	code = refcpy_to_old(op, 0, op - size, size, idmemory, "astore");
111 	if (code < 0)
112 	    return code;
113 	op[-(int)size] = *op;
114 	pop(size);
115     }
116     return 0;
117 }
118 
119 /* ------ Initialization procedure ------ */
120 
121 const op_def zarray_op_defs[] =
122 {
123     {"1aload", zaload},
124     {"1array", zarray},
125     {"1astore", zastore},
126     op_def_end(0)
127 };
128