xref: /onnv-gate/usr/src/lib/efcode/engine/fcode.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright (c) 2000 by Sun Microsystems, Inc.
24*0Sstevel@tonic-gate  * All rights reserved.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <stdio.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate #include <string.h>
32*0Sstevel@tonic-gate #include <ctype.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <fcode/private.h>
35*0Sstevel@tonic-gate #include <fcode/log.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate int fcode_impl_count = 0;
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate void (*crash_ptr)(fcode_env_t *env) = do_crash;
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate uchar_t
next_bytecode(fcode_env_t * env)42*0Sstevel@tonic-gate next_bytecode(fcode_env_t *env)
43*0Sstevel@tonic-gate {
44*0Sstevel@tonic-gate 	uchar_t	byte;
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate 	byte = *env->fcode_ptr;
47*0Sstevel@tonic-gate 	env->fcode_ptr += env->fcode_incr;
48*0Sstevel@tonic-gate 	return (byte);
49*0Sstevel@tonic-gate }
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate ushort_t
get_next_token(fcode_env_t * env)52*0Sstevel@tonic-gate get_next_token(fcode_env_t *env)
53*0Sstevel@tonic-gate {
54*0Sstevel@tonic-gate 	ushort_t token = next_bytecode(env);
55*0Sstevel@tonic-gate 	if ((token) && (token < 0x10)) {
56*0Sstevel@tonic-gate 		token = (token << 8) | next_bytecode(env);
57*0Sstevel@tonic-gate 	}
58*0Sstevel@tonic-gate 	env->last_fcode = token;
59*0Sstevel@tonic-gate 	return (token);
60*0Sstevel@tonic-gate }
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate ushort_t
get_short(fcode_env_t * env)63*0Sstevel@tonic-gate get_short(fcode_env_t *env)
64*0Sstevel@tonic-gate {
65*0Sstevel@tonic-gate 	ushort_t u;
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate 	/*
68*0Sstevel@tonic-gate 	 * Logical or DOES NOT guarantee left to right evaluation...
69*0Sstevel@tonic-gate 	 */
70*0Sstevel@tonic-gate 	u = next_bytecode(env) << 8;
71*0Sstevel@tonic-gate 	return (u | next_bytecode(env));
72*0Sstevel@tonic-gate }
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate uint_t
get_int(fcode_env_t * env)75*0Sstevel@tonic-gate get_int(fcode_env_t *env)
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate 	uint_t u;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	/*
80*0Sstevel@tonic-gate 	 * Logical or DOES NOT guarantee left to right evaluation...
81*0Sstevel@tonic-gate 	 */
82*0Sstevel@tonic-gate 	u = get_short(env) << 16;
83*0Sstevel@tonic-gate 	return (u | get_short(env));
84*0Sstevel@tonic-gate }
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate void
expose_acf(fcode_env_t * env,char * name)87*0Sstevel@tonic-gate expose_acf(fcode_env_t *env, char *name)
88*0Sstevel@tonic-gate {
89*0Sstevel@tonic-gate 	if (name == NULL)
90*0Sstevel@tonic-gate 		name = "<unknown>";
91*0Sstevel@tonic-gate 	EXPOSE_ACF;
92*0Sstevel@tonic-gate 	debug_msg(DEBUG_CONTEXT, "CONTEXT:expose_acf: acf: %p/'%s' %p\n",
93*0Sstevel@tonic-gate 	    LINK_TO_ACF(env->lastlink), name, env->current);
94*0Sstevel@tonic-gate }
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate void
do_code(fcode_env_t * env,int token,char * name,void (* fn)(fcode_env_t *))97*0Sstevel@tonic-gate do_code(fcode_env_t *env, int token, char *name, void (*fn)(fcode_env_t *))
98*0Sstevel@tonic-gate {
99*0Sstevel@tonic-gate 	env->table[token].name = name;
100*0Sstevel@tonic-gate 	if (fn == NULL) {
101*0Sstevel@tonic-gate 		env->table[token].apf = NULL;
102*0Sstevel@tonic-gate 		env->table[token].name = name;
103*0Sstevel@tonic-gate 	} else {
104*0Sstevel@tonic-gate 		header(env, name, strlen(name), 0);
105*0Sstevel@tonic-gate 		env->table[token].apf = (acf_t)HERE;
106*0Sstevel@tonic-gate 		COMPILE_TOKEN(fn);
107*0Sstevel@tonic-gate 		expose_acf(env, name);
108*0Sstevel@tonic-gate 	}
109*0Sstevel@tonic-gate }
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate void
define_word(fcode_env_t * env,int flag,char * name,void (* fn)(fcode_env_t *))112*0Sstevel@tonic-gate define_word(fcode_env_t *env, int flag, char *name, void (*fn)(fcode_env_t *))
113*0Sstevel@tonic-gate {
114*0Sstevel@tonic-gate 	header(env, name, strlen(name), flag);
115*0Sstevel@tonic-gate 	COMPILE_TOKEN(fn);
116*0Sstevel@tonic-gate 	expose_acf(env, name);
117*0Sstevel@tonic-gate }
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate void
end0(fcode_env_t * env)120*0Sstevel@tonic-gate end0(fcode_env_t *env)
121*0Sstevel@tonic-gate {
122*0Sstevel@tonic-gate 	env->interpretting = 0;
123*0Sstevel@tonic-gate }
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate static void
end1(fcode_env_t * env)126*0Sstevel@tonic-gate end1(fcode_env_t *env)
127*0Sstevel@tonic-gate {
128*0Sstevel@tonic-gate 	env->interpretting = 0;
129*0Sstevel@tonic-gate }
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate void
blit(fcode_env_t * env)132*0Sstevel@tonic-gate blit(fcode_env_t *env)
133*0Sstevel@tonic-gate {
134*0Sstevel@tonic-gate 	fstack_t d = (int)get_int(env);
135*0Sstevel@tonic-gate 	PUSH(DS, d);
136*0Sstevel@tonic-gate 	literal(env);
137*0Sstevel@tonic-gate }
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate void (*bbranch_ptrs[3])(fcode_env_t *env) = {
140*0Sstevel@tonic-gate 	do_bbranch,
141*0Sstevel@tonic-gate 	do_bqbranch,
142*0Sstevel@tonic-gate 	do_bofbranch
143*0Sstevel@tonic-gate };
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate void
branch_common(fcode_env_t * env,short direction,fstack_t which,int doswap)146*0Sstevel@tonic-gate branch_common(fcode_env_t *env, short direction, fstack_t which, int doswap)
147*0Sstevel@tonic-gate {
148*0Sstevel@tonic-gate 	fstack_t *sp;
149*0Sstevel@tonic-gate 	token_t *branch_loc;
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	ASSERT((which < 3) && (which >= 0));
152*0Sstevel@tonic-gate 	which = (fstack_t)&bbranch_ptrs[which];
153*0Sstevel@tonic-gate 	set_temporary_compile(env);
154*0Sstevel@tonic-gate 	COMPILE_TOKEN(which);
155*0Sstevel@tonic-gate 	if (direction >= 0) {
156*0Sstevel@tonic-gate 		bmark(env);
157*0Sstevel@tonic-gate 		if (doswap)
158*0Sstevel@tonic-gate 			swap(env);
159*0Sstevel@tonic-gate 		PUSH(DS, 0);
160*0Sstevel@tonic-gate 		compile_comma(env);
161*0Sstevel@tonic-gate 	} else {
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 		/*
164*0Sstevel@tonic-gate 		 * We look down the stack for a branch location
165*0Sstevel@tonic-gate 		 * that isn't pointing to zero (i.e. a forward branch label).
166*0Sstevel@tonic-gate 		 * We move the first one we find to the top of the stack,
167*0Sstevel@tonic-gate 		 * which is what gets compiled in with 'compile_comma'.
168*0Sstevel@tonic-gate 		 * Not finding a valid branch label is bad.
169*0Sstevel@tonic-gate 		 */
170*0Sstevel@tonic-gate 		for (sp = env->ds; sp >= env->ds0; sp--) {
171*0Sstevel@tonic-gate 			branch_loc = (token_t *)*sp;
172*0Sstevel@tonic-gate 			if (branch_loc && *branch_loc) {
173*0Sstevel@tonic-gate 				break;
174*0Sstevel@tonic-gate 			}
175*0Sstevel@tonic-gate 		}
176*0Sstevel@tonic-gate 		if (sp < env->ds0)
177*0Sstevel@tonic-gate 			log_message(MSG_ERROR, "branch_common: back: "
178*0Sstevel@tonic-gate 			    "no branch loc on stack\n");
179*0Sstevel@tonic-gate 		else {
180*0Sstevel@tonic-gate 			/* Move branch_loc to top of data stack */
181*0Sstevel@tonic-gate 			for (; sp < env->ds; sp++)
182*0Sstevel@tonic-gate 				*sp = sp[1];
183*0Sstevel@tonic-gate 			*sp = (fstack_t)branch_loc;
184*0Sstevel@tonic-gate 		}
185*0Sstevel@tonic-gate 		env->level--;
186*0Sstevel@tonic-gate 		compile_comma(env);
187*0Sstevel@tonic-gate 		temporary_execute(env);
188*0Sstevel@tonic-gate 	}
189*0Sstevel@tonic-gate }
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate void
bbranch(fcode_env_t * env)192*0Sstevel@tonic-gate bbranch(fcode_env_t *env)
193*0Sstevel@tonic-gate {
194*0Sstevel@tonic-gate 	short offset = (short)get_short(env);
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	branch_common(env, offset, 0, 1);
197*0Sstevel@tonic-gate }
198*0Sstevel@tonic-gate 
199*0Sstevel@tonic-gate void
bqbranch(fcode_env_t * env)200*0Sstevel@tonic-gate bqbranch(fcode_env_t *env)
201*0Sstevel@tonic-gate {
202*0Sstevel@tonic-gate 	short offset = (short)get_short(env);
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	branch_common(env, offset, 1, 0);
205*0Sstevel@tonic-gate }
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate void
do_quote(fcode_env_t * env)208*0Sstevel@tonic-gate do_quote(fcode_env_t *env)
209*0Sstevel@tonic-gate {
210*0Sstevel@tonic-gate 	int len;
211*0Sstevel@tonic-gate 	uchar_t *strptr;
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	strptr = (uchar_t *)IP;
214*0Sstevel@tonic-gate 	len = *strptr;
215*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)strptr+1);
216*0Sstevel@tonic-gate 	PUSH(DS, len);
217*0Sstevel@tonic-gate 	strptr += TOKEN_ROUNDUP(len+2);
218*0Sstevel@tonic-gate 	IP = (token_t *)strptr;
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate void
bquote(fcode_env_t * env)222*0Sstevel@tonic-gate bquote(fcode_env_t *env)
223*0Sstevel@tonic-gate {
224*0Sstevel@tonic-gate 	char stringbuff[256];
225*0Sstevel@tonic-gate 	int len, count;
226*0Sstevel@tonic-gate 	char *strptr;
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 	count = len = next_bytecode(env);
229*0Sstevel@tonic-gate 	if (env->state) {
230*0Sstevel@tonic-gate 		COMPILE_TOKEN(&quote_ptr);
231*0Sstevel@tonic-gate 		strptr = (char *)HERE;
232*0Sstevel@tonic-gate 		*strptr++ = len;
233*0Sstevel@tonic-gate 		while (count--)
234*0Sstevel@tonic-gate 			*strptr++ = next_bytecode(env);
235*0Sstevel@tonic-gate 		*strptr++ = 0;
236*0Sstevel@tonic-gate 		set_here(env, (uchar_t *)strptr, "bquote");
237*0Sstevel@tonic-gate 		token_roundup(env, "bquote");
238*0Sstevel@tonic-gate 	} else {
239*0Sstevel@tonic-gate 		strptr = stringbuff;
240*0Sstevel@tonic-gate 		while (count--)
241*0Sstevel@tonic-gate 			*strptr++ = next_bytecode(env);
242*0Sstevel@tonic-gate 		*strptr = 0;
243*0Sstevel@tonic-gate 		push_string(env, stringbuff, len);
244*0Sstevel@tonic-gate 	}
245*0Sstevel@tonic-gate }
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate char *
get_name(token_t * linkp)248*0Sstevel@tonic-gate get_name(token_t *linkp)
249*0Sstevel@tonic-gate {
250*0Sstevel@tonic-gate 	char *name, *p;
251*0Sstevel@tonic-gate 	flag_t *fptr = LINK_TO_FLAGS(linkp);
252*0Sstevel@tonic-gate 	int len;
253*0Sstevel@tonic-gate 	char *cptr;
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	if (*fptr & FLAG_NONAME)
256*0Sstevel@tonic-gate 		return (NULL);
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	cptr = (char *)fptr;
259*0Sstevel@tonic-gate 	len = cptr[-1];
260*0Sstevel@tonic-gate 	if (len <= 0 || len > 64 || cptr[-2] != '\0')
261*0Sstevel@tonic-gate 		return (NULL);
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 	name = cptr - (len+2);
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 	for (p = name; *p != '\0'; p++)
266*0Sstevel@tonic-gate 		if (!isprint(*p))
267*0Sstevel@tonic-gate 			return (NULL);
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	if ((p - name) != len)
270*0Sstevel@tonic-gate 		return (NULL);
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	return (name);
273*0Sstevel@tonic-gate }
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate void
header(fcode_env_t * env,char * name,int len,flag_t flag)276*0Sstevel@tonic-gate header(fcode_env_t *env, char *name, int len, flag_t flag)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate 	char *strptr;
279*0Sstevel@tonic-gate 	flag_t *fptr;
280*0Sstevel@tonic-gate 	acf_t dptr;
281*0Sstevel@tonic-gate 	extern void add_debug_acf(fcode_env_t *, acf_t);
282*0Sstevel@tonic-gate 
283*0Sstevel@tonic-gate 	/* Now form the entry in the dictionary */
284*0Sstevel@tonic-gate 	token_roundup(env, "header");
285*0Sstevel@tonic-gate 	dptr = (acf_t)HERE;
286*0Sstevel@tonic-gate 	if (len) {
287*0Sstevel@tonic-gate 		int bytes = len+2+sizeof (flag_t);
288*0Sstevel@tonic-gate 		dptr = (acf_t)(TOKEN_ROUNDUP(HERE+bytes));
289*0Sstevel@tonic-gate 		fptr = LINK_TO_FLAGS(dptr);
290*0Sstevel@tonic-gate 		strptr = (char *)fptr - 1;
291*0Sstevel@tonic-gate 		*strptr-- = len;
292*0Sstevel@tonic-gate 		*strptr-- = 0;
293*0Sstevel@tonic-gate 		while (len)
294*0Sstevel@tonic-gate 			*strptr-- = name[--len];
295*0Sstevel@tonic-gate 	} else {
296*0Sstevel@tonic-gate 		dptr++;
297*0Sstevel@tonic-gate 		fptr = LINK_TO_FLAGS(dptr);
298*0Sstevel@tonic-gate 		flag |= FLAG_NONAME;
299*0Sstevel@tonic-gate 	}
300*0Sstevel@tonic-gate 	*fptr = flag;
301*0Sstevel@tonic-gate 	*dptr = *((acf_t)env->current);
302*0Sstevel@tonic-gate 	env->lastlink = dptr++;
303*0Sstevel@tonic-gate 	set_here(env, (uchar_t *)dptr, "header");
304*0Sstevel@tonic-gate 
305*0Sstevel@tonic-gate 	if (name_is_debugged(env, name)) {
306*0Sstevel@tonic-gate 		log_message(MSG_INFO, "Turning debug on for %s\n", name);
307*0Sstevel@tonic-gate 		add_debug_acf(env, LINK_TO_ACF(env->lastlink));
308*0Sstevel@tonic-gate 	}
309*0Sstevel@tonic-gate 	debug_msg(DEBUG_HEADER, "Define: '%s' @ %p\n", name, HERE);
310*0Sstevel@tonic-gate }
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate void
token_common(fcode_env_t * env,int headered,int visible)313*0Sstevel@tonic-gate token_common(fcode_env_t *env, int headered, int visible)
314*0Sstevel@tonic-gate {
315*0Sstevel@tonic-gate 	char namebuff[32];
316*0Sstevel@tonic-gate 	int len, count, token;
317*0Sstevel@tonic-gate 	char *strptr, c;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	strptr = namebuff;
320*0Sstevel@tonic-gate 	if (headered) {
321*0Sstevel@tonic-gate 		len = next_bytecode(env);
322*0Sstevel@tonic-gate 		for (count = 0; count < len; count++) {
323*0Sstevel@tonic-gate 			c = next_bytecode(env);
324*0Sstevel@tonic-gate 			if (count < sizeof (namebuff))
325*0Sstevel@tonic-gate 				*strptr++ = c;
326*0Sstevel@tonic-gate 		}
327*0Sstevel@tonic-gate 	}
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 	if (!visible)
330*0Sstevel@tonic-gate 		len = 0;
331*0Sstevel@tonic-gate 	*strptr = 0;
332*0Sstevel@tonic-gate 	token = get_short(env);
333*0Sstevel@tonic-gate 	env->last_token = token;
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	debug_msg(DEBUG_NEW_TOKEN, "Define %s token: '%s' (%x)\n",
336*0Sstevel@tonic-gate 	    (visible ? "named" : "headerless"), namebuff, token);
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	header(env, namebuff, len, 0);
339*0Sstevel@tonic-gate 	env->table[token].flags = 0;
340*0Sstevel@tonic-gate 	if (len) {
341*0Sstevel@tonic-gate 		env->table[token].name = MALLOC(len+1);
342*0Sstevel@tonic-gate 		strncpy(env->table[token].name, namebuff, len);
343*0Sstevel@tonic-gate 	} else {
344*0Sstevel@tonic-gate 		env->table[token].name = NULL;
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 	env->last_token = token;
347*0Sstevel@tonic-gate }
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate void
named_token(fcode_env_t * env)350*0Sstevel@tonic-gate named_token(fcode_env_t *env)
351*0Sstevel@tonic-gate {
352*0Sstevel@tonic-gate 	token_common(env, 1, env->fcode_debug);
353*0Sstevel@tonic-gate }
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate void
external_token(fcode_env_t * env)356*0Sstevel@tonic-gate external_token(fcode_env_t *env)
357*0Sstevel@tonic-gate {
358*0Sstevel@tonic-gate 	token_common(env, 1, 1);
359*0Sstevel@tonic-gate }
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate void
new_token(fcode_env_t * env)362*0Sstevel@tonic-gate new_token(fcode_env_t *env)
363*0Sstevel@tonic-gate {
364*0Sstevel@tonic-gate 	token_common(env, 0, 0);
365*0Sstevel@tonic-gate }
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate void
offset16(fcode_env_t * env)368*0Sstevel@tonic-gate offset16(fcode_env_t *env)
369*0Sstevel@tonic-gate {
370*0Sstevel@tonic-gate 	env->offset_incr = 2;
371*0Sstevel@tonic-gate }
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate void
minus_one(fcode_env_t * env)374*0Sstevel@tonic-gate minus_one(fcode_env_t *env)
375*0Sstevel@tonic-gate {
376*0Sstevel@tonic-gate 	PUSH(DS, -1);
377*0Sstevel@tonic-gate }
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate void
zero(fcode_env_t * env)380*0Sstevel@tonic-gate zero(fcode_env_t *env)
381*0Sstevel@tonic-gate {
382*0Sstevel@tonic-gate 	PUSH(DS, 0);
383*0Sstevel@tonic-gate }
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate void
one(fcode_env_t * env)386*0Sstevel@tonic-gate one(fcode_env_t *env)
387*0Sstevel@tonic-gate {
388*0Sstevel@tonic-gate 	PUSH(DS, 1);
389*0Sstevel@tonic-gate }
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate void
two(fcode_env_t * env)392*0Sstevel@tonic-gate two(fcode_env_t *env)
393*0Sstevel@tonic-gate {
394*0Sstevel@tonic-gate 	PUSH(DS, 2);
395*0Sstevel@tonic-gate }
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate void
three(fcode_env_t * env)398*0Sstevel@tonic-gate three(fcode_env_t *env)
399*0Sstevel@tonic-gate {
400*0Sstevel@tonic-gate 	PUSH(DS, 3);
401*0Sstevel@tonic-gate }
402*0Sstevel@tonic-gate 
403*0Sstevel@tonic-gate void
version1(fcode_env_t * env)404*0Sstevel@tonic-gate version1(fcode_env_t *env)
405*0Sstevel@tonic-gate {
406*0Sstevel@tonic-gate 	env->fcode_incr = 1;
407*0Sstevel@tonic-gate }
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate static void
start0(fcode_env_t * env)410*0Sstevel@tonic-gate start0(fcode_env_t *env)
411*0Sstevel@tonic-gate {
412*0Sstevel@tonic-gate 	env->fcode_incr = 1;
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate static void
start1(fcode_env_t * env)416*0Sstevel@tonic-gate start1(fcode_env_t *env)
417*0Sstevel@tonic-gate {
418*0Sstevel@tonic-gate 	env->fcode_incr = 1;
419*0Sstevel@tonic-gate }
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate void
start2(fcode_env_t * env)422*0Sstevel@tonic-gate start2(fcode_env_t *env)
423*0Sstevel@tonic-gate {
424*0Sstevel@tonic-gate 	env->fcode_incr = 2;
425*0Sstevel@tonic-gate }
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate static void
start4(fcode_env_t * env)428*0Sstevel@tonic-gate start4(fcode_env_t *env)
429*0Sstevel@tonic-gate {
430*0Sstevel@tonic-gate 	env->fcode_incr = 4;
431*0Sstevel@tonic-gate }
432*0Sstevel@tonic-gate 
433*0Sstevel@tonic-gate int
check_fcode_header(char * fname,uchar_t * header,int len)434*0Sstevel@tonic-gate check_fcode_header(char *fname, uchar_t *header, int len)
435*0Sstevel@tonic-gate {
436*0Sstevel@tonic-gate 	uint32_t length;
437*0Sstevel@tonic-gate 	static char func_name[] = "check_fcode_header";
438*0Sstevel@tonic-gate 
439*0Sstevel@tonic-gate 	if (len <= 8) {
440*0Sstevel@tonic-gate 		log_message(MSG_ERROR, "%s: '%s' fcode size (%d) <= 8\n",
441*0Sstevel@tonic-gate 		    func_name, fname, len);
442*0Sstevel@tonic-gate 		return (0);
443*0Sstevel@tonic-gate 	}
444*0Sstevel@tonic-gate 	if (header[0] != 0xf1 && header[0] != 0xfd) {
445*0Sstevel@tonic-gate 		log_message(MSG_ERROR, "%s: '%s' header[0] is 0x%02x not"
446*0Sstevel@tonic-gate 		    " 0xf1/0xfd\n", func_name, fname, header[0]);
447*0Sstevel@tonic-gate 		return (0);
448*0Sstevel@tonic-gate 	}
449*0Sstevel@tonic-gate 	length = (header[4] << 24) | (header[5] << 16) | (header[6] << 8) |
450*0Sstevel@tonic-gate 	    header[7];
451*0Sstevel@tonic-gate 	if (length > len) {
452*0Sstevel@tonic-gate 		log_message(MSG_ERROR, "%s: '%s' length (%d) >"
453*0Sstevel@tonic-gate 		    " fcode size (%d)\n", func_name, fname, length, len);
454*0Sstevel@tonic-gate 		return (0);
455*0Sstevel@tonic-gate 	}
456*0Sstevel@tonic-gate 	if (length < len) {
457*0Sstevel@tonic-gate 		log_message(MSG_WARN, "%s: '%s' length (%d) <"
458*0Sstevel@tonic-gate 		    " fcode size (%d)\n", func_name, fname, length, len);
459*0Sstevel@tonic-gate 	}
460*0Sstevel@tonic-gate 	return (1);
461*0Sstevel@tonic-gate }
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate void
byte_load(fcode_env_t * env)464*0Sstevel@tonic-gate byte_load(fcode_env_t *env)
465*0Sstevel@tonic-gate {
466*0Sstevel@tonic-gate 	uchar_t	*fcode_buffer;
467*0Sstevel@tonic-gate 	uchar_t	*fcode_ptr;
468*0Sstevel@tonic-gate 	int	fcode_incr;
469*0Sstevel@tonic-gate 	int	offset_incr;
470*0Sstevel@tonic-gate 	int	fcode_xt;
471*0Sstevel@tonic-gate 	int	interpretting;
472*0Sstevel@tonic-gate 	int	depth;
473*0Sstevel@tonic-gate 	int	length;
474*0Sstevel@tonic-gate 	int	past_eob = 0;
475*0Sstevel@tonic-gate 	int db;
476*0Sstevel@tonic-gate 
477*0Sstevel@tonic-gate 	/* save any existing interpret state */
478*0Sstevel@tonic-gate 	fcode_buffer = env->fcode_buffer;
479*0Sstevel@tonic-gate 	fcode_ptr = env->fcode_ptr;
480*0Sstevel@tonic-gate 	fcode_incr = env->fcode_incr;
481*0Sstevel@tonic-gate 	offset_incr  = env->offset_incr;
482*0Sstevel@tonic-gate 	interpretting = env->interpretting;
483*0Sstevel@tonic-gate 	depth = DEPTH-2;
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 	/* Now init them */
486*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "byte-load");
487*0Sstevel@tonic-gate 	fcode_xt = POP(DS);
488*0Sstevel@tonic-gate 	env->fcode_ptr = env->fcode_buffer = (uchar_t *)POP(DS);
489*0Sstevel@tonic-gate 	if (fcode_xt != 1) {
490*0Sstevel@tonic-gate 		log_message(MSG_WARN, "byte-load: ignoring xt\n");
491*0Sstevel@tonic-gate 	}
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	length = (env->fcode_buffer[4] << 24) | (env->fcode_buffer[5] << 16) |
494*0Sstevel@tonic-gate 	    (env->fcode_buffer[6] << 8) | env->fcode_buffer[7];
495*0Sstevel@tonic-gate 	if (!check_fcode_header("byte-load", env->fcode_ptr, length))
496*0Sstevel@tonic-gate 		log_message(MSG_WARN, "byte-load: header NOT OK\n");
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate 	env->fcode_incr = 1;
499*0Sstevel@tonic-gate 	env->offset_incr = 1;
500*0Sstevel@tonic-gate 	env->interpretting = 1;
501*0Sstevel@tonic-gate 	env->level = 0;
502*0Sstevel@tonic-gate 
503*0Sstevel@tonic-gate 	db = get_interpreter_debug_level() &
504*0Sstevel@tonic-gate 	    (DEBUG_BYTELOAD_DS|DEBUG_BYTELOAD_RS|DEBUG_BYTELOAD_TOKENS);
505*0Sstevel@tonic-gate 	debug_msg(db, "byte_load: %p, %d\n", env->fcode_buffer, fcode_xt);
506*0Sstevel@tonic-gate 	debug_msg(db, "   header: %x, %x\n",
507*0Sstevel@tonic-gate 	    env->fcode_buffer[0], env->fcode_buffer[1]);
508*0Sstevel@tonic-gate 	debug_msg(db, "      crc: %x\n",
509*0Sstevel@tonic-gate 	    (env->fcode_buffer[2]<<8)|(env->fcode_buffer[3]));
510*0Sstevel@tonic-gate 	debug_msg(db, "   length: %x\n", length);
511*0Sstevel@tonic-gate 	env->fcode_ptr += 8;
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate 	debug_msg(db, "Interpretting: %d\n", env->interpretting);
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate 	while (env->interpretting) {
516*0Sstevel@tonic-gate 		int token;
517*0Sstevel@tonic-gate 		fcode_token *entry;
518*0Sstevel@tonic-gate 		acf_t apf;
519*0Sstevel@tonic-gate 
520*0Sstevel@tonic-gate 		if (!past_eob && env->fcode_ptr >= env->fcode_buffer + length) {
521*0Sstevel@tonic-gate 			log_message(MSG_WARN, "byte-load: past EOB\n");
522*0Sstevel@tonic-gate 			past_eob = 1;
523*0Sstevel@tonic-gate 		}
524*0Sstevel@tonic-gate 
525*0Sstevel@tonic-gate 		env->last_fcode_ptr = env->fcode_ptr;
526*0Sstevel@tonic-gate 		token = get_next_token(env);
527*0Sstevel@tonic-gate 
528*0Sstevel@tonic-gate 		entry = &env->table[token];
529*0Sstevel@tonic-gate 		apf   = entry->apf;
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 		DEBUGF(BYTELOAD_DS, output_data_stack(env, MSG_FC_DEBUG));
532*0Sstevel@tonic-gate 		DEBUGF(BYTELOAD_RS, output_return_stack(env, 1, MSG_FC_DEBUG));
533*0Sstevel@tonic-gate 		DEBUGF(BYTELOAD_TOKENS, log_message(MSG_FC_DEBUG,
534*0Sstevel@tonic-gate 		    "%s: %04x %03x %s (%x)",
535*0Sstevel@tonic-gate 		    ((env->state && (entry->flags & IMMEDIATE) == 0)) ?
536*0Sstevel@tonic-gate 		    "Compile" : "Execute",
537*0Sstevel@tonic-gate 		    env->last_fcode_ptr - env->fcode_buffer, token,
538*0Sstevel@tonic-gate 		    entry->name ? entry->name : "???", entry->flags));
539*0Sstevel@tonic-gate 		if (db)
540*0Sstevel@tonic-gate 			log_message(MSG_FC_DEBUG, "\n");
541*0Sstevel@tonic-gate 		if (apf) {
542*0Sstevel@tonic-gate 			DEBUGF(TOKEN_USAGE, entry->usage++);
543*0Sstevel@tonic-gate 			PUSH(DS, (fstack_t)apf);
544*0Sstevel@tonic-gate 			if ((env->state) &&
545*0Sstevel@tonic-gate 				((entry->flags & IMMEDIATE) == 0)) {
546*0Sstevel@tonic-gate 				/* Compile in references */
547*0Sstevel@tonic-gate 				compile_comma(env);
548*0Sstevel@tonic-gate 			} else {
549*0Sstevel@tonic-gate 				execute(env);
550*0Sstevel@tonic-gate 			}
551*0Sstevel@tonic-gate 		}
552*0Sstevel@tonic-gate 	}
553*0Sstevel@tonic-gate 	if (DEPTH != depth) {
554*0Sstevel@tonic-gate 		log_message(MSG_ERROR, "FCODE has net stack change of %d\n",
555*0Sstevel@tonic-gate 		    DEPTH-depth);
556*0Sstevel@tonic-gate 	}
557*0Sstevel@tonic-gate 	/* restore old state */
558*0Sstevel@tonic-gate 	env->fcode_ptr		= fcode_ptr;
559*0Sstevel@tonic-gate 	env->fcode_buffer	= fcode_buffer;
560*0Sstevel@tonic-gate 	env->fcode_incr		= fcode_incr;
561*0Sstevel@tonic-gate 	env->offset_incr	= offset_incr;
562*0Sstevel@tonic-gate 	env->interpretting	= interpretting;
563*0Sstevel@tonic-gate }
564*0Sstevel@tonic-gate 
565*0Sstevel@tonic-gate void
btick(fcode_env_t * env)566*0Sstevel@tonic-gate btick(fcode_env_t *env)
567*0Sstevel@tonic-gate {
568*0Sstevel@tonic-gate 	int token = get_next_token(env);
569*0Sstevel@tonic-gate 
570*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)env->table[token].apf);
571*0Sstevel@tonic-gate 	tick_literal(env);
572*0Sstevel@tonic-gate }
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate static void
show_fcode_def(fcode_env_t * env,char * type)575*0Sstevel@tonic-gate show_fcode_def(fcode_env_t *env, char *type)
576*0Sstevel@tonic-gate {
577*0Sstevel@tonic-gate 	int i = env->last_token;
578*0Sstevel@tonic-gate 
579*0Sstevel@tonic-gate 	if (get_interpreter_debug_level() & DEBUG_DUMP_TOKENS) {
580*0Sstevel@tonic-gate 		if (env->table[i].name)
581*0Sstevel@tonic-gate 			log_message(MSG_INFO, "%s: %s %03x %p\n", type,
582*0Sstevel@tonic-gate 			    env->table[i].name, i, env->table[i].apf);
583*0Sstevel@tonic-gate 		else
584*0Sstevel@tonic-gate 			log_message(MSG_INFO, "%s: <noname> %03x %p\n", type, i,
585*0Sstevel@tonic-gate 			    env->table[i].apf);
586*0Sstevel@tonic-gate 	}
587*0Sstevel@tonic-gate }
588*0Sstevel@tonic-gate 
589*0Sstevel@tonic-gate void
bcolon(fcode_env_t * env)590*0Sstevel@tonic-gate bcolon(fcode_env_t *env)
591*0Sstevel@tonic-gate {
592*0Sstevel@tonic-gate 	if (env->state == 0) {
593*0Sstevel@tonic-gate 		env->table[env->last_token].apf = (acf_t)HERE;
594*0Sstevel@tonic-gate 		env->table[env->last_token].flags = 0;
595*0Sstevel@tonic-gate 		show_fcode_def(env, "bcolon");
596*0Sstevel@tonic-gate 	}
597*0Sstevel@tonic-gate 	env->state |= 1;
598*0Sstevel@tonic-gate 	COMPILE_TOKEN(&do_colon);
599*0Sstevel@tonic-gate }
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate void
bcreate(fcode_env_t * env)602*0Sstevel@tonic-gate bcreate(fcode_env_t *env)
603*0Sstevel@tonic-gate {
604*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
605*0Sstevel@tonic-gate 	show_fcode_def(env, "bcreate");
606*0Sstevel@tonic-gate 	COMPILE_TOKEN(&do_create);
607*0Sstevel@tonic-gate 	expose_acf(env, "<bcreate>");
608*0Sstevel@tonic-gate }
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate void
get_token_name(fcode_env_t * env,int token,char ** name,int * len)611*0Sstevel@tonic-gate get_token_name(fcode_env_t *env, int token, char **name, int *len)
612*0Sstevel@tonic-gate {
613*0Sstevel@tonic-gate 	*name = env->table[token].name;
614*0Sstevel@tonic-gate 	if (*name) {
615*0Sstevel@tonic-gate 		*len = strlen(*name);
616*0Sstevel@tonic-gate 	} else
617*0Sstevel@tonic-gate 		*len = 0;
618*0Sstevel@tonic-gate }
619*0Sstevel@tonic-gate 
620*0Sstevel@tonic-gate void
bvalue(fcode_env_t * env)621*0Sstevel@tonic-gate bvalue(fcode_env_t *env)
622*0Sstevel@tonic-gate {
623*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
624*0Sstevel@tonic-gate 	show_fcode_def(env, "bvalue");
625*0Sstevel@tonic-gate 	make_common_access(env, 0, 0, 1,
626*0Sstevel@tonic-gate 	    env->instance_mode, &noop, &noop, &set_value_actions);
627*0Sstevel@tonic-gate }
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate void
bvariable(fcode_env_t * env)630*0Sstevel@tonic-gate bvariable(fcode_env_t *env)
631*0Sstevel@tonic-gate {
632*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
633*0Sstevel@tonic-gate 	show_fcode_def(env, "bvariable");
634*0Sstevel@tonic-gate 	PUSH(DS, 0);
635*0Sstevel@tonic-gate 	make_common_access(env, 0, 0, 1,
636*0Sstevel@tonic-gate 	    env->instance_mode, &instance_variable, &do_create, NULL);
637*0Sstevel@tonic-gate }
638*0Sstevel@tonic-gate 
639*0Sstevel@tonic-gate void
bconstant(fcode_env_t * env)640*0Sstevel@tonic-gate bconstant(fcode_env_t *env)
641*0Sstevel@tonic-gate {
642*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
643*0Sstevel@tonic-gate 	show_fcode_def(env, "bconstant");
644*0Sstevel@tonic-gate 	make_common_access(env, 0, 0, 1,
645*0Sstevel@tonic-gate 	    env->instance_mode, &do_constant, &do_constant, NULL);
646*0Sstevel@tonic-gate }
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate void
bdefer(fcode_env_t * env)649*0Sstevel@tonic-gate bdefer(fcode_env_t *env)
650*0Sstevel@tonic-gate {
651*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
652*0Sstevel@tonic-gate 	show_fcode_def(env, "bdefer");
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)&crash_ptr);
655*0Sstevel@tonic-gate 	make_common_access(env, 0, 0, 1, env->instance_mode,
656*0Sstevel@tonic-gate 	    &noop, &noop, &set_defer_actions);
657*0Sstevel@tonic-gate }
658*0Sstevel@tonic-gate 
659*0Sstevel@tonic-gate void
bbuffer_colon(fcode_env_t * env)660*0Sstevel@tonic-gate bbuffer_colon(fcode_env_t *env)
661*0Sstevel@tonic-gate {
662*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
663*0Sstevel@tonic-gate 	show_fcode_def(env, "buffer:");
664*0Sstevel@tonic-gate 	PUSH(DS, 0);
665*0Sstevel@tonic-gate 	make_common_access(env, 0, 0, 2, env->instance_mode,
666*0Sstevel@tonic-gate 	    &noop, &noop, &set_buffer_actions);
667*0Sstevel@tonic-gate }
668*0Sstevel@tonic-gate 
669*0Sstevel@tonic-gate void
do_field(fcode_env_t * env)670*0Sstevel@tonic-gate do_field(fcode_env_t *env)
671*0Sstevel@tonic-gate {
672*0Sstevel@tonic-gate 	fstack_t *d;
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate 	d = (fstack_t *)WA;
675*0Sstevel@tonic-gate 	TOS += *d;
676*0Sstevel@tonic-gate }
677*0Sstevel@tonic-gate 
678*0Sstevel@tonic-gate void
bfield(fcode_env_t * env)679*0Sstevel@tonic-gate bfield(fcode_env_t *env)
680*0Sstevel@tonic-gate {
681*0Sstevel@tonic-gate 	env->table[env->last_token].apf = (acf_t)HERE;
682*0Sstevel@tonic-gate 	show_fcode_def(env, "bfield");
683*0Sstevel@tonic-gate 	COMPILE_TOKEN(&do_field);
684*0Sstevel@tonic-gate 	over(env);
685*0Sstevel@tonic-gate 	compile_comma(env);
686*0Sstevel@tonic-gate 	add(env);
687*0Sstevel@tonic-gate 	expose_acf(env, "<bfield>");
688*0Sstevel@tonic-gate }
689*0Sstevel@tonic-gate 
690*0Sstevel@tonic-gate void
bto(fcode_env_t * env)691*0Sstevel@tonic-gate bto(fcode_env_t *env)
692*0Sstevel@tonic-gate {
693*0Sstevel@tonic-gate 	btick(env);
694*0Sstevel@tonic-gate 
695*0Sstevel@tonic-gate 	if (env->state) {
696*0Sstevel@tonic-gate 		COMPILE_TOKEN(&to_ptr);
697*0Sstevel@tonic-gate 	} else {
698*0Sstevel@tonic-gate 		do_set_action(env);
699*0Sstevel@tonic-gate 	}
700*0Sstevel@tonic-gate }
701*0Sstevel@tonic-gate 
702*0Sstevel@tonic-gate void
get_token(fcode_env_t * env)703*0Sstevel@tonic-gate get_token(fcode_env_t *env)
704*0Sstevel@tonic-gate {
705*0Sstevel@tonic-gate 	fstack_t tok;
706*0Sstevel@tonic-gate 	fstack_t immediate = 0;
707*0Sstevel@tonic-gate 
708*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "get-token");
709*0Sstevel@tonic-gate 	tok = POP(DS);
710*0Sstevel@tonic-gate 	tok &= MAX_FCODE;
711*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)env->table[tok].apf);
712*0Sstevel@tonic-gate 	if (env->table[tok].flags & IMMEDIATE) 	immediate = 1;
713*0Sstevel@tonic-gate 	PUSH(DS, immediate);
714*0Sstevel@tonic-gate }
715*0Sstevel@tonic-gate 
716*0Sstevel@tonic-gate void
set_token(fcode_env_t * env)717*0Sstevel@tonic-gate set_token(fcode_env_t *env)
718*0Sstevel@tonic-gate {
719*0Sstevel@tonic-gate 	fstack_t tok;
720*0Sstevel@tonic-gate 	fstack_t immediate;
721*0Sstevel@tonic-gate 	acf_t acf;
722*0Sstevel@tonic-gate 
723*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "set-token");
724*0Sstevel@tonic-gate 	tok = POP(DS);
725*0Sstevel@tonic-gate 	tok &= MAX_FCODE;
726*0Sstevel@tonic-gate 	immediate = POP(DS);
727*0Sstevel@tonic-gate 	acf = (acf_t)POP(DS);
728*0Sstevel@tonic-gate 	if (immediate)
729*0Sstevel@tonic-gate 		env->table[tok].flags |= IMMEDIATE;
730*0Sstevel@tonic-gate 	else
731*0Sstevel@tonic-gate 		env->table[tok].flags &= ~IMMEDIATE;
732*0Sstevel@tonic-gate 	env->table[tok].apf = acf;
733*0Sstevel@tonic-gate 	immediate = env->last_token;
734*0Sstevel@tonic-gate 	env->last_token = tok;
735*0Sstevel@tonic-gate 	show_fcode_def(env, "set_token");
736*0Sstevel@tonic-gate 	env->last_token = immediate;
737*0Sstevel@tonic-gate }
738*0Sstevel@tonic-gate 
739*0Sstevel@tonic-gate void
bof(fcode_env_t * env)740*0Sstevel@tonic-gate bof(fcode_env_t *env)
741*0Sstevel@tonic-gate {
742*0Sstevel@tonic-gate 	short offset = get_short(env);
743*0Sstevel@tonic-gate 	branch_common(env, offset, 2, 0);
744*0Sstevel@tonic-gate }
745*0Sstevel@tonic-gate 
746*0Sstevel@tonic-gate void
bcase(fcode_env_t * env)747*0Sstevel@tonic-gate bcase(fcode_env_t *env)
748*0Sstevel@tonic-gate {
749*0Sstevel@tonic-gate 	env->level++;
750*0Sstevel@tonic-gate 	set_temporary_compile(env);
751*0Sstevel@tonic-gate 	PUSH(DS, 0);
752*0Sstevel@tonic-gate }
753*0Sstevel@tonic-gate 
754*0Sstevel@tonic-gate void
bendcase(fcode_env_t * env)755*0Sstevel@tonic-gate bendcase(fcode_env_t *env)
756*0Sstevel@tonic-gate {
757*0Sstevel@tonic-gate 	COMPILE_TOKEN(env->table[0x46].apf);	/* Hack for now... */
758*0Sstevel@tonic-gate 	while (TOS) {
759*0Sstevel@tonic-gate 		bresolve(env);
760*0Sstevel@tonic-gate 	}
761*0Sstevel@tonic-gate 	(void) POP(DS);
762*0Sstevel@tonic-gate 	env->level--;
763*0Sstevel@tonic-gate 	temporary_execute(env);
764*0Sstevel@tonic-gate }
765*0Sstevel@tonic-gate 
766*0Sstevel@tonic-gate void
bendof(fcode_env_t * env)767*0Sstevel@tonic-gate bendof(fcode_env_t *env)
768*0Sstevel@tonic-gate {
769*0Sstevel@tonic-gate 	short offset = get_short(env);
770*0Sstevel@tonic-gate 	branch_common(env, offset, 0, 1);
771*0Sstevel@tonic-gate 	bresolve(env);
772*0Sstevel@tonic-gate }
773*0Sstevel@tonic-gate 
774*0Sstevel@tonic-gate void
fcode_revision(fcode_env_t * env)775*0Sstevel@tonic-gate fcode_revision(fcode_env_t *env)
776*0Sstevel@tonic-gate {
777*0Sstevel@tonic-gate 	/* We are Version 3.0 */
778*0Sstevel@tonic-gate 	PUSH(DS, 0x30000);
779*0Sstevel@tonic-gate }
780*0Sstevel@tonic-gate 
781*0Sstevel@tonic-gate void
alloc_mem(fcode_env_t * env)782*0Sstevel@tonic-gate alloc_mem(fcode_env_t *env)
783*0Sstevel@tonic-gate {
784*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 1, "alloc-mem");
785*0Sstevel@tonic-gate 	TOS = (fstack_t)MALLOC((size_t)TOS);
786*0Sstevel@tonic-gate 	if (!TOS) {
787*0Sstevel@tonic-gate 		throw_from_fclib(env, 1, "alloc-mem failed");
788*0Sstevel@tonic-gate 	}
789*0Sstevel@tonic-gate }
790*0Sstevel@tonic-gate 
791*0Sstevel@tonic-gate void
free_mem(fcode_env_t * env)792*0Sstevel@tonic-gate free_mem(fcode_env_t *env)
793*0Sstevel@tonic-gate {
794*0Sstevel@tonic-gate 	void *p;
795*0Sstevel@tonic-gate 
796*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "free-mem");
797*0Sstevel@tonic-gate 	(void) POP(DS);
798*0Sstevel@tonic-gate 	p = (void *) POP(DS);
799*0Sstevel@tonic-gate 	FREE(p);
800*0Sstevel@tonic-gate }
801*0Sstevel@tonic-gate 
802*0Sstevel@tonic-gate void
parse_two_int(fcode_env_t * env)803*0Sstevel@tonic-gate parse_two_int(fcode_env_t *env)
804*0Sstevel@tonic-gate {
805*0Sstevel@tonic-gate 	uint_t lo, hi;
806*0Sstevel@tonic-gate 	char *str;
807*0Sstevel@tonic-gate 	int len;
808*0Sstevel@tonic-gate 
809*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "parse-2int");
810*0Sstevel@tonic-gate 	lo = 0;
811*0Sstevel@tonic-gate 	hi = 0;
812*0Sstevel@tonic-gate 	str = pop_a_string(env, &len);
813*0Sstevel@tonic-gate 	if (len) {
814*0Sstevel@tonic-gate 		if (sscanf(str, "%x,%x", &hi, &lo) != 2) {
815*0Sstevel@tonic-gate 			throw_from_fclib(env, 1, "parse_2int");
816*0Sstevel@tonic-gate 		}
817*0Sstevel@tonic-gate 	}
818*0Sstevel@tonic-gate 	PUSH(DS, lo);
819*0Sstevel@tonic-gate 	PUSH(DS, hi);
820*0Sstevel@tonic-gate }
821*0Sstevel@tonic-gate 
822*0Sstevel@tonic-gate void
left_parse_string(fcode_env_t * env)823*0Sstevel@tonic-gate left_parse_string(fcode_env_t *env)
824*0Sstevel@tonic-gate {
825*0Sstevel@tonic-gate 	char sep, *cptr, *lstr, *rstr;
826*0Sstevel@tonic-gate 	int len, llen, rlen;
827*0Sstevel@tonic-gate 
828*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "left-parse-string");
829*0Sstevel@tonic-gate 	sep = (char)POP(DS);
830*0Sstevel@tonic-gate 	if (TOS == 0) {
831*0Sstevel@tonic-gate 		two_dup(env);
832*0Sstevel@tonic-gate 		return;
833*0Sstevel@tonic-gate 	}
834*0Sstevel@tonic-gate 	lstr = pop_a_string(env, &llen);
835*0Sstevel@tonic-gate 	len = 0;
836*0Sstevel@tonic-gate 	cptr = NULL;
837*0Sstevel@tonic-gate 	while (len < llen) {
838*0Sstevel@tonic-gate 		if (lstr[len] == sep) {
839*0Sstevel@tonic-gate 			cptr = lstr+len;
840*0Sstevel@tonic-gate 			break;
841*0Sstevel@tonic-gate 		}
842*0Sstevel@tonic-gate 		len++;
843*0Sstevel@tonic-gate 	}
844*0Sstevel@tonic-gate 	if (cptr != NULL) {
845*0Sstevel@tonic-gate 		rstr = cptr+1;
846*0Sstevel@tonic-gate 		rlen = lstr + llen - rstr;
847*0Sstevel@tonic-gate 		llen = len;
848*0Sstevel@tonic-gate 	} else {
849*0Sstevel@tonic-gate 		rlen = 0;
850*0Sstevel@tonic-gate 		rstr = lstr;
851*0Sstevel@tonic-gate 	}
852*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)rstr);
853*0Sstevel@tonic-gate 	PUSH(DS, rlen);
854*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)lstr);
855*0Sstevel@tonic-gate 	PUSH(DS, llen);
856*0Sstevel@tonic-gate }
857*0Sstevel@tonic-gate 
858*0Sstevel@tonic-gate /*
859*0Sstevel@tonic-gate  * (is-user-word)  ( name-str name-len xt -- )
860*0Sstevel@tonic-gate  */
861*0Sstevel@tonic-gate void
is_user_word(fcode_env_t * env)862*0Sstevel@tonic-gate is_user_word(fcode_env_t *env)
863*0Sstevel@tonic-gate {
864*0Sstevel@tonic-gate 	fstack_t xt;
865*0Sstevel@tonic-gate 	char *name;
866*0Sstevel@tonic-gate 	int len;
867*0Sstevel@tonic-gate 
868*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 3, "(is-user-word)");
869*0Sstevel@tonic-gate 	xt = POP(DS);
870*0Sstevel@tonic-gate 	name = pop_a_string(env, &len);
871*0Sstevel@tonic-gate 	header(env, name, len, 0);
872*0Sstevel@tonic-gate 	COMPILE_TOKEN(&do_alias);
873*0Sstevel@tonic-gate 	COMPILE_TOKEN(xt);
874*0Sstevel@tonic-gate 	expose_acf(env, name);
875*0Sstevel@tonic-gate }
876*0Sstevel@tonic-gate 
877*0Sstevel@tonic-gate void
f_error(fcode_env_t * env)878*0Sstevel@tonic-gate f_error(fcode_env_t *env)
879*0Sstevel@tonic-gate {
880*0Sstevel@tonic-gate #if 0
881*0Sstevel@tonic-gate 	env->interpretting = 0;
882*0Sstevel@tonic-gate 	log_message(MSG_ERROR, "Uniplemented FCODE token encountered %x\n",
883*0Sstevel@tonic-gate 	    env->last_fcode);
884*0Sstevel@tonic-gate #else
885*0Sstevel@tonic-gate 	forth_abort(env, "Unimplemented FCODE token: 0x%x\n", env->last_fcode);
886*0Sstevel@tonic-gate #endif
887*0Sstevel@tonic-gate }
888*0Sstevel@tonic-gate 
889*0Sstevel@tonic-gate static void
fcode_buffer_addr(fcode_env_t * env)890*0Sstevel@tonic-gate fcode_buffer_addr(fcode_env_t *env)
891*0Sstevel@tonic-gate {
892*0Sstevel@tonic-gate 	PUSH(DS, (fstack_t)(env->fcode_buffer));
893*0Sstevel@tonic-gate }
894*0Sstevel@tonic-gate 
895*0Sstevel@tonic-gate #pragma init(_init)
896*0Sstevel@tonic-gate 
897*0Sstevel@tonic-gate static void
_init(void)898*0Sstevel@tonic-gate _init(void)
899*0Sstevel@tonic-gate {
900*0Sstevel@tonic-gate 	fcode_env_t *env = initial_env;
901*0Sstevel@tonic-gate 
902*0Sstevel@tonic-gate 	ASSERT(env);
903*0Sstevel@tonic-gate 	NOTICE;
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate 	P1275(0x000, DEFINER,	"end0",			end0);
906*0Sstevel@tonic-gate 	P1275(0x010, DEFINER,	"b(lit)",		blit);
907*0Sstevel@tonic-gate 	P1275(0x011, DEFINER,	"b(')",			btick);
908*0Sstevel@tonic-gate 	P1275(0x012, DEFINER,	"b(\")",		bquote);
909*0Sstevel@tonic-gate 	P1275(0x013, DEFINER,	"bbranch",		bbranch);
910*0Sstevel@tonic-gate 	P1275(0x014, DEFINER,	"b?branch",		bqbranch);
911*0Sstevel@tonic-gate 	P1275(0x015, DEFINER,	"b(loop)",		bloop);
912*0Sstevel@tonic-gate 	P1275(0x016, DEFINER,	"b(+loop)",		bplusloop);
913*0Sstevel@tonic-gate 	P1275(0x017, DEFINER,	"b(do)",		bdo);
914*0Sstevel@tonic-gate 	P1275(0x018, DEFINER,	"b(?do)",		bqdo);
915*0Sstevel@tonic-gate 	P1275(0x01b, DEFINER,	"b(leave)",		bleave);
916*0Sstevel@tonic-gate 	P1275(0x01c, DEFINER,	"b(of)",		bof);
917*0Sstevel@tonic-gate 
918*0Sstevel@tonic-gate 	P1275(0x087, 0,		"fcode-revision",	fcode_revision);
919*0Sstevel@tonic-gate 
920*0Sstevel@tonic-gate 	P1275(0x08b, 0,		"alloc-mem",		alloc_mem);
921*0Sstevel@tonic-gate 	P1275(0x08c, 0,		"free-mem",		free_mem);
922*0Sstevel@tonic-gate 
923*0Sstevel@tonic-gate 	P1275(0x0a4, 0,		"-1",			minus_one);
924*0Sstevel@tonic-gate 	P1275(0x0a5, 0,		"0",			zero);
925*0Sstevel@tonic-gate 	P1275(0x0a6, 0,		"1",			one);
926*0Sstevel@tonic-gate 	P1275(0x0a7, 0,		"2",			two);
927*0Sstevel@tonic-gate 	P1275(0x0a8, 0,		"3",			three);
928*0Sstevel@tonic-gate 
929*0Sstevel@tonic-gate 	P1275(0x0ae, 0,		"aligned",		aligned);
930*0Sstevel@tonic-gate 	P1275(0x0b1, DEFINER,	"b(<mark)",		bmark);
931*0Sstevel@tonic-gate 	P1275(0x0b2, DEFINER,	"b(>resolve)",		bresolve);
932*0Sstevel@tonic-gate 	FCODE(0x0b3, 0,		"set-token-table",	fc_historical);
933*0Sstevel@tonic-gate 	FCODE(0x0b4, 0,		"set-table",		fc_historical);
934*0Sstevel@tonic-gate 	P1275(0x0b5, 0,		"new-token",		new_token);
935*0Sstevel@tonic-gate 	P1275(0x0b6, 0,		"named-token",		named_token);
936*0Sstevel@tonic-gate 	P1275(0x0b7, DEFINER,	"b(:)",			bcolon);
937*0Sstevel@tonic-gate 	P1275(0x0b8, DEFINER,	"b(value)",		bvalue);
938*0Sstevel@tonic-gate 	P1275(0x0b9, DEFINER,	"b(variable)",		bvariable);
939*0Sstevel@tonic-gate 	P1275(0x0ba, DEFINER,	"b(constant)",		bconstant);
940*0Sstevel@tonic-gate 	P1275(0x0bb, DEFINER,	"b(create)",		bcreate);
941*0Sstevel@tonic-gate 	P1275(0x0bc, DEFINER,	"b(defer)",		bdefer);
942*0Sstevel@tonic-gate 	P1275(0x0bd, 0,		"b(buffer:)",		bbuffer_colon);
943*0Sstevel@tonic-gate 	P1275(0x0be, 0,		"b(field)",		bfield);
944*0Sstevel@tonic-gate 	FCODE(0x0bf, 0,		"b(code)",		fc_historical);
945*0Sstevel@tonic-gate 	P1275(0x0c0, IMMEDIATE,	"instance",		instance);
946*0Sstevel@tonic-gate 
947*0Sstevel@tonic-gate 	P1275(0x0c2, DEFINER,	"b(;)",			semi);
948*0Sstevel@tonic-gate 	P1275(0x0c3, DEFINER,	"b(to)",		bto);
949*0Sstevel@tonic-gate 	P1275(0x0c4, DEFINER,	"b(case)",		bcase);
950*0Sstevel@tonic-gate 	P1275(0x0c5, DEFINER,	"b(endcase)",		bendcase);
951*0Sstevel@tonic-gate 	P1275(0x0c6, DEFINER,	"b(endof)",		bendof);
952*0Sstevel@tonic-gate 
953*0Sstevel@tonic-gate 	P1275(0x0ca, 0,		"external-token",	external_token);
954*0Sstevel@tonic-gate 	P1275(0x0cc, 0,		"offset16",		offset16);
955*0Sstevel@tonic-gate 	P1275(0x0cd, 0,		"evaluate",		evaluate);
956*0Sstevel@tonic-gate 
957*0Sstevel@tonic-gate 	P1275(0x0da, 0,		"get-token",		get_token);
958*0Sstevel@tonic-gate 	P1275(0x0db, 0,		"set-token",		set_token);
959*0Sstevel@tonic-gate 
960*0Sstevel@tonic-gate 	P1275(0x0f0, 0,		"start0",		start0);
961*0Sstevel@tonic-gate 	P1275(0x0f1, 0,		"start1",		start1);
962*0Sstevel@tonic-gate 	P1275(0x0f2, 0,		"start2",		start2);
963*0Sstevel@tonic-gate 	P1275(0x0f3, 0,		"start4",		start4);
964*0Sstevel@tonic-gate 
965*0Sstevel@tonic-gate 	P1275(0x0fd, 0,		"version1",		version1);
966*0Sstevel@tonic-gate 	FCODE(0x0fe, 0,		"4-byte-id",		fc_historical);
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate 	P1275(0x0ff, 0,		"end1",			end1);
969*0Sstevel@tonic-gate 
970*0Sstevel@tonic-gate 	/* Call it "old-dma-alloc" so no one gets confused */
971*0Sstevel@tonic-gate 	FCODE(0x101, 0,		"old-dma-alloc",	fc_historical);
972*0Sstevel@tonic-gate 
973*0Sstevel@tonic-gate 	FCODE(0x104, 0,		"memmap",		fc_historical);
974*0Sstevel@tonic-gate 	FCODE(0x105, 0,		"free-virtual",		fc_unimplemented);
975*0Sstevel@tonic-gate 
976*0Sstevel@tonic-gate 	FCODE(0x106, 0,		">physical",		fc_historical);
977*0Sstevel@tonic-gate 
978*0Sstevel@tonic-gate 	FCODE(0x10f, 0,		"my-params",		fc_historical);
979*0Sstevel@tonic-gate 
980*0Sstevel@tonic-gate 	P1275(0x11b, 0,		"parse-2int",		parse_two_int);
981*0Sstevel@tonic-gate 
982*0Sstevel@tonic-gate 	FCODE(0x122, 0,		"memory-test-suite",	fc_unimplemented);
983*0Sstevel@tonic-gate 	FCODE(0x123, 0,		"group-code",		fc_historical);
984*0Sstevel@tonic-gate 	FCODE(0x124, 0,		"mask",			fc_unimplemented);
985*0Sstevel@tonic-gate 
986*0Sstevel@tonic-gate 	FCODE(0x130, 0,		"map-low",		fc_unimplemented);
987*0Sstevel@tonic-gate 	FCODE(0x131, 0,		"sbus-intr>cpu",	fc_unimplemented);
988*0Sstevel@tonic-gate 
989*0Sstevel@tonic-gate 	FCODE(0x170, 0,		"fb1-draw-character",	fc_historical);
990*0Sstevel@tonic-gate 	FCODE(0x171, 0,		"fb1-reset-screen",	fc_historical);
991*0Sstevel@tonic-gate 	FCODE(0x172, 0,		"fb1-toggle-cursor",	fc_historical);
992*0Sstevel@tonic-gate 	FCODE(0x173, 0,		"fb1-erase-screen",	fc_historical);
993*0Sstevel@tonic-gate 	FCODE(0x174, 0,		"fb1-blink-screen",	fc_historical);
994*0Sstevel@tonic-gate 	FCODE(0x175, 0,		"fb1-invert-screen",	fc_historical);
995*0Sstevel@tonic-gate 	FCODE(0x176, 0,		"fb1-insert-characters",	fc_historical);
996*0Sstevel@tonic-gate 	FCODE(0x177, 0,		"fb1-delete-characters",	fc_historical);
997*0Sstevel@tonic-gate 	FCODE(0x178, 0,		"fb1-insert-lines",	fc_historical);
998*0Sstevel@tonic-gate 	FCODE(0x179, 0,		"fb1-delete-lines",	fc_historical);
999*0Sstevel@tonic-gate 	FCODE(0x17a, 0,		"fb1-draw-logo",	fc_historical);
1000*0Sstevel@tonic-gate 	FCODE(0x17b, 0,		"fb1-install",		fc_historical);
1001*0Sstevel@tonic-gate 	FCODE(0x17c, 0,		"fb1-slide-up",		fc_historical);
1002*0Sstevel@tonic-gate 
1003*0Sstevel@tonic-gate 	FCODE(0x190, 0,		"VME-bus Support",	fc_obsolete);
1004*0Sstevel@tonic-gate 	FCODE(0x191, 0,		"VME-bus Support",	fc_obsolete);
1005*0Sstevel@tonic-gate 	FCODE(0x192, 0,		"VME-bus Support",	fc_obsolete);
1006*0Sstevel@tonic-gate 	FCODE(0x193, 0,		"VME-bus Support",	fc_obsolete);
1007*0Sstevel@tonic-gate 	FCODE(0x194, 0,		"VME-bus Support",	fc_obsolete);
1008*0Sstevel@tonic-gate 	FCODE(0x195, 0,		"VME-bus Support",	fc_obsolete);
1009*0Sstevel@tonic-gate 	FCODE(0x196, 0,		"VME-bus Support",	fc_obsolete);
1010*0Sstevel@tonic-gate 
1011*0Sstevel@tonic-gate 	FCODE(0x1a0, 0,		"return-buffer",	fc_historical);
1012*0Sstevel@tonic-gate 	FCODE(0x1a1, 0,		"xmit-packet",		fc_historical);
1013*0Sstevel@tonic-gate 	FCODE(0x1a2, 0,		"poll-packet",		fc_historical);
1014*0Sstevel@tonic-gate 
1015*0Sstevel@tonic-gate 	FCODE(0x210, 0,		"processor-type",	fc_historical);
1016*0Sstevel@tonic-gate 	FCODE(0x211, 0,		"firmware-version",	fc_historical);
1017*0Sstevel@tonic-gate 	FCODE(0x212, 0,		"fcode-version",	fc_historical);
1018*0Sstevel@tonic-gate 
1019*0Sstevel@tonic-gate 	FCODE(0x214, 0,		"(is-user-word)",	is_user_word);
1020*0Sstevel@tonic-gate 	FCODE(0x215, 0,		"suspend-fcode",	fc_unimplemented);
1021*0Sstevel@tonic-gate 
1022*0Sstevel@tonic-gate 	FCODE(0x229, 0,		"adr-mask",		fc_historical);
1023*0Sstevel@tonic-gate 
1024*0Sstevel@tonic-gate 	FCODE(0x238, 0,		"probe",		fc_historical);
1025*0Sstevel@tonic-gate 	FCODE(0x239, 0,		"probe-virtual",	fc_historical);
1026*0Sstevel@tonic-gate 
1027*0Sstevel@tonic-gate 	P1275(0x23e, 0,		"byte-load",		byte_load);
1028*0Sstevel@tonic-gate 
1029*0Sstevel@tonic-gate 	P1275(0x240, 0,		"left-parse-string",	left_parse_string);
1030*0Sstevel@tonic-gate 	FORTH(0,		"fcode-buffer",		fcode_buffer_addr);
1031*0Sstevel@tonic-gate }
1032