1 /* Copyright (C) 1989, 1992, 1993, 1999 artofcode LLC.  All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify it
4   under the terms of the GNU General Public License as published by the
5   Free Software Foundation; either version 2 of the License, or (at your
6   option) any later version.
7 
8   This program is distributed in the hope that it will be useful, but
9   WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License along
14   with this program; if not, write to the Free Software Foundation, Inc.,
15   59 Temple Place, Suite 330, Boston, MA, 02111-1307.
16 
17 */
18 
19 /*$Id: zarray.c,v 1.2.6.1.2.1 2003/01/17 00:49:05 giles Exp $ */
20 /* Array operators */
21 #include "memory_.h"
22 #include "ghost.h"
23 #include "ialloc.h"
24 #include "ipacked.h"
25 #include "oper.h"
26 #include "store.h"
27 
28 /* The generic operators (copy, get, put, getinterval, putinterval, */
29 /* length, and forall) are implemented in zgeneric.c. */
30 
31 /* <int> array <array> */
32 int
zarray(i_ctx_t * i_ctx_p)33 zarray(i_ctx_t *i_ctx_p)
34 {
35     os_ptr op = osp;
36     uint size;
37     int code;
38 
39     check_int_leu(*op, max_array_size);
40     size = op->value.intval;
41     code = ialloc_ref_array((ref *)op, a_all, size, "array");
42     if (code < 0)
43 	return code;
44     refset_null(op->value.refs, size);
45     return 0;
46 }
47 
48 /* <array> aload <obj_0> ... <obj_n-1> <array> */
49 private int
zaload(i_ctx_t * i_ctx_p)50 zaload(i_ctx_t *i_ctx_p)
51 {
52     os_ptr op = osp;
53     ref aref;
54     uint asize;
55 
56     ref_assign(&aref, op);
57     if (!r_is_array(&aref))
58 	return_op_typecheck(op);
59     check_read(aref);
60     asize = r_size(&aref);
61     if (asize > ostop - op) {	/* Use the slow, general algorithm. */
62 	int code = ref_stack_push(&o_stack, asize);
63 	uint i;
64 	const ref_packed *packed = aref.value.packed;
65 
66 	if (code < 0)
67 	    return code;
68 	for (i = asize; i > 0; i--, packed = packed_next(packed))
69 	    packed_get(packed, ref_stack_index(&o_stack, i));
70 	*osp = aref;
71 	return 0;
72     }
73     if (r_has_type(&aref, t_array))
74 	memcpy(op, aref.value.refs, asize * sizeof(ref));
75     else {
76 	uint i;
77 	const ref_packed *packed = aref.value.packed;
78 	os_ptr pdest = op;
79 
80 	for (i = 0; i < asize; i++, pdest++, packed = packed_next(packed))
81 	    packed_get(packed, pdest);
82     }
83     push(asize);
84     ref_assign(op, &aref);
85     return 0;
86 }
87 
88 /* <obj_0> ... <obj_n-1> <array> astore <array> */
89 private int
zastore(i_ctx_t * i_ctx_p)90 zastore(i_ctx_t *i_ctx_p)
91 {
92     os_ptr op = osp;
93     uint size;
94     int code;
95 
96     check_write_type(*op, t_array);
97     size = r_size(op);
98     if (size > op - osbot) {
99 	/* The store operation might involve other stack segments. */
100 	ref arr;
101 
102 	if (size >= ref_stack_count(&o_stack))
103 	    return_error(e_stackunderflow);
104 	arr = *op;
105 	code = ref_stack_store(&o_stack, &arr, size, 1, 0, true, idmemory,
106 			       "astore");
107 	if (code < 0)
108 	    return code;
109 	ref_stack_pop(&o_stack, size);
110 	*ref_stack_index(&o_stack, 0) = arr;
111     } else {
112 	code = refcpy_to_old(op, 0, op - size, size, idmemory, "astore");
113 	if (code < 0)
114 	    return code;
115 	op[-(int)size] = *op;
116 	pop(size);
117     }
118     return 0;
119 }
120 
121 /* ------ Initialization procedure ------ */
122 
123 const op_def zarray_op_defs[] =
124 {
125     {"1aload", zaload},
126     {"1array", zarray},
127     {"1astore", zastore},
128     op_def_end(0)
129 };
130