xref: /titanic_52/usr/src/lib/efcode/engine/actions.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <string.h>
31 
32 #include <fcode/private.h>
33 #include <fcode/log.h>
34 
35 #define	NUM_DEFAULT_ACTIONS	7
36 
37 /*
38  * value_fetch and value_store are the same as "fetch" and "store", but
39  * we'll leave them implemented here for now.
40  */
41 static void
42 value_fetch(fcode_env_t *env)
43 {
44 	variable_t *addr;
45 
46 	CHECK_DEPTH(env, 1, "value_fetch");
47 	addr = (variable_t *)POP(DS);
48 	PUSH(DS, (variable_t)*addr);
49 }
50 
51 static void
52 value_store(fcode_env_t *env)
53 {
54 	variable_t *addr;
55 
56 	CHECK_DEPTH(env, 1, "value_store");
57 	addr = (variable_t *)POP(DS);
58 	*addr = (variable_t)POP(DS);
59 }
60 
61 void *
62 get_internal_address(fcode_env_t *env)
63 {
64 	int *ptr;
65 
66 	CHECK_DEPTH(env, 1, "get_internal_address");
67 	ptr = (int *)POP(DS);
68 	if (*ptr > 0)
69 		return ((uchar_t *)env + *ptr);
70 	return ((uchar_t *)MYSELF - *ptr);
71 }
72 
73 void
74 internal_env_fetch(fcode_env_t *env)
75 {
76 	instance_t **iptr;
77 
78 	CHECK_DEPTH(env, 1, "internal_env_fetch");
79 	iptr = (instance_t **)get_internal_address(env);
80 	PUSH(DS, (fstack_t)(*iptr));
81 }
82 
83 void
84 internal_env_store(fcode_env_t *env)
85 {
86 	instance_t **iptr;
87 
88 	CHECK_DEPTH(env, 2, "internal_env_store");
89 	iptr = (instance_t **)get_internal_address(env);
90 	*iptr = (instance_t *)POP(DS);
91 }
92 
93 void
94 internal_env_addr(fcode_env_t *env)
95 {
96 	fstack_t d;
97 
98 	CHECK_DEPTH(env, 1, "internal_env_addr");
99 	d = (fstack_t)get_internal_address(env);
100 	PUSH(DS, d);
101 }
102 
103 void
104 do_buffer_data(fcode_env_t *env, token_t *d, int instance)
105 {
106 	if (!*d) {	/* check if buffer not alloc'ed yet */
107 		token_t *buf;
108 
109 		if (instance) {
110 			int n, off;
111 
112 			n = TOKEN_ROUNDUP(d[1]);
113 			buf = alloc_instance_data(env, UINIT_DATA, n, &off);
114 			memset(buf, 0, d[1]);
115 		} else {
116 			buf = (token_t *)HERE;
117 			set_here(env, HERE + d[1], "do_buffer_data");
118 		}
119 		*d = (token_t)buf;
120 	}
121 	PUSH(DS, *d);
122 }
123 
124 void
125 ibuffer_init(fcode_env_t *env)
126 {
127 	token_t *d;
128 
129 	d = get_instance_address(env);
130 	do_buffer_data(env, d, 1);
131 }
132 
133 void
134 buffer_init(fcode_env_t *env)
135 {
136 	token_t *d;
137 
138 	CHECK_DEPTH(env, 1, "buffer_init");
139 	d = (token_t *)POP(DS);
140 	do_buffer_data(env, d, 0);
141 }
142 
143 void
144 do_defer(fcode_env_t *env)
145 {
146 	fetch(env);
147 	execute(env);
148 }
149 
150 token_t *value_actions[NUM_DEFAULT_ACTIONS];
151 token_t value_defines[NUM_DEFAULT_ACTIONS][3] = {
152 	{ (token_t)&value_fetch, (token_t)&value_store, (token_t)&noop },
153 	{ (token_t)&fetch_instance_data, (token_t)&set_instance_data,
154 	    (token_t)&address_instance_data },
155 	{ (token_t)&internal_env_fetch, (token_t)&internal_env_store,
156 	    (token_t)&internal_env_addr },
157 	{ (token_t)&do_defer, (token_t)&store, (token_t)&noop },
158 	{ (token_t)&idefer_exec, (token_t)&set_instance_data,
159 	    (token_t)&address_instance_data },
160 	{ (token_t)&buffer_init, (token_t)&two_drop, (token_t)&noop, },
161 	{ (token_t)&ibuffer_init, (token_t)&two_drop,
162 	    (token_t)&address_instance_data }
163 };
164 
165 int
166 run_action(fcode_env_t *env, acf_t acf, int action)
167 {
168 	token_t *p = (token_t *)acf;
169 
170 	if ((p[0] & 1) == 0) {
171 		log_message(MSG_WARN, "run_action: acf: %p @acf: %p not"
172 		    " indirect\n", acf, p[0]);
173 		return (1);
174 	}
175 
176 	p = (token_t *)(p[0] & ~1);
177 
178 	if (action >= p[1] || action < 0) {
179 		log_message(MSG_WARN, "run_action: acf: %p action: %d"
180 		    " out of range: 0-%d\n", acf, action, (int)p[1]);
181 		return (1);
182 	}
183 
184 	if (p[0] == (token_t)&do_default_action) {
185 		fstack_t d;
186 
187 		d = (fstack_t)p[action+2];
188 		PUSH(DS, d);
189 		execute(env);
190 		return (0);
191 	}
192 	log_message(MSG_WARN, "run_action: acf: %p/%p not default action\n",
193 	    acf, p[0]);
194 	return (1);
195 }
196 
197 void
198 do_default_action(fcode_env_t *env)
199 {
200 	acf_t a;
201 
202 	CHECK_DEPTH(env, 1, "do_default_action");
203 	a = (acf_t)TOS;
204 	(void) run_action(env, (a-1), 0);
205 }
206 
207 void
208 do_set_action(fcode_env_t *env)
209 {
210 	acf_t  a = (acf_t)TOS;
211 
212 	CHECK_DEPTH(env, 1, "do_set_action");
213 	TOS += sizeof (acf_t);
214 	(void) run_action(env, a, 1);
215 }
216 
217 void
218 action_colon(fcode_env_t *env)
219 {
220 	token_roundup(env, "action_colon");
221 	env->action_ptr[env->action_count] = (token_t)HERE;
222 	COMPILE_TOKEN(&do_colon);
223 	env->action_count++;
224 	env->state |= 1;
225 }
226 
227 void
228 actions(fcode_env_t *env)
229 {
230 	int n;
231 	token_t *d;
232 
233 	token_roundup(env, "actions");
234 	d = (token_t *)HERE;
235 	*d++ = (token_t)&do_default_action;
236 	n = (int)POP(DS);
237 	*d++ = n;
238 	env->num_actions = n;
239 	env->action_count = 0;
240 	env->action_ptr = d;
241 	d += n;
242 	set_here(env, (uchar_t *)d, "actions");
243 }
244 
245 void
246 install_actions(fcode_env_t *env, token_t *table)
247 {
248 	acf_t *dptr;
249 	token_t p;
250 
251 	dptr  = (acf_t *)LINK_TO_ACF(env->lastlink);
252 	p = (token_t)table;
253 	p -= (sizeof (token_t) + sizeof (acf_t));
254 	*dptr = (acf_t)(p | 1);
255 }
256 
257 void
258 use_actions(fcode_env_t *env)
259 {
260 	if (env->state) {
261 		TODO;	/* use-actions in compile state. */
262 	} else {
263 		install_actions(env, env->action_ptr);
264 	}
265 }
266 
267 void
268 perform_action(fcode_env_t *env)
269 {
270 	int n;
271 	acf_t a;
272 
273 	CHECK_DEPTH(env, 2, "perform_action");
274 	n = POP(DS);
275 	a = (acf_t)POP(DS);
276 	PUSH(DS, (fstack_t)ACF_TO_BODY(a));
277 
278 	if (run_action(env, a, n)) {
279 		system_message(env, "Bad Object action");
280 	}
281 }
282 
283 void
284 define_actions(fcode_env_t *env, int n, token_t *array)
285 {
286 	int a;
287 
288 	PUSH(DS, (fstack_t)n);
289 	actions(env);
290 
291 	a = 0;
292 	while (n--) {
293 		action_colon(env);
294 		COMPILE_TOKEN(&array[a]);
295 		env->state |= 8;
296 		semi(env);
297 		a++;
298 	}
299 }
300 
301 /*
302  * This is for things like my-self which have meaning to the
303  * forth engine but I don't want to turn them into standard forth values
304  * that would make the 'C' variables hard to understand, instead these
305  * 'global' state variables will act directly upon the native 'C' structures.
306  */
307 
308 void
309 set_internal_value_actions(fcode_env_t *env)
310 {
311 	ASSERT(value_actions[2]);
312 	install_actions(env, value_actions[2]);
313 }
314 
315 void
316 set_value_actions(fcode_env_t *env, int which)
317 {
318 	ASSERT((which == 0) || (which == 1));
319 	ASSERT(value_actions[which]);
320 	install_actions(env, value_actions[which]);
321 }
322 
323 void
324 set_defer_actions(fcode_env_t *env, int which)
325 {
326 	ASSERT((which == 0) || (which == 1));
327 	ASSERT(value_actions[which+3]);
328 	install_actions(env, value_actions[which+3]);
329 }
330 
331 void
332 set_buffer_actions(fcode_env_t *env, int which)
333 {
334 	ASSERT((which == 0) || (which == 1));
335 	ASSERT(value_actions[which+5]);
336 	install_actions(env, value_actions[which+5]);
337 }
338 
339 #if defined(DEBUG)
340 
341 void
342 do_get(fcode_env_t *env)
343 {
344 	PUSH(DS, 0);
345 	perform_action(env);
346 }
347 
348 void
349 do_set(fcode_env_t *env)
350 {
351 	PUSH(DS, 1);
352 	perform_action(env);
353 }
354 
355 void
356 do_addr(fcode_env_t *env)
357 {
358 	PUSH(DS, 2);
359 	perform_action(env);
360 }
361 
362 void
363 dump_actions(fcode_env_t *env)
364 {
365 	int i;
366 	for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) {
367 		log_message(MSG_INFO, "Action Set: %d = %p\n", i,
368 		    value_actions[i]);
369 	}
370 }
371 #endif	/* DEBUG */
372 
373 #pragma init(_init)
374 
375 static void
376 _init(void)
377 {
378 	fcode_env_t *env = initial_env;
379 	int i;
380 
381 	ASSERT(env);
382 	NOTICE;
383 
384 	for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) {
385 		define_actions(env, 3, value_defines[i]);
386 		value_actions[i] = env->action_ptr;
387 	}
388 
389 #if defined(DEBUG)
390 	FORTH(0,		"get",			do_get);
391 	FORTH(0,		"set",			do_set);
392 	FORTH(0,		"addr",			do_addr);
393 	FORTH(0,		"dump-actions",		dump_actions);
394 	FORTH(IMMEDIATE,	"actions",		actions);
395 	FORTH(IMMEDIATE,	"use-actions",		use_actions);
396 	FORTH(IMMEDIATE,	"action:",		action_colon);
397 	FORTH(0,		"perform-action",	perform_action);
398 #endif /* DEBUG */
399 }
400