xref: /titanic_44/usr/src/lib/efcode/engine/debug.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2000-2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <string.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <stdarg.h>
33*7c478bd9Sstevel@tonic-gate #include <unistd.h>
34*7c478bd9Sstevel@tonic-gate #include <errno.h>
35*7c478bd9Sstevel@tonic-gate #include <ctype.h>
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #include <fcode/private.h>
38*7c478bd9Sstevel@tonic-gate #include <fcode/log.h>
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate #ifndef DEBUG_LVL
41*7c478bd9Sstevel@tonic-gate #define	DEBUG_LVL	0
42*7c478bd9Sstevel@tonic-gate #endif
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate struct bitab {
45*7c478bd9Sstevel@tonic-gate 	token_t bi_ptr;
46*7c478bd9Sstevel@tonic-gate 	char *bi_name;
47*7c478bd9Sstevel@tonic-gate 	int bi_type;
48*7c478bd9Sstevel@tonic-gate };
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate struct bitab *lookup_builtin(token_t);
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate static int debug_level = DEBUG_LVL;
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate void
55*7c478bd9Sstevel@tonic-gate set_interpreter_debug_level(long lvl)
56*7c478bd9Sstevel@tonic-gate {
57*7c478bd9Sstevel@tonic-gate 	debug_level = lvl;
58*7c478bd9Sstevel@tonic-gate }
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate long
61*7c478bd9Sstevel@tonic-gate get_interpreter_debug_level(void)
62*7c478bd9Sstevel@tonic-gate {
63*7c478bd9Sstevel@tonic-gate 	return (debug_level);
64*7c478bd9Sstevel@tonic-gate }
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate void
67*7c478bd9Sstevel@tonic-gate output_data_stack(fcode_env_t *env, int msglevel)
68*7c478bd9Sstevel@tonic-gate {
69*7c478bd9Sstevel@tonic-gate 	int i;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 	log_message(msglevel, "( ");
72*7c478bd9Sstevel@tonic-gate 	if (DS > env->ds0) {
73*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < (DS - env->ds0); i++)
74*7c478bd9Sstevel@tonic-gate 			log_message(msglevel, "%llx ",
75*7c478bd9Sstevel@tonic-gate 			    (uint64_t)(env->ds0[i + 1]));
76*7c478bd9Sstevel@tonic-gate 	} else
77*7c478bd9Sstevel@tonic-gate 		log_message(msglevel, "<empty> ");
78*7c478bd9Sstevel@tonic-gate 	log_message(msglevel, ") ");
79*7c478bd9Sstevel@tonic-gate }
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate void
82*7c478bd9Sstevel@tonic-gate output_return_stack(fcode_env_t *env, int show_wa, int msglevel)
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	int i;
85*7c478bd9Sstevel@tonic-gate 	int anyout = 0;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	log_message(msglevel, "R:( ");
88*7c478bd9Sstevel@tonic-gate 	if (show_wa) {
89*7c478bd9Sstevel@tonic-gate 		log_message(msglevel, "%s ",
90*7c478bd9Sstevel@tonic-gate 		    acf_backup_search(env, (acf_t)WA));
91*7c478bd9Sstevel@tonic-gate 		anyout++;
92*7c478bd9Sstevel@tonic-gate 	}
93*7c478bd9Sstevel@tonic-gate 	if (IP) {
94*7c478bd9Sstevel@tonic-gate 		anyout++;
95*7c478bd9Sstevel@tonic-gate 		log_message(msglevel, "%s ", acf_backup_search(env, IP));
96*7c478bd9Sstevel@tonic-gate 	}
97*7c478bd9Sstevel@tonic-gate 	for (i = (RS - env->rs0) - 1; i > 0; i--) {
98*7c478bd9Sstevel@tonic-gate 		anyout++;
99*7c478bd9Sstevel@tonic-gate 		log_message(msglevel, "%s ",
100*7c478bd9Sstevel@tonic-gate 			    acf_backup_search(env, (acf_t)env->rs0[i+1]));
101*7c478bd9Sstevel@tonic-gate 	}
102*7c478bd9Sstevel@tonic-gate 	if (!anyout)
103*7c478bd9Sstevel@tonic-gate 		log_message(msglevel, "<empty> ");
104*7c478bd9Sstevel@tonic-gate 	log_message(msglevel, ") ");
105*7c478bd9Sstevel@tonic-gate }
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate void
108*7c478bd9Sstevel@tonic-gate dump_comma(fcode_env_t *env, char *type)
109*7c478bd9Sstevel@tonic-gate {
110*7c478bd9Sstevel@tonic-gate 	xforth_t d;
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	if (strcmp(type, "x,") == 0)
113*7c478bd9Sstevel@tonic-gate 		d = peek_xforth(env);
114*7c478bd9Sstevel@tonic-gate 	else
115*7c478bd9Sstevel@tonic-gate 		d = TOS;
116*7c478bd9Sstevel@tonic-gate 	log_message(MSG_FC_DEBUG, "%s %p, %llx\n", type, HERE, (uint64_t)d);
117*7c478bd9Sstevel@tonic-gate }
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate static int ndebug_names;
120*7c478bd9Sstevel@tonic-gate #define	MAXDEBUG_NAMES	10
121*7c478bd9Sstevel@tonic-gate static char *debug_names[MAXDEBUG_NAMES];
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate static int ndebug_acfs;
124*7c478bd9Sstevel@tonic-gate #define	MAXDEBUG_ACFS	10
125*7c478bd9Sstevel@tonic-gate static acf_t debug_acfs[MAXDEBUG_ACFS];
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate void
128*7c478bd9Sstevel@tonic-gate add_debug_acf(fcode_env_t *env, acf_t acf)
129*7c478bd9Sstevel@tonic-gate {
130*7c478bd9Sstevel@tonic-gate 	int i;
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ndebug_acfs; i++)
133*7c478bd9Sstevel@tonic-gate 		if (acf == debug_acfs[i])
134*7c478bd9Sstevel@tonic-gate 			return;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	if (!within_dictionary(env, acf))
137*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "Can't debug builtin\n");
138*7c478bd9Sstevel@tonic-gate 	else if (ndebug_acfs >= MAXDEBUG_ACFS)
139*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "Too many debug ACF's\n");
140*7c478bd9Sstevel@tonic-gate 	else {
141*7c478bd9Sstevel@tonic-gate 		debug_acfs[ndebug_acfs++] = acf;
142*7c478bd9Sstevel@tonic-gate 		*LINK_TO_FLAGS(ACF_TO_LINK(acf)) |= FLAG_DEBUG;
143*7c478bd9Sstevel@tonic-gate 	}
144*7c478bd9Sstevel@tonic-gate }
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate static void
147*7c478bd9Sstevel@tonic-gate paren_debug(fcode_env_t *env)
148*7c478bd9Sstevel@tonic-gate {
149*7c478bd9Sstevel@tonic-gate 	acf_t acf;
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	acf = (acf_t)POP(DS);
152*7c478bd9Sstevel@tonic-gate 	if (!within_dictionary(env, acf)) {
153*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "acf: %llx not in dictionary\n",
154*7c478bd9Sstevel@tonic-gate 		    (uint64_t)acf);
155*7c478bd9Sstevel@tonic-gate 		return;
156*7c478bd9Sstevel@tonic-gate 	}
157*7c478bd9Sstevel@tonic-gate 	if ((acf_t)_ALIGN(acf, token_t) != acf) {
158*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "acf: %llx not aligned\n",
159*7c478bd9Sstevel@tonic-gate 		    (uint64_t)acf);
160*7c478bd9Sstevel@tonic-gate 		return;
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 	if (*acf != (token_t)(&do_colon)) {
163*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "acf: %llx not a colon-def\n",
164*7c478bd9Sstevel@tonic-gate 		    (uint64_t)acf);
165*7c478bd9Sstevel@tonic-gate 		return;
166*7c478bd9Sstevel@tonic-gate 	}
167*7c478bd9Sstevel@tonic-gate 	add_debug_acf(env, acf);
168*7c478bd9Sstevel@tonic-gate }
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate static void
171*7c478bd9Sstevel@tonic-gate debug(fcode_env_t *env)
172*7c478bd9Sstevel@tonic-gate {
173*7c478bd9Sstevel@tonic-gate 	fstack_t d;
174*7c478bd9Sstevel@tonic-gate 	char *word;
175*7c478bd9Sstevel@tonic-gate 	acf_t acf;
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	parse_word(env);
178*7c478bd9Sstevel@tonic-gate 	dollar_find(env);
179*7c478bd9Sstevel@tonic-gate 	d = POP(DS);
180*7c478bd9Sstevel@tonic-gate 	if (d) {
181*7c478bd9Sstevel@tonic-gate 		acf = (acf_t)POP(DS);
182*7c478bd9Sstevel@tonic-gate 		add_debug_acf(env, acf);
183*7c478bd9Sstevel@tonic-gate 	} else if (ndebug_names >= MAXDEBUG_NAMES) {
184*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "Too many forward debug words\n");
185*7c478bd9Sstevel@tonic-gate 		two_drop(env);
186*7c478bd9Sstevel@tonic-gate 	} else {
187*7c478bd9Sstevel@tonic-gate 		word = pop_a_duped_string(env, NULL);
188*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "Forward defined word: %s\n", word);
189*7c478bd9Sstevel@tonic-gate 		debug_names[ndebug_names++] = word;
190*7c478bd9Sstevel@tonic-gate 	}
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * Eliminate dups and add vocabulary forth to end if not already on list.
195*7c478bd9Sstevel@tonic-gate  */
196*7c478bd9Sstevel@tonic-gate static void
197*7c478bd9Sstevel@tonic-gate order_to_dict_list(fcode_env_t *env, token_t *order[])
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate 	int i, j, norder = 0;
200*7c478bd9Sstevel@tonic-gate 
201*7c478bd9Sstevel@tonic-gate 	if (env->current)
202*7c478bd9Sstevel@tonic-gate 		order[norder++] = env->current;
203*7c478bd9Sstevel@tonic-gate 	for (i = env->order_depth; i >= 0; i--) {
204*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < norder && order[j] != env->order[i]; j++)
205*7c478bd9Sstevel@tonic-gate 			;
206*7c478bd9Sstevel@tonic-gate 		if (j == norder)
207*7c478bd9Sstevel@tonic-gate 			order[norder++] = env->order[i];
208*7c478bd9Sstevel@tonic-gate 	}
209*7c478bd9Sstevel@tonic-gate 	for (j = 0; j < norder && order[j] != (token_t *)&env->forth_voc_link;
210*7c478bd9Sstevel@tonic-gate 	    j++)
211*7c478bd9Sstevel@tonic-gate 		;
212*7c478bd9Sstevel@tonic-gate 	if (j == norder)
213*7c478bd9Sstevel@tonic-gate 		order[norder++] = (token_t *)&env->forth_voc_link;
214*7c478bd9Sstevel@tonic-gate 	order[norder] = NULL;
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate static acf_t
218*7c478bd9Sstevel@tonic-gate search_all_dictionaries(fcode_env_t *env,
219*7c478bd9Sstevel@tonic-gate     acf_t (*fn)(fcode_env_t *, acf_t, void *),
220*7c478bd9Sstevel@tonic-gate     void *arg)
221*7c478bd9Sstevel@tonic-gate {
222*7c478bd9Sstevel@tonic-gate 	token_t *order[MAX_ORDER+1];
223*7c478bd9Sstevel@tonic-gate 	int i;
224*7c478bd9Sstevel@tonic-gate 	token_t *dptr;
225*7c478bd9Sstevel@tonic-gate 	acf_t acf;
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate 	order_to_dict_list(env, order);
228*7c478bd9Sstevel@tonic-gate 	for (i = 0; (dptr = order[i]) != NULL; i++) {
229*7c478bd9Sstevel@tonic-gate 		for (dptr = (token_t *)(*dptr); dptr;
230*7c478bd9Sstevel@tonic-gate 		    dptr = (token_t *)(*dptr))
231*7c478bd9Sstevel@tonic-gate 			if ((acf = (*fn)(env, LINK_TO_ACF(dptr), arg)) != NULL)
232*7c478bd9Sstevel@tonic-gate 				return (acf);
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 	return (NULL);
235*7c478bd9Sstevel@tonic-gate }
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate char *
238*7c478bd9Sstevel@tonic-gate acf_to_str(acf_t acf)
239*7c478bd9Sstevel@tonic-gate {
240*7c478bd9Sstevel@tonic-gate 	static char msg[(sizeof (acf) * 2) + 3];
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	sprintf(msg, "(%08p)", acf);
243*7c478bd9Sstevel@tonic-gate 	return (msg);
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate 
246*7c478bd9Sstevel@tonic-gate char *
247*7c478bd9Sstevel@tonic-gate get_name_or_acf(token_t *dptr)
248*7c478bd9Sstevel@tonic-gate {
249*7c478bd9Sstevel@tonic-gate 	char *name;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	if ((name = get_name(dptr)) != NULL)
252*7c478bd9Sstevel@tonic-gate 		return (name);
253*7c478bd9Sstevel@tonic-gate 	return (acf_to_str(LINK_TO_ACF(dptr)));
254*7c478bd9Sstevel@tonic-gate }
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate static void
257*7c478bd9Sstevel@tonic-gate output_acf_name(acf_t acf)
258*7c478bd9Sstevel@tonic-gate {
259*7c478bd9Sstevel@tonic-gate 	char *name;
260*7c478bd9Sstevel@tonic-gate 	token_t *dptr;
261*7c478bd9Sstevel@tonic-gate 	static int acf_count = 0;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	if (acf == NULL) {
264*7c478bd9Sstevel@tonic-gate 		if (acf_count)
265*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "\n");
266*7c478bd9Sstevel@tonic-gate 		acf_count = 0;
267*7c478bd9Sstevel@tonic-gate 		return;
268*7c478bd9Sstevel@tonic-gate 	}
269*7c478bd9Sstevel@tonic-gate 	dptr = ACF_TO_LINK(acf);
270*7c478bd9Sstevel@tonic-gate 	if ((name = get_name(dptr)) == NULL)
271*7c478bd9Sstevel@tonic-gate 		name = "<noname>";
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "%24s (%08p)", name, acf);
274*7c478bd9Sstevel@tonic-gate 	if (++acf_count >= 2) {
275*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "\n");
276*7c478bd9Sstevel@tonic-gate 		acf_count = 0;
277*7c478bd9Sstevel@tonic-gate 	} else
278*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "    ");
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate static void
282*7c478bd9Sstevel@tonic-gate dot_debug(fcode_env_t *env)
283*7c478bd9Sstevel@tonic-gate {
284*7c478bd9Sstevel@tonic-gate 	int i;
285*7c478bd9Sstevel@tonic-gate 	token_t *dptr;
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	if (ndebug_names == 0)
288*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "No forward debug words\n");
289*7c478bd9Sstevel@tonic-gate 	else {
290*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < ndebug_names; i++)
291*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%s Forward\n", debug_names[i]);
292*7c478bd9Sstevel@tonic-gate 	}
293*7c478bd9Sstevel@tonic-gate 	if (ndebug_acfs == 0)
294*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "No debug words\n");
295*7c478bd9Sstevel@tonic-gate 	else {
296*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < ndebug_acfs; i++)
297*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%s\n",
298*7c478bd9Sstevel@tonic-gate 			    get_name_or_acf(ACF_TO_LINK(debug_acfs[i])));
299*7c478bd9Sstevel@tonic-gate 	}
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate static void
303*7c478bd9Sstevel@tonic-gate do_undebug(fcode_env_t *env, char *name)
304*7c478bd9Sstevel@tonic-gate {
305*7c478bd9Sstevel@tonic-gate 	int i;
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ndebug_names; i++) {
308*7c478bd9Sstevel@tonic-gate 		if (strcmp(debug_names[i], name) == 0) {
309*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "Undebugging forward word %s\n",
310*7c478bd9Sstevel@tonic-gate 			    name);
311*7c478bd9Sstevel@tonic-gate 			FREE(debug_names[i]);
312*7c478bd9Sstevel@tonic-gate 			for (i++; i < ndebug_names; i++)
313*7c478bd9Sstevel@tonic-gate 				debug_names[i - 1] = debug_names[i];
314*7c478bd9Sstevel@tonic-gate 			ndebug_names--;
315*7c478bd9Sstevel@tonic-gate 			break;
316*7c478bd9Sstevel@tonic-gate 		}
317*7c478bd9Sstevel@tonic-gate 	}
318*7c478bd9Sstevel@tonic-gate }
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate static void
321*7c478bd9Sstevel@tonic-gate undebug(fcode_env_t *env)
322*7c478bd9Sstevel@tonic-gate {
323*7c478bd9Sstevel@tonic-gate 	fstack_t d;
324*7c478bd9Sstevel@tonic-gate 	acf_t acf;
325*7c478bd9Sstevel@tonic-gate 	flag_t *flagp;
326*7c478bd9Sstevel@tonic-gate 	char *name;
327*7c478bd9Sstevel@tonic-gate 	int i, j;
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 	parse_word(env);
330*7c478bd9Sstevel@tonic-gate 	two_dup(env);
331*7c478bd9Sstevel@tonic-gate 	dollar_find(env);
332*7c478bd9Sstevel@tonic-gate 	d = POP(DS);
333*7c478bd9Sstevel@tonic-gate 	if (d) {
334*7c478bd9Sstevel@tonic-gate 		acf = (acf_t)POP(DS);
335*7c478bd9Sstevel@tonic-gate 		flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf));
336*7c478bd9Sstevel@tonic-gate 		if ((*flagp & FLAG_DEBUG) == 0)
337*7c478bd9Sstevel@tonic-gate 			log_message(MSG_WARN, "Word not debugged?\n");
338*7c478bd9Sstevel@tonic-gate 		else {
339*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "Undebugging acf: %p\n", acf);
340*7c478bd9Sstevel@tonic-gate 			*flagp &= ~FLAG_DEBUG;
341*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < ndebug_acfs; i++) {
342*7c478bd9Sstevel@tonic-gate 				if (debug_acfs[i] == acf) {
343*7c478bd9Sstevel@tonic-gate 					for (j = i + 1; j < ndebug_acfs; j++)
344*7c478bd9Sstevel@tonic-gate 						debug_acfs[j-1] = debug_acfs[j];
345*7c478bd9Sstevel@tonic-gate 					ndebug_acfs--;
346*7c478bd9Sstevel@tonic-gate 					break;
347*7c478bd9Sstevel@tonic-gate 				}
348*7c478bd9Sstevel@tonic-gate 			}
349*7c478bd9Sstevel@tonic-gate 		}
350*7c478bd9Sstevel@tonic-gate 	} else
351*7c478bd9Sstevel@tonic-gate 		two_drop(env);
352*7c478bd9Sstevel@tonic-gate 	name = pop_a_string(env, NULL);
353*7c478bd9Sstevel@tonic-gate 	do_undebug(env, name);
354*7c478bd9Sstevel@tonic-gate }
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate int
357*7c478bd9Sstevel@tonic-gate name_is_debugged(fcode_env_t *env, char *name)
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate 	int i;
360*7c478bd9Sstevel@tonic-gate 
361*7c478bd9Sstevel@tonic-gate 	if (ndebug_names <= 0)
362*7c478bd9Sstevel@tonic-gate 		return (0);
363*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ndebug_names; i++)
364*7c478bd9Sstevel@tonic-gate 		if (strcmp(debug_names[i], name) == 0)
365*7c478bd9Sstevel@tonic-gate 			return (1);
366*7c478bd9Sstevel@tonic-gate 	return (0);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate /*
370*7c478bd9Sstevel@tonic-gate  * This is complicated by being given ACF's to temporary compile words which
371*7c478bd9Sstevel@tonic-gate  * don't have a header.
372*7c478bd9Sstevel@tonic-gate  */
373*7c478bd9Sstevel@tonic-gate int
374*7c478bd9Sstevel@tonic-gate is_debug_word(fcode_env_t *env, acf_t acf)
375*7c478bd9Sstevel@tonic-gate {
376*7c478bd9Sstevel@tonic-gate 	flag_t *flagp;
377*7c478bd9Sstevel@tonic-gate 	int i;
378*7c478bd9Sstevel@tonic-gate 
379*7c478bd9Sstevel@tonic-gate 	/* check to see if any words are being debugged */
380*7c478bd9Sstevel@tonic-gate 	if (ndebug_acfs == 0)
381*7c478bd9Sstevel@tonic-gate 		return (0);
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate 	/* only words in dictionary can be debugged */
384*7c478bd9Sstevel@tonic-gate 	if (!within_dictionary(env, acf))
385*7c478bd9Sstevel@tonic-gate 		return (0);
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate 	/* check that word has "FLAG_DEBUG" on */
388*7c478bd9Sstevel@tonic-gate 	flagp = LINK_TO_FLAGS(ACF_TO_LINK(acf));
389*7c478bd9Sstevel@tonic-gate 	if ((*flagp & FLAG_DEBUG) == 0)
390*7c478bd9Sstevel@tonic-gate 		return (0);
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 	/* look in table of debug acf's */
393*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ndebug_acfs; i++)
394*7c478bd9Sstevel@tonic-gate 		if (debug_acfs[i] == acf)
395*7c478bd9Sstevel@tonic-gate 			return (1);
396*7c478bd9Sstevel@tonic-gate 	return (0);
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate #define	MAX_DEBUG_STACK	100
400*7c478bd9Sstevel@tonic-gate token_t debug_low[MAX_DEBUG_STACK], debug_high[MAX_DEBUG_STACK];
401*7c478bd9Sstevel@tonic-gate int debug_prev_level[MAX_DEBUG_STACK];
402*7c478bd9Sstevel@tonic-gate int debug_curr_level[MAX_DEBUG_STACK];
403*7c478bd9Sstevel@tonic-gate int ndebug_stack = 0;
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate void
406*7c478bd9Sstevel@tonic-gate debug_set_level(fcode_env_t *env, int level)
407*7c478bd9Sstevel@tonic-gate {
408*7c478bd9Sstevel@tonic-gate 	debug_curr_level[ndebug_stack - 1] = level;
409*7c478bd9Sstevel@tonic-gate 	set_interpreter_debug_level(level);
410*7c478bd9Sstevel@tonic-gate }
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate token_t
413*7c478bd9Sstevel@tonic-gate find_semi_in_colon_def(fcode_env_t *env, acf_t acf)
414*7c478bd9Sstevel@tonic-gate {
415*7c478bd9Sstevel@tonic-gate 	for (; within_dictionary(env, acf); acf++)
416*7c478bd9Sstevel@tonic-gate 		if (*acf == (token_t)(&semi_ptr))
417*7c478bd9Sstevel@tonic-gate 			return ((token_t)acf);
418*7c478bd9Sstevel@tonic-gate 	return (0);
419*7c478bd9Sstevel@tonic-gate }
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate void
422*7c478bd9Sstevel@tonic-gate check_for_debug_entry(fcode_env_t *env)
423*7c478bd9Sstevel@tonic-gate {
424*7c478bd9Sstevel@tonic-gate 	int top;
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	if (is_debug_word(env, WA) && ndebug_stack < MAX_DEBUG_STACK) {
427*7c478bd9Sstevel@tonic-gate 		top = ndebug_stack++;
428*7c478bd9Sstevel@tonic-gate 		debug_prev_level[top] = get_interpreter_debug_level();
429*7c478bd9Sstevel@tonic-gate 		debug_low[top] = (token_t)WA;
430*7c478bd9Sstevel@tonic-gate 		if (*WA == (token_t)(&do_colon)) {
431*7c478bd9Sstevel@tonic-gate 			debug_high[top] =
432*7c478bd9Sstevel@tonic-gate 			    find_semi_in_colon_def(env, WA);
433*7c478bd9Sstevel@tonic-gate 		} else {
434*7c478bd9Sstevel@tonic-gate 			debug_high[top] = 0;	/* marker... */
435*7c478bd9Sstevel@tonic-gate 		}
436*7c478bd9Sstevel@tonic-gate 		debug_set_level(env, DEBUG_STEPPING);
437*7c478bd9Sstevel@tonic-gate 		output_step_message(env);
438*7c478bd9Sstevel@tonic-gate 	}
439*7c478bd9Sstevel@tonic-gate }
440*7c478bd9Sstevel@tonic-gate 
441*7c478bd9Sstevel@tonic-gate void
442*7c478bd9Sstevel@tonic-gate check_for_debug_exit(fcode_env_t *env)
443*7c478bd9Sstevel@tonic-gate {
444*7c478bd9Sstevel@tonic-gate 	if (ndebug_stack) {
445*7c478bd9Sstevel@tonic-gate 		int top = ndebug_stack - 1;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 		if (debug_high[top] == 0) {
448*7c478bd9Sstevel@tonic-gate 			set_interpreter_debug_level(debug_prev_level[top]);
449*7c478bd9Sstevel@tonic-gate 			ndebug_stack--;
450*7c478bd9Sstevel@tonic-gate 		} else if ((token_t)IP >= debug_low[top] &&
451*7c478bd9Sstevel@tonic-gate 		    (token_t)IP <= debug_high[top]) {
452*7c478bd9Sstevel@tonic-gate 			set_interpreter_debug_level(debug_curr_level[top]);
453*7c478bd9Sstevel@tonic-gate 		} else {
454*7c478bd9Sstevel@tonic-gate 			set_interpreter_debug_level(debug_prev_level[top]);
455*7c478bd9Sstevel@tonic-gate 		}
456*7c478bd9Sstevel@tonic-gate 	}
457*7c478bd9Sstevel@tonic-gate }
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate void
460*7c478bd9Sstevel@tonic-gate check_semi_debug_exit(fcode_env_t *env)
461*7c478bd9Sstevel@tonic-gate {
462*7c478bd9Sstevel@tonic-gate 	if (ndebug_stack) {
463*7c478bd9Sstevel@tonic-gate 		int top = ndebug_stack - 1;
464*7c478bd9Sstevel@tonic-gate 
465*7c478bd9Sstevel@tonic-gate 		if ((token_t)(IP - 1) == debug_high[top]) {
466*7c478bd9Sstevel@tonic-gate 			set_interpreter_debug_level(debug_prev_level[top]);
467*7c478bd9Sstevel@tonic-gate 			ndebug_stack--;
468*7c478bd9Sstevel@tonic-gate 		}
469*7c478bd9Sstevel@tonic-gate 	}
470*7c478bd9Sstevel@tonic-gate }
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate /*
473*7c478bd9Sstevel@tonic-gate  * Really entering do_run, since this may be a recursive entry to do_run,
474*7c478bd9Sstevel@tonic-gate  * we need to set the debug level to what it was previously.
475*7c478bd9Sstevel@tonic-gate  */
476*7c478bd9Sstevel@tonic-gate int
477*7c478bd9Sstevel@tonic-gate current_debug_state(fcode_env_t *env)
478*7c478bd9Sstevel@tonic-gate {
479*7c478bd9Sstevel@tonic-gate 	if (ndebug_stack) {
480*7c478bd9Sstevel@tonic-gate 		int top = ndebug_stack - 1;
481*7c478bd9Sstevel@tonic-gate 		set_interpreter_debug_level(debug_prev_level[top]);
482*7c478bd9Sstevel@tonic-gate 	}
483*7c478bd9Sstevel@tonic-gate 	return (ndebug_stack);
484*7c478bd9Sstevel@tonic-gate }
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate void
487*7c478bd9Sstevel@tonic-gate clear_debug_state(fcode_env_t *env, int oldstate)
488*7c478bd9Sstevel@tonic-gate {
489*7c478bd9Sstevel@tonic-gate 	if (ndebug_stack && oldstate <= ndebug_stack) {
490*7c478bd9Sstevel@tonic-gate 		set_interpreter_debug_level(debug_prev_level[oldstate]);
491*7c478bd9Sstevel@tonic-gate 		ndebug_stack = oldstate;
492*7c478bd9Sstevel@tonic-gate 	}
493*7c478bd9Sstevel@tonic-gate }
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate void
496*7c478bd9Sstevel@tonic-gate unbug(fcode_env_t *env)
497*7c478bd9Sstevel@tonic-gate {
498*7c478bd9Sstevel@tonic-gate 	int i;
499*7c478bd9Sstevel@tonic-gate 	token_t *link;
500*7c478bd9Sstevel@tonic-gate 	flag_t *flag;
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 	for (i = ndebug_stack - 1; i >= 0; i--) {
503*7c478bd9Sstevel@tonic-gate 		link = ACF_TO_LINK(debug_low[i]);
504*7c478bd9Sstevel@tonic-gate 		flag = LINK_TO_FLAGS(link);
505*7c478bd9Sstevel@tonic-gate 		*flag &= ~FLAG_DEBUG;
506*7c478bd9Sstevel@tonic-gate 	}
507*7c478bd9Sstevel@tonic-gate 	clear_debug_state(env, 0);
508*7c478bd9Sstevel@tonic-gate }
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate void
511*7c478bd9Sstevel@tonic-gate output_vitals(fcode_env_t *env)
512*7c478bd9Sstevel@tonic-gate {
513*7c478bd9Sstevel@tonic-gate 	log_message(MSG_FC_DEBUG, "IP=%p, *IP=%p, WA=%p, *WA=%p ", IP,
514*7c478bd9Sstevel@tonic-gate 	    (IP ? *IP : 0), WA, (WA ? *WA : 0));
515*7c478bd9Sstevel@tonic-gate }
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate int
518*7c478bd9Sstevel@tonic-gate do_exec_debug(fcode_env_t *env, void *fn)
519*7c478bd9Sstevel@tonic-gate {
520*7c478bd9Sstevel@tonic-gate 	int dl = debug_level;
521*7c478bd9Sstevel@tonic-gate 	int show_wa = 1;
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	if ((dl & (DEBUG_EXEC_DUMP_DS | DEBUG_EXEC_DUMP_RS |
524*7c478bd9Sstevel@tonic-gate 	    DEBUG_EXEC_SHOW_VITALS | DEBUG_EXEC_TRACE | DEBUG_TRACING |
525*7c478bd9Sstevel@tonic-gate 	    DEBUG_STEPPING)) == 0)
526*7c478bd9Sstevel@tonic-gate 		return (0);
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate 	if (dl & DEBUG_STEPPING) {
529*7c478bd9Sstevel@tonic-gate 		dl |= DEBUG_EXEC_DUMP_DS;
530*7c478bd9Sstevel@tonic-gate 	}
531*7c478bd9Sstevel@tonic-gate 	if (dl & (DEBUG_STEPPING | DEBUG_EXEC_TRACE)) {
532*7c478bd9Sstevel@tonic-gate 		log_message(MSG_FC_DEBUG, "%-15s ", acf_to_name(env, WA));
533*7c478bd9Sstevel@tonic-gate 		show_wa = 0;
534*7c478bd9Sstevel@tonic-gate 	}
535*7c478bd9Sstevel@tonic-gate 	if (dl & DEBUG_EXEC_DUMP_DS)
536*7c478bd9Sstevel@tonic-gate 		output_data_stack(env, MSG_FC_DEBUG);
537*7c478bd9Sstevel@tonic-gate 	if (dl & DEBUG_EXEC_DUMP_RS)
538*7c478bd9Sstevel@tonic-gate 		output_return_stack(env, show_wa, MSG_FC_DEBUG);
539*7c478bd9Sstevel@tonic-gate 	if (dl & DEBUG_EXEC_SHOW_VITALS)
540*7c478bd9Sstevel@tonic-gate 		output_vitals(env);
541*7c478bd9Sstevel@tonic-gate 	if (dl & DEBUG_TRACING)
542*7c478bd9Sstevel@tonic-gate 		do_fclib_trace(env, (void *) fn);
543*7c478bd9Sstevel@tonic-gate 	log_message(MSG_FC_DEBUG, "\n");
544*7c478bd9Sstevel@tonic-gate 	if (dl & DEBUG_STEPPING)
545*7c478bd9Sstevel@tonic-gate 		return (do_fclib_step(env));
546*7c478bd9Sstevel@tonic-gate 	return (0);
547*7c478bd9Sstevel@tonic-gate }
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate static void
550*7c478bd9Sstevel@tonic-gate smatch(fcode_env_t *env)
551*7c478bd9Sstevel@tonic-gate {
552*7c478bd9Sstevel@tonic-gate 	int len;
553*7c478bd9Sstevel@tonic-gate 	char *str, *p;
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate 	if ((str = parse_a_string(env, &len)) == NULL)
556*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "smatch: no string\n");
557*7c478bd9Sstevel@tonic-gate 	else {
558*7c478bd9Sstevel@tonic-gate 		for (p = (char *)env->base; p < (char *)HERE; p++)
559*7c478bd9Sstevel@tonic-gate 			if (memcmp(p, str, len) == 0)
560*7c478bd9Sstevel@tonic-gate 				log_message(MSG_DEBUG, "%p\n", p);
561*7c478bd9Sstevel@tonic-gate 	}
562*7c478bd9Sstevel@tonic-gate }
563*7c478bd9Sstevel@tonic-gate 
564*7c478bd9Sstevel@tonic-gate void
565*7c478bd9Sstevel@tonic-gate check_vitals(fcode_env_t *env)
566*7c478bd9Sstevel@tonic-gate {
567*7c478bd9Sstevel@tonic-gate 	int i;
568*7c478bd9Sstevel@tonic-gate 	token_t *dptr;
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate 	dptr = env->current;
571*7c478bd9Sstevel@tonic-gate 	if (*dptr && !within_dictionary(env, (uchar_t *)*dptr))
572*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "Current: %p outside dictionary\n",
573*7c478bd9Sstevel@tonic-gate 		    *dptr);
574*7c478bd9Sstevel@tonic-gate 	for (i = env->order_depth; i >= 0; i--) {
575*7c478bd9Sstevel@tonic-gate 		dptr = env->order[i];
576*7c478bd9Sstevel@tonic-gate 		if (!dptr)
577*7c478bd9Sstevel@tonic-gate 			continue;
578*7c478bd9Sstevel@tonic-gate 		if (*dptr && !within_dictionary(env, (uchar_t *)*dptr))
579*7c478bd9Sstevel@tonic-gate 			log_message(MSG_ERROR, "Order%d: %p outside"
580*7c478bd9Sstevel@tonic-gate 			    " dictionary\n", i, *dptr);
581*7c478bd9Sstevel@tonic-gate 	}
582*7c478bd9Sstevel@tonic-gate 	if (HERE < env->base || HERE >= env->base + dict_size) {
583*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "HERE: %p outside range\n", HERE);
584*7c478bd9Sstevel@tonic-gate 	}
585*7c478bd9Sstevel@tonic-gate 	if (DS < env->ds0 || DS >= &env->ds0[stack_size]) {
586*7c478bd9Sstevel@tonic-gate 		forth_abort(env, "DS: %p outside range\n", DS);
587*7c478bd9Sstevel@tonic-gate 	}
588*7c478bd9Sstevel@tonic-gate 	if (RS < env->rs0 || RS >= &env->rs0[stack_size]) {
589*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "RS: %p outside range\n", RS);
590*7c478bd9Sstevel@tonic-gate 		RS = env->rs0;
591*7c478bd9Sstevel@tonic-gate 	}
592*7c478bd9Sstevel@tonic-gate 	if (IP && !within_dictionary(env, IP))
593*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "IP: %p outside dictionary\n", IP);
594*7c478bd9Sstevel@tonic-gate 	if (!within_dictionary(env, (void *)env->forth_voc_link))
595*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "forth_voc_link: %p outside"
596*7c478bd9Sstevel@tonic-gate 		    " dictionary\n", env->forth_voc_link);
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate static void
600*7c478bd9Sstevel@tonic-gate dump_table(fcode_env_t *env)
601*7c478bd9Sstevel@tonic-gate {
602*7c478bd9Sstevel@tonic-gate 	int i;
603*7c478bd9Sstevel@tonic-gate 
604*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAX_FCODE; i++) {
605*7c478bd9Sstevel@tonic-gate 		if (*(env->table[i].apf) != (token_t)(&f_error)) {
606*7c478bd9Sstevel@tonic-gate 			log_message(MSG_DEBUG, "Token: %4x %32s acf = %8p,"
607*7c478bd9Sstevel@tonic-gate 			    " %8p\n", i, env->table[i].name, env->table[i].apf,
608*7c478bd9Sstevel@tonic-gate 			    *(env->table[i].apf));
609*7c478bd9Sstevel@tonic-gate 		}
610*7c478bd9Sstevel@tonic-gate 	}
611*7c478bd9Sstevel@tonic-gate 	log_message(MSG_DEBUG, "%d FCODES implemented\n", fcode_impl_count);
612*7c478bd9Sstevel@tonic-gate }
613*7c478bd9Sstevel@tonic-gate 
614*7c478bd9Sstevel@tonic-gate void
615*7c478bd9Sstevel@tonic-gate verify_usage(fcode_env_t *env)
616*7c478bd9Sstevel@tonic-gate {
617*7c478bd9Sstevel@tonic-gate 	int i, untested = 0;
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAX_FCODE; i++) {
620*7c478bd9Sstevel@tonic-gate 		int verify;
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate 		verify = env->table[i].flags & (ANSI_WORD|P1275_WORD);
623*7c478bd9Sstevel@tonic-gate 		if ((verify) &&
624*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
625*7c478bd9Sstevel@tonic-gate 			(env->table[i].usage == 0) &&
626*7c478bd9Sstevel@tonic-gate #endif
627*7c478bd9Sstevel@tonic-gate 			(env->table[i].apf)) {
628*7c478bd9Sstevel@tonic-gate 			log_message(MSG_DEBUG,
629*7c478bd9Sstevel@tonic-gate 			    "Untested: %4x %32s acf = %8p, %8p\n", i,
630*7c478bd9Sstevel@tonic-gate 			    env->table[i].name, env->table[i].apf,
631*7c478bd9Sstevel@tonic-gate 			    *(env->table[i].apf));
632*7c478bd9Sstevel@tonic-gate 			untested++;
633*7c478bd9Sstevel@tonic-gate 		}
634*7c478bd9Sstevel@tonic-gate 	}
635*7c478bd9Sstevel@tonic-gate 	if (untested)
636*7c478bd9Sstevel@tonic-gate 		log_message(MSG_DEBUG, "%d untested tokens\n", untested);
637*7c478bd9Sstevel@tonic-gate }
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate static void
640*7c478bd9Sstevel@tonic-gate debugf(fcode_env_t *env)
641*7c478bd9Sstevel@tonic-gate {
642*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)&debug_level);
643*7c478bd9Sstevel@tonic-gate }
644*7c478bd9Sstevel@tonic-gate 
645*7c478bd9Sstevel@tonic-gate static void
646*7c478bd9Sstevel@tonic-gate control(fcode_env_t *env)
647*7c478bd9Sstevel@tonic-gate {
648*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)&env->control);
649*7c478bd9Sstevel@tonic-gate }
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate struct bittab {
652*7c478bd9Sstevel@tonic-gate 	int b_bitval;
653*7c478bd9Sstevel@tonic-gate 	char *b_bitname;
654*7c478bd9Sstevel@tonic-gate } bittab[] = {
655*7c478bd9Sstevel@tonic-gate 	DEBUG_CONTEXT,		"context",
656*7c478bd9Sstevel@tonic-gate 	DEBUG_BYTELOAD_DS,	"byteload-ds",
657*7c478bd9Sstevel@tonic-gate 	DEBUG_BYTELOAD_RS,	"byteload-rs",
658*7c478bd9Sstevel@tonic-gate 	DEBUG_BYTELOAD_TOKENS,	"byteload-tokens",
659*7c478bd9Sstevel@tonic-gate 	DEBUG_NEW_TOKEN,	"new-token",
660*7c478bd9Sstevel@tonic-gate 	DEBUG_EXEC_TRACE,	"exec-trace",
661*7c478bd9Sstevel@tonic-gate 	DEBUG_EXEC_SHOW_VITALS,	"exec-show-vitals",
662*7c478bd9Sstevel@tonic-gate 	DEBUG_EXEC_DUMP_DS,	"exec-dump-ds",
663*7c478bd9Sstevel@tonic-gate 	DEBUG_EXEC_DUMP_RS,	"exec-dump-rs",
664*7c478bd9Sstevel@tonic-gate 	DEBUG_COMMA,		"comma",
665*7c478bd9Sstevel@tonic-gate 	DEBUG_HEADER,		"header",
666*7c478bd9Sstevel@tonic-gate 	DEBUG_EXIT_WORDS,	"exit-words",
667*7c478bd9Sstevel@tonic-gate 	DEBUG_EXIT_DUMP,	"exit-dump",
668*7c478bd9Sstevel@tonic-gate 	DEBUG_DUMP_TOKENS,	"dump-tokens",
669*7c478bd9Sstevel@tonic-gate 	DEBUG_COLON,		"colon",
670*7c478bd9Sstevel@tonic-gate 	DEBUG_NEXT_VITALS,	"next-vitals",
671*7c478bd9Sstevel@tonic-gate 	DEBUG_VOC_FIND,		"voc-find",
672*7c478bd9Sstevel@tonic-gate 	DEBUG_DUMP_DICT_TOKENS,	"dump-dict-tokens",
673*7c478bd9Sstevel@tonic-gate 	DEBUG_TOKEN_USAGE,	"token-usage",
674*7c478bd9Sstevel@tonic-gate 	DEBUG_DUMP_TOKEN_TABLE,	"dump-token-table",
675*7c478bd9Sstevel@tonic-gate 	DEBUG_SHOW_STACK,	"show-stack",
676*7c478bd9Sstevel@tonic-gate 	DEBUG_SHOW_RS,		"show-rs",
677*7c478bd9Sstevel@tonic-gate 	DEBUG_TRACING,		"tracing",
678*7c478bd9Sstevel@tonic-gate 	DEBUG_TRACE_STACK,	"trace-stack",
679*7c478bd9Sstevel@tonic-gate 	DEBUG_CALL_METHOD,	"call-method",
680*7c478bd9Sstevel@tonic-gate 	DEBUG_ACTIONS,		"actions",
681*7c478bd9Sstevel@tonic-gate 	DEBUG_STEPPING,		"stepping",
682*7c478bd9Sstevel@tonic-gate 	DEBUG_REG_ACCESS,	"reg-access",
683*7c478bd9Sstevel@tonic-gate 	DEBUG_ADDR_ABUSE,	"addr-abuse",
684*7c478bd9Sstevel@tonic-gate 	DEBUG_FIND_FCODE,	"find-fcode",
685*7c478bd9Sstevel@tonic-gate 	DEBUG_UPLOAD,		"upload",
686*7c478bd9Sstevel@tonic-gate 	0
687*7c478bd9Sstevel@tonic-gate };
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate void
690*7c478bd9Sstevel@tonic-gate debug_flags_to_output(fcode_env_t *env, int flags)
691*7c478bd9Sstevel@tonic-gate {
692*7c478bd9Sstevel@tonic-gate 	int first = 1, i;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	for (i = 0; bittab[i].b_bitval != 0; i++)
695*7c478bd9Sstevel@tonic-gate 		if (bittab[i].b_bitval & flags) {
696*7c478bd9Sstevel@tonic-gate 			if (!first)
697*7c478bd9Sstevel@tonic-gate 				log_message(MSG_INFO, ",");
698*7c478bd9Sstevel@tonic-gate 			first = 0;
699*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, bittab[i].b_bitname);
700*7c478bd9Sstevel@tonic-gate 		}
701*7c478bd9Sstevel@tonic-gate 	if (first)
702*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "<empty>");
703*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "\n");
704*7c478bd9Sstevel@tonic-gate }
705*7c478bd9Sstevel@tonic-gate 
706*7c478bd9Sstevel@tonic-gate static void
707*7c478bd9Sstevel@tonic-gate dot_debugf(fcode_env_t *env)
708*7c478bd9Sstevel@tonic-gate {
709*7c478bd9Sstevel@tonic-gate 	debug_flags_to_output(env, debug_level);
710*7c478bd9Sstevel@tonic-gate }
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate static void
713*7c478bd9Sstevel@tonic-gate debugf_qmark(fcode_env_t *env)
714*7c478bd9Sstevel@tonic-gate {
715*7c478bd9Sstevel@tonic-gate 	debug_flags_to_output(env, 0xffffffff);
716*7c478bd9Sstevel@tonic-gate }
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate int
719*7c478bd9Sstevel@tonic-gate debug_flags_to_mask(char *str)
720*7c478bd9Sstevel@tonic-gate {
721*7c478bd9Sstevel@tonic-gate 	int flags = 0;
722*7c478bd9Sstevel@tonic-gate 	char *p;
723*7c478bd9Sstevel@tonic-gate 	int i;
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	if (isdigit(*str)) {
726*7c478bd9Sstevel@tonic-gate 		if (*str == '0') {
727*7c478bd9Sstevel@tonic-gate 			str++;
728*7c478bd9Sstevel@tonic-gate 			if (*str == 'x' || *str == 'X') {
729*7c478bd9Sstevel@tonic-gate 				sscanf(str + 1, "%x", &flags);
730*7c478bd9Sstevel@tonic-gate 			} else
731*7c478bd9Sstevel@tonic-gate 				sscanf(str, "%o", &flags);
732*7c478bd9Sstevel@tonic-gate 		} else
733*7c478bd9Sstevel@tonic-gate 			sscanf(str, "%d", &flags);
734*7c478bd9Sstevel@tonic-gate 		return (flags);
735*7c478bd9Sstevel@tonic-gate 	}
736*7c478bd9Sstevel@tonic-gate 	if (strcmp(str, "clear") == 0)
737*7c478bd9Sstevel@tonic-gate 		return (0);
738*7c478bd9Sstevel@tonic-gate 	if (strcmp(str, "all") == 0)
739*7c478bd9Sstevel@tonic-gate 		return (0xffffffff & ~DEBUG_STEPPING);
740*7c478bd9Sstevel@tonic-gate 	if (*str) {
741*7c478bd9Sstevel@tonic-gate 		do {
742*7c478bd9Sstevel@tonic-gate 			if (p = strchr(str, ','))
743*7c478bd9Sstevel@tonic-gate 				*p++ = '\0';
744*7c478bd9Sstevel@tonic-gate 			for (i = 0; bittab[i].b_bitname != 0; i++)
745*7c478bd9Sstevel@tonic-gate 				if (strcmp(str, bittab[i].b_bitname) == 0) {
746*7c478bd9Sstevel@tonic-gate 					flags |= bittab[i].b_bitval;
747*7c478bd9Sstevel@tonic-gate 					break;
748*7c478bd9Sstevel@tonic-gate 			}
749*7c478bd9Sstevel@tonic-gate 			if (bittab[i].b_bitname == 0)
750*7c478bd9Sstevel@tonic-gate 				log_message(MSG_WARN,
751*7c478bd9Sstevel@tonic-gate 				    "Unknown debug flag: '%s'\n", str);
752*7c478bd9Sstevel@tonic-gate 			str = p;
753*7c478bd9Sstevel@tonic-gate 		} while (p);
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 	return (flags);
756*7c478bd9Sstevel@tonic-gate }
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate static void
759*7c478bd9Sstevel@tonic-gate set_debugf(fcode_env_t *env)
760*7c478bd9Sstevel@tonic-gate {
761*7c478bd9Sstevel@tonic-gate 	char *str;
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 	str = parse_a_string(env, NULL);
764*7c478bd9Sstevel@tonic-gate 	debug_level = debug_flags_to_mask(str);
765*7c478bd9Sstevel@tonic-gate }
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate static acf_t
768*7c478bd9Sstevel@tonic-gate show_a_word(fcode_env_t *env, acf_t acf, void *arg)
769*7c478bd9Sstevel@tonic-gate {
770*7c478bd9Sstevel@tonic-gate 	static int nshow_words = 0;
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	if (acf == NULL) {
773*7c478bd9Sstevel@tonic-gate 		if (nshow_words > 0) {
774*7c478bd9Sstevel@tonic-gate 			log_message(MSG_DEBUG, "\n");
775*7c478bd9Sstevel@tonic-gate 			nshow_words = 0;
776*7c478bd9Sstevel@tonic-gate 		}
777*7c478bd9Sstevel@tonic-gate 		return (NULL);
778*7c478bd9Sstevel@tonic-gate 	}
779*7c478bd9Sstevel@tonic-gate 	log_message(MSG_DEBUG, "%15s  ", get_name_or_acf(ACF_TO_LINK(acf)));
780*7c478bd9Sstevel@tonic-gate 	nshow_words++;
781*7c478bd9Sstevel@tonic-gate 	if (nshow_words >= 4) {
782*7c478bd9Sstevel@tonic-gate 		log_message(MSG_DEBUG, "\n");
783*7c478bd9Sstevel@tonic-gate 		nshow_words = 0;
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 	return (NULL);
786*7c478bd9Sstevel@tonic-gate }
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate void
789*7c478bd9Sstevel@tonic-gate words(fcode_env_t *env)
790*7c478bd9Sstevel@tonic-gate {
791*7c478bd9Sstevel@tonic-gate 	(void) search_all_dictionaries(env, show_a_word, NULL);
792*7c478bd9Sstevel@tonic-gate 	(void) show_a_word(env, NULL, NULL);
793*7c478bd9Sstevel@tonic-gate }
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate static acf_t
796*7c478bd9Sstevel@tonic-gate dump_a_word(fcode_env_t *env, acf_t acf, void *arg)
797*7c478bd9Sstevel@tonic-gate {
798*7c478bd9Sstevel@tonic-gate 	output_acf_name(acf);
799*7c478bd9Sstevel@tonic-gate 	return (NULL);
800*7c478bd9Sstevel@tonic-gate }
801*7c478bd9Sstevel@tonic-gate 
802*7c478bd9Sstevel@tonic-gate void
803*7c478bd9Sstevel@tonic-gate dump_words(fcode_env_t *env)
804*7c478bd9Sstevel@tonic-gate {
805*7c478bd9Sstevel@tonic-gate 	(void) search_all_dictionaries(env, dump_a_word, NULL);
806*7c478bd9Sstevel@tonic-gate 	output_acf_name(NULL);
807*7c478bd9Sstevel@tonic-gate }
808*7c478bd9Sstevel@tonic-gate 
809*7c478bd9Sstevel@tonic-gate static void
810*7c478bd9Sstevel@tonic-gate dump_line(uchar_t *ptr)
811*7c478bd9Sstevel@tonic-gate {
812*7c478bd9Sstevel@tonic-gate 	uchar_t *byte;
813*7c478bd9Sstevel@tonic-gate 	int i;
814*7c478bd9Sstevel@tonic-gate 
815*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "%p  ", (uint32_t)ptr);
816*7c478bd9Sstevel@tonic-gate 	for (i = 0, byte = ptr; i < 16; i++) {
817*7c478bd9Sstevel@tonic-gate 		if (i == 8)
818*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, " ");
819*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "%02.2x ", *byte++);
820*7c478bd9Sstevel@tonic-gate 	}
821*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, " ");
822*7c478bd9Sstevel@tonic-gate 	for (i = 0, byte = ptr; i < 16; i++, byte++) {
823*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "%c",
824*7c478bd9Sstevel@tonic-gate 		    ((*byte < 0x20) || (*byte > 0x7f)) ? '.' : *byte);
825*7c478bd9Sstevel@tonic-gate 	}
826*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "\n");
827*7c478bd9Sstevel@tonic-gate }
828*7c478bd9Sstevel@tonic-gate 
829*7c478bd9Sstevel@tonic-gate void
830*7c478bd9Sstevel@tonic-gate dump_dictionary(fcode_env_t *env)
831*7c478bd9Sstevel@tonic-gate {
832*7c478bd9Sstevel@tonic-gate 	uchar_t *ptr;
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "Dictionary dump: base: %p\n", env->base);
835*7c478bd9Sstevel@tonic-gate 	for (ptr = (uchar_t *)(((long)(env->base)) & ~0xf); ptr < HERE;
836*7c478bd9Sstevel@tonic-gate 	    ptr += 16)
837*7c478bd9Sstevel@tonic-gate 		dump_line(ptr);
838*7c478bd9Sstevel@tonic-gate }
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate static char *
841*7c478bd9Sstevel@tonic-gate acf_to_fcode_name(fcode_env_t *env, acf_t acf)
842*7c478bd9Sstevel@tonic-gate {
843*7c478bd9Sstevel@tonic-gate 	int i;
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAX_FCODE; i++)
846*7c478bd9Sstevel@tonic-gate 		if (env->table[i].apf == acf)
847*7c478bd9Sstevel@tonic-gate 			return (env->table[i].name);
848*7c478bd9Sstevel@tonic-gate 	return (NULL);
849*7c478bd9Sstevel@tonic-gate }
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate static acf_t
852*7c478bd9Sstevel@tonic-gate acf_match(fcode_env_t *env, acf_t sacf, void *macf)
853*7c478bd9Sstevel@tonic-gate {
854*7c478bd9Sstevel@tonic-gate 	if (sacf == (acf_t)macf)
855*7c478bd9Sstevel@tonic-gate 		return (sacf);
856*7c478bd9Sstevel@tonic-gate 	return (NULL);
857*7c478bd9Sstevel@tonic-gate }
858*7c478bd9Sstevel@tonic-gate 
859*7c478bd9Sstevel@tonic-gate /*
860*7c478bd9Sstevel@tonic-gate  * Given an ACF, return ptr to name or "unknown" string.
861*7c478bd9Sstevel@tonic-gate  */
862*7c478bd9Sstevel@tonic-gate char *
863*7c478bd9Sstevel@tonic-gate acf_to_name(fcode_env_t *env, acf_t acf)
864*7c478bd9Sstevel@tonic-gate {
865*7c478bd9Sstevel@tonic-gate 	struct bitab *bip;
866*7c478bd9Sstevel@tonic-gate 	static char name_buf[256];
867*7c478bd9Sstevel@tonic-gate 	uchar_t *p, *np;
868*7c478bd9Sstevel@tonic-gate 	int i, n;
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	if (!within_dictionary(env, acf)) {
871*7c478bd9Sstevel@tonic-gate 		if ((bip = lookup_builtin((token_t)acf)) != NULL)
872*7c478bd9Sstevel@tonic-gate 			return (bip->bi_name);
873*7c478bd9Sstevel@tonic-gate 		return (NULL);
874*7c478bd9Sstevel@tonic-gate 	}
875*7c478bd9Sstevel@tonic-gate 	return (get_name_or_acf(ACF_TO_LINK(acf)));
876*7c478bd9Sstevel@tonic-gate }
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate int
879*7c478bd9Sstevel@tonic-gate within_dictionary(fcode_env_t *env, void *addr)
880*7c478bd9Sstevel@tonic-gate {
881*7c478bd9Sstevel@tonic-gate 	return ((uchar_t *)addr >= env->base &&
882*7c478bd9Sstevel@tonic-gate 	    (uchar_t *)addr < env->base + dict_size);
883*7c478bd9Sstevel@tonic-gate }
884*7c478bd9Sstevel@tonic-gate 
885*7c478bd9Sstevel@tonic-gate static int
886*7c478bd9Sstevel@tonic-gate within_word(fcode_env_t *env, acf_t acf, acf_t wacf)
887*7c478bd9Sstevel@tonic-gate {
888*7c478bd9Sstevel@tonic-gate 	if (acf == wacf || acf + 1 == wacf)
889*7c478bd9Sstevel@tonic-gate 		return (1);
890*7c478bd9Sstevel@tonic-gate 	if (*acf == (token_t)(&do_colon)) {
891*7c478bd9Sstevel@tonic-gate 		do {
892*7c478bd9Sstevel@tonic-gate 			if (acf == wacf)
893*7c478bd9Sstevel@tonic-gate 				return (1);
894*7c478bd9Sstevel@tonic-gate 		} while (*acf++ != (token_t)(&semi_ptr));
895*7c478bd9Sstevel@tonic-gate 	}
896*7c478bd9Sstevel@tonic-gate 	return (0);
897*7c478bd9Sstevel@tonic-gate }
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate /*
900*7c478bd9Sstevel@tonic-gate  * Given an ACF in the middle of a colon definition, search dictionary towards
901*7c478bd9Sstevel@tonic-gate  * beginning for "colon" acf.  If we find a "semi" acf first, we're not in
902*7c478bd9Sstevel@tonic-gate  * the middle of a colon-def (temporary execute?).
903*7c478bd9Sstevel@tonic-gate  */
904*7c478bd9Sstevel@tonic-gate char *
905*7c478bd9Sstevel@tonic-gate acf_backup_search(fcode_env_t *env, acf_t acf)
906*7c478bd9Sstevel@tonic-gate {
907*7c478bd9Sstevel@tonic-gate 	acf_t nacf;
908*7c478bd9Sstevel@tonic-gate 	char *name;
909*7c478bd9Sstevel@tonic-gate 
910*7c478bd9Sstevel@tonic-gate 	if ((acf_t)_ALIGN(acf, token_t) == acf && within_dictionary(env, acf)) {
911*7c478bd9Sstevel@tonic-gate 		for (nacf = acf; nacf >= (acf_t)env->base; nacf--)
912*7c478bd9Sstevel@tonic-gate 			if (*nacf == (token_t)(&do_colon) ||
913*7c478bd9Sstevel@tonic-gate 			    *nacf == (token_t)(&semi_ptr))
914*7c478bd9Sstevel@tonic-gate 				break;
915*7c478bd9Sstevel@tonic-gate 		if (nacf >= (acf_t)env->base && *nacf == (token_t)(&do_colon) &&
916*7c478bd9Sstevel@tonic-gate 		    (name = get_name(ACF_TO_LINK(nacf))) != NULL)
917*7c478bd9Sstevel@tonic-gate 			return (name);
918*7c478bd9Sstevel@tonic-gate 	}
919*7c478bd9Sstevel@tonic-gate 	return (acf_to_str(acf));
920*7c478bd9Sstevel@tonic-gate }
921*7c478bd9Sstevel@tonic-gate 
922*7c478bd9Sstevel@tonic-gate /*
923*7c478bd9Sstevel@tonic-gate  * Print out current process's C stack using /usr/proc/bin/pstack
924*7c478bd9Sstevel@tonic-gate  */
925*7c478bd9Sstevel@tonic-gate void
926*7c478bd9Sstevel@tonic-gate ctrace(fcode_env_t *env)
927*7c478bd9Sstevel@tonic-gate {
928*7c478bd9Sstevel@tonic-gate 	char buf[256];
929*7c478bd9Sstevel@tonic-gate 	FILE *fd;
930*7c478bd9Sstevel@tonic-gate 
931*7c478bd9Sstevel@tonic-gate 	log_message(MSG_DEBUG, "Interpreter C Stack:\n");
932*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "/usr/proc/bin/pstack %d", getpid());
933*7c478bd9Sstevel@tonic-gate 	if ((fd = popen(buf, "r")) == NULL)
934*7c478bd9Sstevel@tonic-gate 		log_perror(MSG_ERROR, "Can't run: %s", buf);
935*7c478bd9Sstevel@tonic-gate 	else {
936*7c478bd9Sstevel@tonic-gate 		while (fgets(buf, sizeof (buf), fd))
937*7c478bd9Sstevel@tonic-gate 			log_message(MSG_DEBUG, buf);
938*7c478bd9Sstevel@tonic-gate 		fclose(fd);
939*7c478bd9Sstevel@tonic-gate 	}
940*7c478bd9Sstevel@tonic-gate }
941*7c478bd9Sstevel@tonic-gate 
942*7c478bd9Sstevel@tonic-gate /*
943*7c478bd9Sstevel@tonic-gate  * Dump data, return stacks, try to unthread forth calling stack.
944*7c478bd9Sstevel@tonic-gate  */
945*7c478bd9Sstevel@tonic-gate void
946*7c478bd9Sstevel@tonic-gate ftrace(fcode_env_t *env)
947*7c478bd9Sstevel@tonic-gate {
948*7c478bd9Sstevel@tonic-gate 	log_message(MSG_DEBUG, "Forth Interpreter Stacks:\n");
949*7c478bd9Sstevel@tonic-gate 	output_data_stack(env, MSG_DEBUG);
950*7c478bd9Sstevel@tonic-gate 	output_return_stack(env, 1, MSG_DEBUG);
951*7c478bd9Sstevel@tonic-gate 	log_message(MSG_DEBUG, "\n");
952*7c478bd9Sstevel@tonic-gate }
953*7c478bd9Sstevel@tonic-gate 
954*7c478bd9Sstevel@tonic-gate int in_forth_abort;
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate /*
957*7c478bd9Sstevel@tonic-gate  * Handle fatal error, if interactive mode, return to ok prompt.
958*7c478bd9Sstevel@tonic-gate  */
959*7c478bd9Sstevel@tonic-gate void
960*7c478bd9Sstevel@tonic-gate forth_abort(fcode_env_t *env, char *fmt, ...)
961*7c478bd9Sstevel@tonic-gate {
962*7c478bd9Sstevel@tonic-gate 	va_list ap;
963*7c478bd9Sstevel@tonic-gate 	char msg[256];
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	if (in_forth_abort) {
966*7c478bd9Sstevel@tonic-gate 		log_message(MSG_FATAL, "ABORT: abort within forth_abort\n");
967*7c478bd9Sstevel@tonic-gate 		abort();
968*7c478bd9Sstevel@tonic-gate 	}
969*7c478bd9Sstevel@tonic-gate 	in_forth_abort++;
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
972*7c478bd9Sstevel@tonic-gate 	vsprintf(msg, fmt, ap);
973*7c478bd9Sstevel@tonic-gate 	log_message(MSG_ERROR, "ABORT: %s\n", msg);
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate 	if (env) {
976*7c478bd9Sstevel@tonic-gate 		ctrace(env);
977*7c478bd9Sstevel@tonic-gate 		ftrace(env);
978*7c478bd9Sstevel@tonic-gate 	}
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate 	return_to_interact(env);
981*7c478bd9Sstevel@tonic-gate 	/*
982*7c478bd9Sstevel@tonic-gate 	 * If not in interactive mode, return_to_interact just returns.
983*7c478bd9Sstevel@tonic-gate 	 */
984*7c478bd9Sstevel@tonic-gate 	exit(1);
985*7c478bd9Sstevel@tonic-gate }
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate /*
988*7c478bd9Sstevel@tonic-gate  * Handle fatal system call error
989*7c478bd9Sstevel@tonic-gate  */
990*7c478bd9Sstevel@tonic-gate void
991*7c478bd9Sstevel@tonic-gate forth_perror(fcode_env_t *env, char *fmt, ...)
992*7c478bd9Sstevel@tonic-gate {
993*7c478bd9Sstevel@tonic-gate 	va_list ap;
994*7c478bd9Sstevel@tonic-gate 	char msg[256];
995*7c478bd9Sstevel@tonic-gate 	int save_errno = errno;	/* just in case... */
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
998*7c478bd9Sstevel@tonic-gate 	vsprintf(msg, fmt, ap);
999*7c478bd9Sstevel@tonic-gate 
1000*7c478bd9Sstevel@tonic-gate 	forth_abort(env, "%s: %s", msg, strerror(save_errno));
1001*7c478bd9Sstevel@tonic-gate }
1002*7c478bd9Sstevel@tonic-gate 
1003*7c478bd9Sstevel@tonic-gate static void
1004*7c478bd9Sstevel@tonic-gate show_stack(fcode_env_t *env)
1005*7c478bd9Sstevel@tonic-gate {
1006*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
1007*7c478bd9Sstevel@tonic-gate 	debug_level ^= DEBUG_SHOW_STACK;
1008*7c478bd9Sstevel@tonic-gate #else
1009*7c478bd9Sstevel@tonic-gate 	/*EMPTY*/
1010*7c478bd9Sstevel@tonic-gate #endif
1011*7c478bd9Sstevel@tonic-gate }
1012*7c478bd9Sstevel@tonic-gate 
1013*7c478bd9Sstevel@tonic-gate static void
1014*7c478bd9Sstevel@tonic-gate print_bytes_header(int width, int offset)
1015*7c478bd9Sstevel@tonic-gate {
1016*7c478bd9Sstevel@tonic-gate 	int i;
1017*7c478bd9Sstevel@tonic-gate 
1018*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < width; i++)
1019*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, " ");
1020*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "  ");
1021*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 16; i++) {
1022*7c478bd9Sstevel@tonic-gate 		if (i == 8)
1023*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, " ");
1024*7c478bd9Sstevel@tonic-gate 		if (i == offset)
1025*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "\\/ ");
1026*7c478bd9Sstevel@tonic-gate 		else
1027*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%2x ", i);
1028*7c478bd9Sstevel@tonic-gate 	}
1029*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, " ");
1030*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 16; i++) {
1031*7c478bd9Sstevel@tonic-gate 		if (i == offset)
1032*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "v");
1033*7c478bd9Sstevel@tonic-gate 		else
1034*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%x", i);
1035*7c478bd9Sstevel@tonic-gate 	}
1036*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "\n");
1037*7c478bd9Sstevel@tonic-gate }
1038*7c478bd9Sstevel@tonic-gate 
1039*7c478bd9Sstevel@tonic-gate static void
1040*7c478bd9Sstevel@tonic-gate dump(fcode_env_t *env)
1041*7c478bd9Sstevel@tonic-gate {
1042*7c478bd9Sstevel@tonic-gate 	uchar_t *data;
1043*7c478bd9Sstevel@tonic-gate 	int len, offset;
1044*7c478bd9Sstevel@tonic-gate 	char buf[20];
1045*7c478bd9Sstevel@tonic-gate 
1046*7c478bd9Sstevel@tonic-gate 	len = POP(DS);
1047*7c478bd9Sstevel@tonic-gate 	data = (uchar_t *)POP(DS);
1048*7c478bd9Sstevel@tonic-gate 	offset = ((long)data) & 0xf;
1049*7c478bd9Sstevel@tonic-gate 	len += offset;
1050*7c478bd9Sstevel@tonic-gate 	data = (uchar_t *)((long)data & ~0xf);
1051*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "%p", (uint32_t)data);
1052*7c478bd9Sstevel@tonic-gate 	print_bytes_header(strlen(buf), offset);
1053*7c478bd9Sstevel@tonic-gate 	for (len += offset; len > 0; len -= 16, data += 16)
1054*7c478bd9Sstevel@tonic-gate 		dump_line(data);
1055*7c478bd9Sstevel@tonic-gate }
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate static acf_t
1058*7c478bd9Sstevel@tonic-gate do_sifting(fcode_env_t *env, acf_t acf, void *pat)
1059*7c478bd9Sstevel@tonic-gate {
1060*7c478bd9Sstevel@tonic-gate 	char *name;
1061*7c478bd9Sstevel@tonic-gate 
1062*7c478bd9Sstevel@tonic-gate 	if ((name = get_name(ACF_TO_LINK(acf))) != NULL && strstr(name, pat))
1063*7c478bd9Sstevel@tonic-gate 		output_acf_name(acf);
1064*7c478bd9Sstevel@tonic-gate 	return (NULL);
1065*7c478bd9Sstevel@tonic-gate }
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate static void
1068*7c478bd9Sstevel@tonic-gate sifting(fcode_env_t *env)
1069*7c478bd9Sstevel@tonic-gate {
1070*7c478bd9Sstevel@tonic-gate 	char *pat;
1071*7c478bd9Sstevel@tonic-gate 
1072*7c478bd9Sstevel@tonic-gate 	if ((pat = parse_a_string(env, NULL)) != NULL) {
1073*7c478bd9Sstevel@tonic-gate 		(void) search_all_dictionaries(env, do_sifting, pat);
1074*7c478bd9Sstevel@tonic-gate 		output_acf_name(NULL);
1075*7c478bd9Sstevel@tonic-gate 	}
1076*7c478bd9Sstevel@tonic-gate }
1077*7c478bd9Sstevel@tonic-gate 
1078*7c478bd9Sstevel@tonic-gate void
1079*7c478bd9Sstevel@tonic-gate print_level(int level, int *doprint)
1080*7c478bd9Sstevel@tonic-gate {
1081*7c478bd9Sstevel@tonic-gate 	int i;
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate 	if (*doprint) {
1084*7c478bd9Sstevel@tonic-gate 		log_message(MSG_DEBUG, "\n    ");
1085*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < level; i++)
1086*7c478bd9Sstevel@tonic-gate 			log_message(MSG_DEBUG, "    ");
1087*7c478bd9Sstevel@tonic-gate 		*doprint = 0;
1088*7c478bd9Sstevel@tonic-gate 	}
1089*7c478bd9Sstevel@tonic-gate }
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate #define	BI_QUOTE	1
1092*7c478bd9Sstevel@tonic-gate #define	BI_BLIT		2
1093*7c478bd9Sstevel@tonic-gate #define	BI_BDO		3
1094*7c478bd9Sstevel@tonic-gate #define	BI_QDO		4
1095*7c478bd9Sstevel@tonic-gate #define	BI_BR		5
1096*7c478bd9Sstevel@tonic-gate #define	BI_QBR		6
1097*7c478bd9Sstevel@tonic-gate #define	BI_BOF		7
1098*7c478bd9Sstevel@tonic-gate #define	BI_LOOP		8
1099*7c478bd9Sstevel@tonic-gate #define	BI_PLOOP	9
1100*7c478bd9Sstevel@tonic-gate #define	BI_TO		10
1101*7c478bd9Sstevel@tonic-gate #define	BI_SEMI		11
1102*7c478bd9Sstevel@tonic-gate #define	BI_COLON	12
1103*7c478bd9Sstevel@tonic-gate #define	BI_NOOP		13
1104*7c478bd9Sstevel@tonic-gate #define	BI_NOTYET	14	/* unimplented in "see" */
1105*7c478bd9Sstevel@tonic-gate 
1106*7c478bd9Sstevel@tonic-gate struct bitab bitab[] = {
1107*7c478bd9Sstevel@tonic-gate 	(token_t)(&quote_ptr),			"\"",		BI_QUOTE,
1108*7c478bd9Sstevel@tonic-gate 	(token_t)(&blit_ptr),			"blit",		BI_BLIT,
1109*7c478bd9Sstevel@tonic-gate 	(token_t)(&do_bdo_ptr),			"do",		BI_BDO,
1110*7c478bd9Sstevel@tonic-gate 	(token_t)(&do_bqdo_ptr),		"?do",		BI_QDO,
1111*7c478bd9Sstevel@tonic-gate 	(token_t)(&bbranch_ptrs[0]),		"br",		BI_BR,
1112*7c478bd9Sstevel@tonic-gate 	(token_t)(&bbranch_ptrs[1]),		"qbr",		BI_QBR,
1113*7c478bd9Sstevel@tonic-gate 	(token_t)(&bbranch_ptrs[2]),		"bof",		BI_BOF,
1114*7c478bd9Sstevel@tonic-gate 	(token_t)(&do_loop_ptr),		"loop",		BI_LOOP,
1115*7c478bd9Sstevel@tonic-gate 	(token_t)(&do_ploop_ptr),		"+loop",	BI_PLOOP,
1116*7c478bd9Sstevel@tonic-gate 	(token_t)(&to_ptr),			"to",		BI_NOOP,
1117*7c478bd9Sstevel@tonic-gate 	(token_t)(&semi_ptr),			";",		BI_SEMI,
1118*7c478bd9Sstevel@tonic-gate 	(token_t)(&do_colon),			":",		BI_COLON,
1119*7c478bd9Sstevel@tonic-gate 	(token_t)(&tlit_ptr),			"[']",		BI_NOOP,
1120*7c478bd9Sstevel@tonic-gate 	(token_t)(&do_leave_ptr),		"leave",	BI_NOTYET,
1121*7c478bd9Sstevel@tonic-gate 	(token_t)(&create_ptr),			"create",	BI_NOTYET,
1122*7c478bd9Sstevel@tonic-gate 	(token_t)(&does_ptr),			"does>",	BI_NOTYET,
1123*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[0][0]),	"a.@",		BI_NOTYET,
1124*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[0][1]),	"a.!",		BI_NOTYET,
1125*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[0][2]),	"a.nop",	BI_NOTYET,
1126*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[1][0]),	"a.i@",		BI_NOTYET,
1127*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[1][1]),	"a.i!",		BI_NOTYET,
1128*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[1][2]),	"a.iad",	BI_NOTYET,
1129*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[2][0]),	"a.defer",	BI_NOTYET,
1130*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[2][1]),	"a.@",		BI_NOTYET,
1131*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[2][2]),	"a.nop",	BI_NOTYET,
1132*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[3][0]),	"a.defexec",	BI_NOTYET,
1133*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[3][1]),	"a.iset",	BI_NOTYET,
1134*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[3][2]),	"a.iad",	BI_NOTYET,
1135*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[4][0]),	"a.binit",	BI_NOTYET,
1136*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[4][1]),	"a.2drop",	BI_NOTYET,
1137*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[4][2]),	"a.nop",	BI_NOTYET,
1138*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[5][0]),	"a.ibinit",	BI_NOTYET,
1139*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[5][1]),	"a.2drop",	BI_NOTYET,
1140*7c478bd9Sstevel@tonic-gate 	(token_t)(&value_defines[5][2]),	"a.iad",	BI_NOTYET,
1141*7c478bd9Sstevel@tonic-gate 	0
1142*7c478bd9Sstevel@tonic-gate };
1143*7c478bd9Sstevel@tonic-gate 
1144*7c478bd9Sstevel@tonic-gate struct bitab *
1145*7c478bd9Sstevel@tonic-gate lookup_builtin(token_t builtin)
1146*7c478bd9Sstevel@tonic-gate {
1147*7c478bd9Sstevel@tonic-gate 	int i;
1148*7c478bd9Sstevel@tonic-gate 
1149*7c478bd9Sstevel@tonic-gate 	for (i = 0; bitab[i].bi_ptr; i++)
1150*7c478bd9Sstevel@tonic-gate 		if (bitab[i].bi_ptr == builtin)
1151*7c478bd9Sstevel@tonic-gate 			return (&bitab[i]);
1152*7c478bd9Sstevel@tonic-gate 	return (NULL);
1153*7c478bd9Sstevel@tonic-gate }
1154*7c478bd9Sstevel@tonic-gate 
1155*7c478bd9Sstevel@tonic-gate static void
1156*7c478bd9Sstevel@tonic-gate paren_see(fcode_env_t *env)
1157*7c478bd9Sstevel@tonic-gate {
1158*7c478bd9Sstevel@tonic-gate 	acf_t save_acf = (acf_t)POP(DS);
1159*7c478bd9Sstevel@tonic-gate 	acf_t acf = save_acf;
1160*7c478bd9Sstevel@tonic-gate 	int i, n, pass;
1161*7c478bd9Sstevel@tonic-gate 	token_t brtab[30], thentab[30], brstk[30];
1162*7c478bd9Sstevel@tonic-gate 	int nbrtab = 0, nthentab = 0, nbrstk = 0;
1163*7c478bd9Sstevel@tonic-gate 	uchar_t *p;
1164*7c478bd9Sstevel@tonic-gate 	int level = 0, doprintlevel = 1, nthen;
1165*7c478bd9Sstevel@tonic-gate 	struct bitab *bip;
1166*7c478bd9Sstevel@tonic-gate 	token_t last_lit = 0, case_lit = 0, endof_loc = 0, endcase_loc = 0;
1167*7c478bd9Sstevel@tonic-gate 
1168*7c478bd9Sstevel@tonic-gate 	if ((bip = lookup_builtin(*acf)) == NULL ||
1169*7c478bd9Sstevel@tonic-gate 	    bip->bi_type != BI_COLON) {
1170*7c478bd9Sstevel@tonic-gate 		if (bip = lookup_builtin((token_t)acf))
1171*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%s: builtin\n", bip->bi_name);
1172*7c478bd9Sstevel@tonic-gate 		else
1173*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%s: builtin\n",
1174*7c478bd9Sstevel@tonic-gate 			    acf_to_name(env, acf));
1175*7c478bd9Sstevel@tonic-gate 		return;
1176*7c478bd9Sstevel@tonic-gate 	}
1177*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, ": %s", acf_to_name(env, acf));
1178*7c478bd9Sstevel@tonic-gate 	for (pass = 0; pass < 2; pass++) {
1179*7c478bd9Sstevel@tonic-gate 		acf = save_acf;
1180*7c478bd9Sstevel@tonic-gate 		for (acf++; ; acf++) {
1181*7c478bd9Sstevel@tonic-gate 			if (pass) {
1182*7c478bd9Sstevel@tonic-gate 				print_level(level, &doprintlevel);
1183*7c478bd9Sstevel@tonic-gate 				for (nthen = 0; nthentab > 0 &&
1184*7c478bd9Sstevel@tonic-gate 				    thentab[nthentab-1] == (token_t)acf;
1185*7c478bd9Sstevel@tonic-gate 				    nthentab--)
1186*7c478bd9Sstevel@tonic-gate 					nthen++;
1187*7c478bd9Sstevel@tonic-gate 				if (nthen) {
1188*7c478bd9Sstevel@tonic-gate 					level -= nthen;
1189*7c478bd9Sstevel@tonic-gate 					doprintlevel = 1;
1190*7c478bd9Sstevel@tonic-gate 					print_level(level, &doprintlevel);
1191*7c478bd9Sstevel@tonic-gate 					for (i = 0; i < nthen; i++)
1192*7c478bd9Sstevel@tonic-gate 						log_message(MSG_INFO, "then ");
1193*7c478bd9Sstevel@tonic-gate 				}
1194*7c478bd9Sstevel@tonic-gate 				print_level(level, &doprintlevel);
1195*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < nbrtab; i += 2)
1196*7c478bd9Sstevel@tonic-gate 					if ((token_t)acf == brtab[i]) {
1197*7c478bd9Sstevel@tonic-gate 						log_message(MSG_INFO, "begin ");
1198*7c478bd9Sstevel@tonic-gate 						brstk[nbrstk++] = brtab[i+1];
1199*7c478bd9Sstevel@tonic-gate 						level++;
1200*7c478bd9Sstevel@tonic-gate 						doprintlevel = 1;
1201*7c478bd9Sstevel@tonic-gate 					}
1202*7c478bd9Sstevel@tonic-gate 				print_level(level, &doprintlevel);
1203*7c478bd9Sstevel@tonic-gate 				if (case_lit == (token_t)acf) {
1204*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "case ");
1205*7c478bd9Sstevel@tonic-gate 					doprintlevel = 1;
1206*7c478bd9Sstevel@tonic-gate 					print_level(level, &doprintlevel);
1207*7c478bd9Sstevel@tonic-gate 				}
1208*7c478bd9Sstevel@tonic-gate 				if (endof_loc == (token_t)acf) {
1209*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "endof ");
1210*7c478bd9Sstevel@tonic-gate 					doprintlevel = 1;
1211*7c478bd9Sstevel@tonic-gate 					print_level(level, &doprintlevel);
1212*7c478bd9Sstevel@tonic-gate 				}
1213*7c478bd9Sstevel@tonic-gate 				if (endcase_loc == (token_t)acf) {
1214*7c478bd9Sstevel@tonic-gate 					doprintlevel = 1;
1215*7c478bd9Sstevel@tonic-gate 					print_level(level, &doprintlevel);
1216*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "endcase ");
1217*7c478bd9Sstevel@tonic-gate 				}
1218*7c478bd9Sstevel@tonic-gate 			}
1219*7c478bd9Sstevel@tonic-gate 			if ((bip = lookup_builtin((token_t)*acf)) == 0) {
1220*7c478bd9Sstevel@tonic-gate 				last_lit = (token_t)acf;
1221*7c478bd9Sstevel@tonic-gate 				if (pass)
1222*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%s ",
1223*7c478bd9Sstevel@tonic-gate 					    acf_to_name(env, (acf_t)*acf));
1224*7c478bd9Sstevel@tonic-gate 				continue;
1225*7c478bd9Sstevel@tonic-gate 			}
1226*7c478bd9Sstevel@tonic-gate 			if (bip->bi_type == BI_SEMI) {
1227*7c478bd9Sstevel@tonic-gate 				if (pass) {
1228*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "\n");
1229*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%s\n",
1230*7c478bd9Sstevel@tonic-gate 					    bip->bi_name);
1231*7c478bd9Sstevel@tonic-gate 				}
1232*7c478bd9Sstevel@tonic-gate 				break;
1233*7c478bd9Sstevel@tonic-gate 			}
1234*7c478bd9Sstevel@tonic-gate 			switch (bip->bi_type) {
1235*7c478bd9Sstevel@tonic-gate 
1236*7c478bd9Sstevel@tonic-gate 			case BI_NOOP:
1237*7c478bd9Sstevel@tonic-gate 			case BI_NOTYET:
1238*7c478bd9Sstevel@tonic-gate 				if (pass)
1239*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%s ",
1240*7c478bd9Sstevel@tonic-gate 					    bip->bi_name);
1241*7c478bd9Sstevel@tonic-gate 				break;
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate 			case BI_QUOTE:
1244*7c478bd9Sstevel@tonic-gate 				if (pass)
1245*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "\" ");
1246*7c478bd9Sstevel@tonic-gate 				acf++;
1247*7c478bd9Sstevel@tonic-gate 				p = (uchar_t *)acf;
1248*7c478bd9Sstevel@tonic-gate 				n = *p++;
1249*7c478bd9Sstevel@tonic-gate 				if (pass)
1250*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%s\" ", p);
1251*7c478bd9Sstevel@tonic-gate 				p += n + 1;
1252*7c478bd9Sstevel@tonic-gate 				for (; ((token_t)(p)) & (sizeof (token_t) - 1);
1253*7c478bd9Sstevel@tonic-gate 				    p++)
1254*7c478bd9Sstevel@tonic-gate 					;
1255*7c478bd9Sstevel@tonic-gate 				acf = (acf_t)p;
1256*7c478bd9Sstevel@tonic-gate 				acf--;
1257*7c478bd9Sstevel@tonic-gate 				break;
1258*7c478bd9Sstevel@tonic-gate 
1259*7c478bd9Sstevel@tonic-gate 			case BI_BLIT:
1260*7c478bd9Sstevel@tonic-gate 				acf++;
1261*7c478bd9Sstevel@tonic-gate 				if (pass)
1262*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%x ", *acf);
1263*7c478bd9Sstevel@tonic-gate 				break;
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 			case BI_BDO:
1266*7c478bd9Sstevel@tonic-gate 			case BI_QDO:
1267*7c478bd9Sstevel@tonic-gate 				if (pass) {
1268*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%s ",
1269*7c478bd9Sstevel@tonic-gate 					    bip->bi_name);
1270*7c478bd9Sstevel@tonic-gate 					doprintlevel = 1;
1271*7c478bd9Sstevel@tonic-gate 					level++;
1272*7c478bd9Sstevel@tonic-gate 				}
1273*7c478bd9Sstevel@tonic-gate 				acf++;
1274*7c478bd9Sstevel@tonic-gate 				break;
1275*7c478bd9Sstevel@tonic-gate 
1276*7c478bd9Sstevel@tonic-gate 			case BI_BR:
1277*7c478bd9Sstevel@tonic-gate 				acf++;
1278*7c478bd9Sstevel@tonic-gate 				if (pass) {
1279*7c478bd9Sstevel@tonic-gate 					if (*acf < (token_t)acf) {
1280*7c478bd9Sstevel@tonic-gate 						if (nbrstk) {
1281*7c478bd9Sstevel@tonic-gate 							doprintlevel = 1;
1282*7c478bd9Sstevel@tonic-gate 							level--;
1283*7c478bd9Sstevel@tonic-gate 							print_level(level,
1284*7c478bd9Sstevel@tonic-gate 							    &doprintlevel);
1285*7c478bd9Sstevel@tonic-gate 							log_message(MSG_INFO,
1286*7c478bd9Sstevel@tonic-gate 							    "repeat ");
1287*7c478bd9Sstevel@tonic-gate 							nbrstk--;
1288*7c478bd9Sstevel@tonic-gate 						} else
1289*7c478bd9Sstevel@tonic-gate 							log_message(MSG_INFO,
1290*7c478bd9Sstevel@tonic-gate 							    "[br back?]");
1291*7c478bd9Sstevel@tonic-gate 					} else if (nthentab) {
1292*7c478bd9Sstevel@tonic-gate 						doprintlevel = 1;
1293*7c478bd9Sstevel@tonic-gate 						print_level(level - 1,
1294*7c478bd9Sstevel@tonic-gate 						    &doprintlevel);
1295*7c478bd9Sstevel@tonic-gate 						log_message(MSG_INFO, "else ");
1296*7c478bd9Sstevel@tonic-gate 						doprintlevel = 1;
1297*7c478bd9Sstevel@tonic-gate 						thentab[nthentab - 1] = *acf;
1298*7c478bd9Sstevel@tonic-gate 					}
1299*7c478bd9Sstevel@tonic-gate 				} else {
1300*7c478bd9Sstevel@tonic-gate 					if (*acf < (token_t)acf) {
1301*7c478bd9Sstevel@tonic-gate 						brtab[nbrtab++] = *acf;
1302*7c478bd9Sstevel@tonic-gate 						brtab[nbrtab++] = (token_t)acf;
1303*7c478bd9Sstevel@tonic-gate 					}
1304*7c478bd9Sstevel@tonic-gate 					if (endcase_loc == 0 &&
1305*7c478bd9Sstevel@tonic-gate 					    case_lit) {
1306*7c478bd9Sstevel@tonic-gate 						endcase_loc = *acf;
1307*7c478bd9Sstevel@tonic-gate 					}
1308*7c478bd9Sstevel@tonic-gate 				}
1309*7c478bd9Sstevel@tonic-gate 				break;
1310*7c478bd9Sstevel@tonic-gate 
1311*7c478bd9Sstevel@tonic-gate 			case BI_QBR:
1312*7c478bd9Sstevel@tonic-gate 				acf++;
1313*7c478bd9Sstevel@tonic-gate 				if (pass) {
1314*7c478bd9Sstevel@tonic-gate 					if (*acf < (token_t)acf) {
1315*7c478bd9Sstevel@tonic-gate 						if (nbrstk) {
1316*7c478bd9Sstevel@tonic-gate 							doprintlevel = 1;
1317*7c478bd9Sstevel@tonic-gate 							level--;
1318*7c478bd9Sstevel@tonic-gate 							print_level(level,
1319*7c478bd9Sstevel@tonic-gate 							    &doprintlevel);
1320*7c478bd9Sstevel@tonic-gate 							log_message(MSG_INFO,
1321*7c478bd9Sstevel@tonic-gate 							    "until ");
1322*7c478bd9Sstevel@tonic-gate 							nbrstk--;
1323*7c478bd9Sstevel@tonic-gate 						} else
1324*7c478bd9Sstevel@tonic-gate 							log_message(MSG_INFO,
1325*7c478bd9Sstevel@tonic-gate 							    "[br back?]");
1326*7c478bd9Sstevel@tonic-gate 					} else if (nbrstk > 0 &&
1327*7c478bd9Sstevel@tonic-gate 					    *acf >= brstk[nbrstk - 1]) {
1328*7c478bd9Sstevel@tonic-gate 						doprintlevel = 1;
1329*7c478bd9Sstevel@tonic-gate 						print_level(level - 1,
1330*7c478bd9Sstevel@tonic-gate 						    &doprintlevel);
1331*7c478bd9Sstevel@tonic-gate 						log_message(MSG_INFO,
1332*7c478bd9Sstevel@tonic-gate 						    "while ");
1333*7c478bd9Sstevel@tonic-gate 						doprintlevel = 1;
1334*7c478bd9Sstevel@tonic-gate 					} else {
1335*7c478bd9Sstevel@tonic-gate 						log_message(MSG_INFO, "if ");
1336*7c478bd9Sstevel@tonic-gate 						doprintlevel = 1;
1337*7c478bd9Sstevel@tonic-gate 						level++;
1338*7c478bd9Sstevel@tonic-gate 						thentab[nthentab++] = *acf;
1339*7c478bd9Sstevel@tonic-gate 					}
1340*7c478bd9Sstevel@tonic-gate 				} else if (*acf < (token_t)acf) {
1341*7c478bd9Sstevel@tonic-gate 					brtab[nbrtab++] = *acf;
1342*7c478bd9Sstevel@tonic-gate 					brtab[nbrtab++] = (token_t)acf;
1343*7c478bd9Sstevel@tonic-gate 				}
1344*7c478bd9Sstevel@tonic-gate 				break;
1345*7c478bd9Sstevel@tonic-gate 
1346*7c478bd9Sstevel@tonic-gate 			case BI_BOF:
1347*7c478bd9Sstevel@tonic-gate 				acf++;
1348*7c478bd9Sstevel@tonic-gate 				if (pass) {
1349*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "of ");
1350*7c478bd9Sstevel@tonic-gate 					endof_loc = *acf;
1351*7c478bd9Sstevel@tonic-gate 				} else if (case_lit == 0) {
1352*7c478bd9Sstevel@tonic-gate 					case_lit = last_lit;
1353*7c478bd9Sstevel@tonic-gate 				}
1354*7c478bd9Sstevel@tonic-gate 				break;
1355*7c478bd9Sstevel@tonic-gate 
1356*7c478bd9Sstevel@tonic-gate 			case BI_LOOP:
1357*7c478bd9Sstevel@tonic-gate 			case BI_PLOOP:
1358*7c478bd9Sstevel@tonic-gate 				if (pass) {
1359*7c478bd9Sstevel@tonic-gate 					level--;
1360*7c478bd9Sstevel@tonic-gate 					doprintlevel = 1;
1361*7c478bd9Sstevel@tonic-gate 					print_level(level, &doprintlevel);
1362*7c478bd9Sstevel@tonic-gate 					log_message(MSG_INFO, "%s ",
1363*7c478bd9Sstevel@tonic-gate 					    bip->bi_name);
1364*7c478bd9Sstevel@tonic-gate 				}
1365*7c478bd9Sstevel@tonic-gate 				acf++;
1366*7c478bd9Sstevel@tonic-gate 				break;
1367*7c478bd9Sstevel@tonic-gate 
1368*7c478bd9Sstevel@tonic-gate 			default:
1369*7c478bd9Sstevel@tonic-gate 				log_message(MSG_ERROR, "Invalid builtin %s\n",
1370*7c478bd9Sstevel@tonic-gate 				    bip->bi_name);
1371*7c478bd9Sstevel@tonic-gate 			}
1372*7c478bd9Sstevel@tonic-gate 		}
1373*7c478bd9Sstevel@tonic-gate 	}
1374*7c478bd9Sstevel@tonic-gate }
1375*7c478bd9Sstevel@tonic-gate 
1376*7c478bd9Sstevel@tonic-gate static void
1377*7c478bd9Sstevel@tonic-gate see(fcode_env_t *env)
1378*7c478bd9Sstevel@tonic-gate {
1379*7c478bd9Sstevel@tonic-gate 	fstack_t d;
1380*7c478bd9Sstevel@tonic-gate 
1381*7c478bd9Sstevel@tonic-gate 	parse_word(env);
1382*7c478bd9Sstevel@tonic-gate 	dollar_find(env);
1383*7c478bd9Sstevel@tonic-gate 	d = POP(DS);
1384*7c478bd9Sstevel@tonic-gate 	if (d)
1385*7c478bd9Sstevel@tonic-gate 		paren_see(env);
1386*7c478bd9Sstevel@tonic-gate 	else {
1387*7c478bd9Sstevel@tonic-gate 		log_message(MSG_WARN, "?");
1388*7c478bd9Sstevel@tonic-gate 		two_drop(env);
1389*7c478bd9Sstevel@tonic-gate 	}
1390*7c478bd9Sstevel@tonic-gate }
1391*7c478bd9Sstevel@tonic-gate 
1392*7c478bd9Sstevel@tonic-gate static acf_t
1393*7c478bd9Sstevel@tonic-gate do_dot_calls(fcode_env_t *env, acf_t acf, void *cacf)
1394*7c478bd9Sstevel@tonic-gate {
1395*7c478bd9Sstevel@tonic-gate 	token_t *dptr = ACF_TO_LINK(acf);
1396*7c478bd9Sstevel@tonic-gate 	token_t *wptr = acf;
1397*7c478bd9Sstevel@tonic-gate 
1398*7c478bd9Sstevel@tonic-gate 	if (*wptr == (token_t)(&do_colon)) {
1399*7c478bd9Sstevel@tonic-gate 		do {
1400*7c478bd9Sstevel@tonic-gate 			if ((acf_t)(*wptr) == (acf_t)cacf)
1401*7c478bd9Sstevel@tonic-gate 				output_acf_name(acf);
1402*7c478bd9Sstevel@tonic-gate 		} while (*wptr++ != (token_t)(&semi_ptr));
1403*7c478bd9Sstevel@tonic-gate 	} else if ((acf_t)(*wptr) == cacf)
1404*7c478bd9Sstevel@tonic-gate 		output_acf_name(acf);
1405*7c478bd9Sstevel@tonic-gate 	else if (wptr == (token_t *)cacf)
1406*7c478bd9Sstevel@tonic-gate 		output_acf_name(acf);
1407*7c478bd9Sstevel@tonic-gate 	return (NULL);
1408*7c478bd9Sstevel@tonic-gate }
1409*7c478bd9Sstevel@tonic-gate 
1410*7c478bd9Sstevel@tonic-gate static void
1411*7c478bd9Sstevel@tonic-gate dot_calls(fcode_env_t *env)
1412*7c478bd9Sstevel@tonic-gate {
1413*7c478bd9Sstevel@tonic-gate 	acf_t acf = (acf_t)POP(DS);
1414*7c478bd9Sstevel@tonic-gate 
1415*7c478bd9Sstevel@tonic-gate 	search_all_dictionaries(env, do_dot_calls, acf);
1416*7c478bd9Sstevel@tonic-gate 	output_acf_name(NULL);
1417*7c478bd9Sstevel@tonic-gate }
1418*7c478bd9Sstevel@tonic-gate 
1419*7c478bd9Sstevel@tonic-gate static void
1420*7c478bd9Sstevel@tonic-gate dot_pci_space(fcode_env_t *env)
1421*7c478bd9Sstevel@tonic-gate {
1422*7c478bd9Sstevel@tonic-gate 	fstack_t d = POP(DS);
1423*7c478bd9Sstevel@tonic-gate 
1424*7c478bd9Sstevel@tonic-gate 	switch ((d >> 24) & 0x3) {
1425*7c478bd9Sstevel@tonic-gate 	case 0: log_message(MSG_INFO, "Config,"); break;
1426*7c478bd9Sstevel@tonic-gate 	case 1: log_message(MSG_INFO, "IO,"); break;
1427*7c478bd9Sstevel@tonic-gate 	case 2: log_message(MSG_INFO, "Memory32,"); break;
1428*7c478bd9Sstevel@tonic-gate 	case 3: log_message(MSG_INFO, "Memory64,"); break;
1429*7c478bd9Sstevel@tonic-gate 	}
1430*7c478bd9Sstevel@tonic-gate 	if (d & 0x80000000)
1431*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "Not_reloc,");
1432*7c478bd9Sstevel@tonic-gate 	if (d & 0x400000000)
1433*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "Prefetch,");
1434*7c478bd9Sstevel@tonic-gate 	if (d & 0x200000000)
1435*7c478bd9Sstevel@tonic-gate 		log_message(MSG_INFO, "Alias,");
1436*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "Bus%d,", (d >> 16) & 0xff);
1437*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "Dev%d,", (d >> 11) & 0x1f);
1438*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "Func%d,", (d >> 8) & 0x7);
1439*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "Reg%x", d & 0xff);
1440*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "\n");
1441*7c478bd9Sstevel@tonic-gate }
1442*7c478bd9Sstevel@tonic-gate 
1443*7c478bd9Sstevel@tonic-gate void
1444*7c478bd9Sstevel@tonic-gate fcode_debug(fcode_env_t *env)
1445*7c478bd9Sstevel@tonic-gate {
1446*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)(&env->fcode_debug));
1447*7c478bd9Sstevel@tonic-gate }
1448*7c478bd9Sstevel@tonic-gate 
1449*7c478bd9Sstevel@tonic-gate static void
1450*7c478bd9Sstevel@tonic-gate base_addr(fcode_env_t *env)
1451*7c478bd9Sstevel@tonic-gate {
1452*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)env->base);
1453*7c478bd9Sstevel@tonic-gate }
1454*7c478bd9Sstevel@tonic-gate 
1455*7c478bd9Sstevel@tonic-gate static int mw_valid;
1456*7c478bd9Sstevel@tonic-gate static int mw_size;
1457*7c478bd9Sstevel@tonic-gate static void *mw_addr;
1458*7c478bd9Sstevel@tonic-gate static fstack_t mw_value;
1459*7c478bd9Sstevel@tonic-gate static fstack_t mw_lastvalue;
1460*7c478bd9Sstevel@tonic-gate 
1461*7c478bd9Sstevel@tonic-gate static fstack_t
1462*7c478bd9Sstevel@tonic-gate mw_fetch(void)
1463*7c478bd9Sstevel@tonic-gate {
1464*7c478bd9Sstevel@tonic-gate 	switch (mw_size) {
1465*7c478bd9Sstevel@tonic-gate 	case 1: return (*((uint8_t *)mw_addr));
1466*7c478bd9Sstevel@tonic-gate 	case 2: return (*((uint16_t *)mw_addr));
1467*7c478bd9Sstevel@tonic-gate 	case 4: return (*((uint32_t *)mw_addr));
1468*7c478bd9Sstevel@tonic-gate 	case 8: return (*((uint64_t *)mw_addr));
1469*7c478bd9Sstevel@tonic-gate 	}
1470*7c478bd9Sstevel@tonic-gate 	return (0);
1471*7c478bd9Sstevel@tonic-gate }
1472*7c478bd9Sstevel@tonic-gate 
1473*7c478bd9Sstevel@tonic-gate void
1474*7c478bd9Sstevel@tonic-gate do_memory_watch(fcode_env_t *env)
1475*7c478bd9Sstevel@tonic-gate {
1476*7c478bd9Sstevel@tonic-gate 	fstack_t value;
1477*7c478bd9Sstevel@tonic-gate 
1478*7c478bd9Sstevel@tonic-gate 	if (!mw_valid)
1479*7c478bd9Sstevel@tonic-gate 		return;
1480*7c478bd9Sstevel@tonic-gate 	value = mw_fetch();
1481*7c478bd9Sstevel@tonic-gate 	if (value != mw_lastvalue) {
1482*7c478bd9Sstevel@tonic-gate 		if (mw_valid == 1 || mw_value == value) {
1483*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO,
1484*7c478bd9Sstevel@tonic-gate 			    "memory-watch: %p/%d: %llx -> %llx\n",
1485*7c478bd9Sstevel@tonic-gate 			    mw_addr, mw_size, (uint64_t)mw_lastvalue,
1486*7c478bd9Sstevel@tonic-gate 			    (uint64_t)value);
1487*7c478bd9Sstevel@tonic-gate 			do_fclib_step(env);
1488*7c478bd9Sstevel@tonic-gate 		}
1489*7c478bd9Sstevel@tonic-gate 		mw_lastvalue = value;
1490*7c478bd9Sstevel@tonic-gate 	}
1491*7c478bd9Sstevel@tonic-gate }
1492*7c478bd9Sstevel@tonic-gate 
1493*7c478bd9Sstevel@tonic-gate static void
1494*7c478bd9Sstevel@tonic-gate set_memory_watch(fcode_env_t *env, int type, int size, void *addr,
1495*7c478bd9Sstevel@tonic-gate     fstack_t value)
1496*7c478bd9Sstevel@tonic-gate {
1497*7c478bd9Sstevel@tonic-gate 	switch (size) {
1498*7c478bd9Sstevel@tonic-gate 	case 1: case 2: case 4: case 8:
1499*7c478bd9Sstevel@tonic-gate 		break;
1500*7c478bd9Sstevel@tonic-gate 	default:
1501*7c478bd9Sstevel@tonic-gate 		log_message(MSG_ERROR, "set_memory_watch: invalid size: %d\n",
1502*7c478bd9Sstevel@tonic-gate 		    size);
1503*7c478bd9Sstevel@tonic-gate 		return;
1504*7c478bd9Sstevel@tonic-gate 	}
1505*7c478bd9Sstevel@tonic-gate 	mw_valid = type;
1506*7c478bd9Sstevel@tonic-gate 	mw_size = size;
1507*7c478bd9Sstevel@tonic-gate 	mw_addr = addr;
1508*7c478bd9Sstevel@tonic-gate 	mw_value = value;
1509*7c478bd9Sstevel@tonic-gate 	mw_lastvalue = mw_fetch();
1510*7c478bd9Sstevel@tonic-gate }
1511*7c478bd9Sstevel@tonic-gate 
1512*7c478bd9Sstevel@tonic-gate static void
1513*7c478bd9Sstevel@tonic-gate memory_watch(fcode_env_t *env)
1514*7c478bd9Sstevel@tonic-gate {
1515*7c478bd9Sstevel@tonic-gate 	int size = POP(DS);
1516*7c478bd9Sstevel@tonic-gate 	void *addr = (void *)POP(DS);
1517*7c478bd9Sstevel@tonic-gate 
1518*7c478bd9Sstevel@tonic-gate 	set_memory_watch(env, 1, size, addr, 0);
1519*7c478bd9Sstevel@tonic-gate }
1520*7c478bd9Sstevel@tonic-gate 
1521*7c478bd9Sstevel@tonic-gate static void
1522*7c478bd9Sstevel@tonic-gate memory_watch_value(fcode_env_t *env)
1523*7c478bd9Sstevel@tonic-gate {
1524*7c478bd9Sstevel@tonic-gate 	int size = POP(DS);
1525*7c478bd9Sstevel@tonic-gate 	void *addr = (void *)POP(DS);
1526*7c478bd9Sstevel@tonic-gate 	fstack_t value = POP(DS);
1527*7c478bd9Sstevel@tonic-gate 
1528*7c478bd9Sstevel@tonic-gate 	set_memory_watch(env, 2, size, addr, value);
1529*7c478bd9Sstevel@tonic-gate }
1530*7c478bd9Sstevel@tonic-gate 
1531*7c478bd9Sstevel@tonic-gate static void
1532*7c478bd9Sstevel@tonic-gate memory_watch_clear(fcode_env_t *env)
1533*7c478bd9Sstevel@tonic-gate {
1534*7c478bd9Sstevel@tonic-gate 	mw_valid = 0;
1535*7c478bd9Sstevel@tonic-gate }
1536*7c478bd9Sstevel@tonic-gate 
1537*7c478bd9Sstevel@tonic-gate static void
1538*7c478bd9Sstevel@tonic-gate vsearch(fcode_env_t *env)
1539*7c478bd9Sstevel@tonic-gate {
1540*7c478bd9Sstevel@tonic-gate 	fstack_t value;
1541*7c478bd9Sstevel@tonic-gate 	int size = POP(DS);
1542*7c478bd9Sstevel@tonic-gate 	fstack_t match_value = POP(DS);
1543*7c478bd9Sstevel@tonic-gate 	uchar_t *toaddr = (uchar_t *)POP(DS);
1544*7c478bd9Sstevel@tonic-gate 	uchar_t *fromaddr = (uchar_t *)POP(DS);
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "%p to %p by %d looking for %llx\n", fromaddr,
1547*7c478bd9Sstevel@tonic-gate 	    toaddr, size, (uint64_t)match_value);
1548*7c478bd9Sstevel@tonic-gate 	for (; fromaddr < toaddr; fromaddr += size) {
1549*7c478bd9Sstevel@tonic-gate 		switch (size) {
1550*7c478bd9Sstevel@tonic-gate 		case 1: value = *((uint8_t *)fromaddr); break;
1551*7c478bd9Sstevel@tonic-gate 		case 2: value = *((uint16_t *)fromaddr); break;
1552*7c478bd9Sstevel@tonic-gate 		case 4: value = *((uint32_t *)fromaddr); break;
1553*7c478bd9Sstevel@tonic-gate 		case 8: value = *((uint64_t *)fromaddr); break;
1554*7c478bd9Sstevel@tonic-gate 		default:
1555*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "Invalid size: %d\n", size);
1556*7c478bd9Sstevel@tonic-gate 			return;
1557*7c478bd9Sstevel@tonic-gate 		}
1558*7c478bd9Sstevel@tonic-gate 		if (value == match_value)
1559*7c478bd9Sstevel@tonic-gate 			log_message(MSG_INFO, "%p\n", fromaddr);
1560*7c478bd9Sstevel@tonic-gate 	}
1561*7c478bd9Sstevel@tonic-gate }
1562*7c478bd9Sstevel@tonic-gate 
1563*7c478bd9Sstevel@tonic-gate #pragma init(_init)
1564*7c478bd9Sstevel@tonic-gate 
1565*7c478bd9Sstevel@tonic-gate static void
1566*7c478bd9Sstevel@tonic-gate _init(void)
1567*7c478bd9Sstevel@tonic-gate {
1568*7c478bd9Sstevel@tonic-gate 	fcode_env_t *env = initial_env;
1569*7c478bd9Sstevel@tonic-gate 
1570*7c478bd9Sstevel@tonic-gate 	ASSERT(env);
1571*7c478bd9Sstevel@tonic-gate 	NOTICE;
1572*7c478bd9Sstevel@tonic-gate 
1573*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"words",		words);
1574*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"dump-words",		dump_words);
1575*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"dump-dict",		dump_dictionary);
1576*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"dump-table",		dump_table);
1577*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"debugf",		debugf);
1578*7c478bd9Sstevel@tonic-gate 	FORTH(0,		".debugf",		dot_debugf);
1579*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"set-debugf",		set_debugf);
1580*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"debugf?",		debugf_qmark);
1581*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"control",		control);
1582*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"dump",			dump);
1583*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"showstack",		show_stack);
1584*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"sifting",		sifting);
1585*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"ctrace",		ctrace);
1586*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"ftrace",		ftrace);
1587*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"see",			see);
1588*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"(see)",		paren_see);
1589*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"base-addr",		base_addr);
1590*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"smatch",		smatch);
1591*7c478bd9Sstevel@tonic-gate 	FORTH(0,		".calls",		dot_calls);
1592*7c478bd9Sstevel@tonic-gate 	FORTH(0,		".pci-space",		dot_pci_space);
1593*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"(debug)",		paren_debug);
1594*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"debug",		debug);
1595*7c478bd9Sstevel@tonic-gate 	FORTH(0,		".debug",		dot_debug);
1596*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"undebug",		undebug);
1597*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"memory-watch",		memory_watch);
1598*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"memory-watch-value",	memory_watch_value);
1599*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"memory-watch-clear",	memory_watch_clear);
1600*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"vsearch",		vsearch);
1601*7c478bd9Sstevel@tonic-gate }
1602