summaryrefslogtreecommitdiff
path: root/usr/src/lib/efcode/engine/actions.c
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/efcode/engine/actions.c
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/efcode/engine/actions.c')
-rw-r--r--usr/src/lib/efcode/engine/actions.c399
1 files changed, 399 insertions, 0 deletions
diff --git a/usr/src/lib/efcode/engine/actions.c b/usr/src/lib/efcode/engine/actions.c
new file mode 100644
index 0000000000..11fb96c363
--- /dev/null
+++ b/usr/src/lib/efcode/engine/actions.c
@@ -0,0 +1,399 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2000 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <fcode/private.h>
+#include <fcode/log.h>
+
+#define NUM_DEFAULT_ACTIONS 7
+
+/*
+ * value_fetch and value_store are the same as "fetch" and "store", but
+ * we'll leave them implemented here for now.
+ */
+static void
+value_fetch(fcode_env_t *env)
+{
+ variable_t *addr;
+
+ CHECK_DEPTH(env, 1, "value_fetch");
+ addr = (variable_t *)POP(DS);
+ PUSH(DS, (variable_t)*addr);
+}
+
+static void
+value_store(fcode_env_t *env)
+{
+ variable_t *addr;
+
+ CHECK_DEPTH(env, 1, "value_store");
+ addr = (variable_t *)POP(DS);
+ *addr = (variable_t)POP(DS);
+}
+
+void *
+get_internal_address(fcode_env_t *env)
+{
+ int *ptr;
+
+ CHECK_DEPTH(env, 1, "get_internal_address");
+ ptr = (int *)POP(DS);
+ if (*ptr > 0)
+ return ((uchar_t *)env + *ptr);
+ return ((uchar_t *)MYSELF - *ptr);
+}
+
+void
+internal_env_fetch(fcode_env_t *env)
+{
+ instance_t **iptr;
+
+ CHECK_DEPTH(env, 1, "internal_env_fetch");
+ iptr = (instance_t **)get_internal_address(env);
+ PUSH(DS, (fstack_t)(*iptr));
+}
+
+void
+internal_env_store(fcode_env_t *env)
+{
+ instance_t **iptr;
+
+ CHECK_DEPTH(env, 2, "internal_env_store");
+ iptr = (instance_t **)get_internal_address(env);
+ *iptr = (instance_t *)POP(DS);
+}
+
+void
+internal_env_addr(fcode_env_t *env)
+{
+ fstack_t d;
+
+ CHECK_DEPTH(env, 1, "internal_env_addr");
+ d = (fstack_t)get_internal_address(env);
+ PUSH(DS, d);
+}
+
+void
+do_buffer_data(fcode_env_t *env, token_t *d, int instance)
+{
+ if (!*d) { /* check if buffer not alloc'ed yet */
+ token_t *buf;
+
+ if (instance) {
+ int n, off;
+
+ n = TOKEN_ROUNDUP(d[1]);
+ buf = alloc_instance_data(env, UINIT_DATA, n, &off);
+ memset(buf, 0, d[1]);
+ } else {
+ buf = (token_t *)HERE;
+ set_here(env, HERE + d[1], "do_buffer_data");
+ }
+ *d = (token_t)buf;
+ }
+ PUSH(DS, *d);
+}
+
+void
+ibuffer_init(fcode_env_t *env)
+{
+ token_t *d;
+
+ d = get_instance_address(env);
+ do_buffer_data(env, d, 1);
+}
+
+void
+buffer_init(fcode_env_t *env)
+{
+ token_t *d;
+
+ CHECK_DEPTH(env, 1, "buffer_init");
+ d = (token_t *)POP(DS);
+ do_buffer_data(env, d, 0);
+}
+
+void
+do_defer(fcode_env_t *env)
+{
+ fetch(env);
+ execute(env);
+}
+
+token_t *value_actions[NUM_DEFAULT_ACTIONS];
+token_t value_defines[NUM_DEFAULT_ACTIONS][3] = {
+ { (token_t)&value_fetch, (token_t)&value_store, (token_t)&noop },
+ { (token_t)&fetch_instance_data, (token_t)&set_instance_data,
+ (token_t)&address_instance_data },
+ { (token_t)&internal_env_fetch, (token_t)&internal_env_store,
+ (token_t)&internal_env_addr },
+ { (token_t)&do_defer, (token_t)&store, (token_t)&noop },
+ { (token_t)&idefer_exec, (token_t)&set_instance_data,
+ (token_t)&address_instance_data },
+ { (token_t)&buffer_init, (token_t)&two_drop, (token_t)&noop, },
+ { (token_t)&ibuffer_init, (token_t)&two_drop,
+ (token_t)&address_instance_data }
+};
+
+int
+run_action(fcode_env_t *env, acf_t acf, int action)
+{
+ token_t *p = (token_t *)acf;
+
+ if ((p[0] & 1) == 0) {
+ log_message(MSG_WARN, "run_action: acf: %p @acf: %p not"
+ " indirect\n", acf, p[0]);
+ return (1);
+ }
+
+ p = (token_t *)(p[0] & ~1);
+
+ if (action >= p[1] || action < 0) {
+ log_message(MSG_WARN, "run_action: acf: %p action: %d"
+ " out of range: 0-%d\n", acf, action, (int)p[1]);
+ return (1);
+ }
+
+ if (p[0] == (token_t)&do_default_action) {
+ fstack_t d;
+
+ d = (fstack_t)p[action+2];
+ PUSH(DS, d);
+ execute(env);
+ return (0);
+ }
+ log_message(MSG_WARN, "run_action: acf: %p/%p not default action\n",
+ acf, p[0]);
+ return (1);
+}
+
+void
+do_default_action(fcode_env_t *env)
+{
+ acf_t a;
+
+ CHECK_DEPTH(env, 1, "do_default_action");
+ a = (acf_t)TOS;
+ (void) run_action(env, (a-1), 0);
+}
+
+void
+do_set_action(fcode_env_t *env)
+{
+ acf_t a = (acf_t)TOS;
+
+ CHECK_DEPTH(env, 1, "do_set_action");
+ TOS += sizeof (acf_t);
+ (void) run_action(env, a, 1);
+}
+
+void
+action_colon(fcode_env_t *env)
+{
+ token_roundup(env, "action_colon");
+ env->action_ptr[env->action_count] = (token_t)HERE;
+ COMPILE_TOKEN(&do_colon);
+ env->action_count++;
+ env->state |= 1;
+}
+
+void
+actions(fcode_env_t *env)
+{
+ int n;
+ token_t *d;
+
+ token_roundup(env, "actions");
+ d = (token_t *)HERE;
+ *d++ = (token_t)&do_default_action;
+ n = (int)POP(DS);
+ *d++ = n;
+ env->num_actions = n;
+ env->action_count = 0;
+ env->action_ptr = d;
+ d += n;
+ set_here(env, (uchar_t *)d, "actions");
+}
+
+void
+install_actions(fcode_env_t *env, token_t *table)
+{
+ acf_t *dptr;
+ token_t p;
+
+ dptr = (acf_t *)LINK_TO_ACF(env->lastlink);
+ p = (token_t)table;
+ p -= (sizeof (token_t) + sizeof (acf_t));
+ *dptr = (acf_t)(p | 1);
+}
+
+void
+use_actions(fcode_env_t *env)
+{
+ if (env->state) {
+ TODO; /* use-actions in compile state. */
+ } else {
+ install_actions(env, env->action_ptr);
+ }
+}
+
+void
+perform_action(fcode_env_t *env)
+{
+ int n;
+ acf_t a;
+
+ CHECK_DEPTH(env, 2, "perform_action");
+ n = POP(DS);
+ a = (acf_t)POP(DS);
+ PUSH(DS, (fstack_t)ACF_TO_BODY(a));
+
+ if (run_action(env, a, n)) {
+ system_message(env, "Bad Object action");
+ }
+}
+
+void
+define_actions(fcode_env_t *env, int n, token_t *array)
+{
+ int a;
+
+ PUSH(DS, (fstack_t)n);
+ actions(env);
+
+ a = 0;
+ while (n--) {
+ action_colon(env);
+ COMPILE_TOKEN(&array[a]);
+ env->state |= 8;
+ semi(env);
+ a++;
+ }
+}
+
+/*
+ * This is for things like my-self which have meaning to the
+ * forth engine but I don't want to turn them into standard forth values
+ * that would make the 'C' variables hard to understand, instead these
+ * 'global' state variables will act directly upon the native 'C' structures.
+ */
+
+void
+set_internal_value_actions(fcode_env_t *env)
+{
+ ASSERT(value_actions[2]);
+ install_actions(env, value_actions[2]);
+}
+
+void
+set_value_actions(fcode_env_t *env, int which)
+{
+ ASSERT((which == 0) || (which == 1));
+ ASSERT(value_actions[which]);
+ install_actions(env, value_actions[which]);
+}
+
+void
+set_defer_actions(fcode_env_t *env, int which)
+{
+ ASSERT((which == 0) || (which == 1));
+ ASSERT(value_actions[which+3]);
+ install_actions(env, value_actions[which+3]);
+}
+
+void
+set_buffer_actions(fcode_env_t *env, int which)
+{
+ ASSERT((which == 0) || (which == 1));
+ ASSERT(value_actions[which+5]);
+ install_actions(env, value_actions[which+5]);
+}
+
+#if defined(DEBUG)
+
+void
+do_get(fcode_env_t *env)
+{
+ PUSH(DS, 0);
+ perform_action(env);
+}
+
+void
+do_set(fcode_env_t *env)
+{
+ PUSH(DS, 1);
+ perform_action(env);
+}
+
+void
+do_addr(fcode_env_t *env)
+{
+ PUSH(DS, 2);
+ perform_action(env);
+}
+
+void
+dump_actions(fcode_env_t *env)
+{
+ int i;
+ for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) {
+ log_message(MSG_INFO, "Action Set: %d = %p\n", i,
+ value_actions[i]);
+ }
+}
+#endif /* DEBUG */
+
+#pragma init(_init)
+
+static void
+_init(void)
+{
+ fcode_env_t *env = initial_env;
+ int i;
+
+ ASSERT(env);
+ NOTICE;
+
+ for (i = 0; i < NUM_DEFAULT_ACTIONS; i++) {
+ define_actions(env, 3, value_defines[i]);
+ value_actions[i] = env->action_ptr;
+ }
+
+#if defined(DEBUG)
+ FORTH(0, "get", do_get);
+ FORTH(0, "set", do_set);
+ FORTH(0, "addr", do_addr);
+ FORTH(0, "dump-actions", dump_actions);
+ FORTH(IMMEDIATE, "actions", actions);
+ FORTH(IMMEDIATE, "use-actions", use_actions);
+ FORTH(IMMEDIATE, "action:", action_colon);
+ FORTH(0, "perform-action", perform_action);
+#endif /* DEBUG */
+}