xref: /titanic_52/usr/src/lib/efcode/engine/interactive.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 (c) 2000 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
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 <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <unistd.h>
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
34*7c478bd9Sstevel@tonic-gate #include <setjmp.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.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 void (*to_ptr)(fcode_env_t *env) = do_set_action;
41*7c478bd9Sstevel@tonic-gate jmp_buf *jmp_buf_ptr = NULL;
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate char *
44*7c478bd9Sstevel@tonic-gate parse_a_string(fcode_env_t *env, int *lenp)
45*7c478bd9Sstevel@tonic-gate {
46*7c478bd9Sstevel@tonic-gate 	parse_word(env);
47*7c478bd9Sstevel@tonic-gate 	return (pop_a_string(env, lenp));
48*7c478bd9Sstevel@tonic-gate }
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate void
51*7c478bd9Sstevel@tonic-gate constant(fcode_env_t *env)
52*7c478bd9Sstevel@tonic-gate {
53*7c478bd9Sstevel@tonic-gate 	char *name;
54*7c478bd9Sstevel@tonic-gate 	int len;
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate 	name = parse_a_string(env, &len);
57*7c478bd9Sstevel@tonic-gate 	env->instance_mode = 0;
58*7c478bd9Sstevel@tonic-gate 	make_common_access(env, name, len, 1, 0,
59*7c478bd9Sstevel@tonic-gate 	    &do_constant, &do_constant, NULL);
60*7c478bd9Sstevel@tonic-gate }
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate void
63*7c478bd9Sstevel@tonic-gate buffer_colon(fcode_env_t *env)
64*7c478bd9Sstevel@tonic-gate {
65*7c478bd9Sstevel@tonic-gate 	char *name;
66*7c478bd9Sstevel@tonic-gate 	int len;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 	PUSH(DS, 0);
69*7c478bd9Sstevel@tonic-gate 	name = parse_a_string(env, &len);
70*7c478bd9Sstevel@tonic-gate 	make_common_access(env, name, len, 2,
71*7c478bd9Sstevel@tonic-gate 	    env->instance_mode, &noop, &noop, &set_buffer_actions);
72*7c478bd9Sstevel@tonic-gate }
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate void
75*7c478bd9Sstevel@tonic-gate value(fcode_env_t *env)
76*7c478bd9Sstevel@tonic-gate {
77*7c478bd9Sstevel@tonic-gate 	char *name;
78*7c478bd9Sstevel@tonic-gate 	int len;
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate 	name = parse_a_string(env, &len);
81*7c478bd9Sstevel@tonic-gate 	make_common_access(env, name, len, 1,
82*7c478bd9Sstevel@tonic-gate 	    env->instance_mode, &noop, &noop, &set_value_actions);
83*7c478bd9Sstevel@tonic-gate }
84*7c478bd9Sstevel@tonic-gate 
85*7c478bd9Sstevel@tonic-gate void
86*7c478bd9Sstevel@tonic-gate variable(fcode_env_t *env)
87*7c478bd9Sstevel@tonic-gate {
88*7c478bd9Sstevel@tonic-gate 	char *name;
89*7c478bd9Sstevel@tonic-gate 	int len;
90*7c478bd9Sstevel@tonic-gate 
91*7c478bd9Sstevel@tonic-gate 	PUSH(DS, 0);
92*7c478bd9Sstevel@tonic-gate 	name = parse_a_string(env, &len);
93*7c478bd9Sstevel@tonic-gate 	make_common_access(env, name, len, 1,
94*7c478bd9Sstevel@tonic-gate 	    env->instance_mode, &instance_variable, &do_create, NULL);
95*7c478bd9Sstevel@tonic-gate }
96*7c478bd9Sstevel@tonic-gate 
97*7c478bd9Sstevel@tonic-gate void
98*7c478bd9Sstevel@tonic-gate defer(fcode_env_t *env)
99*7c478bd9Sstevel@tonic-gate {
100*7c478bd9Sstevel@tonic-gate 	static void (*crash_ptr)(fcode_env_t *env) = do_crash;
101*7c478bd9Sstevel@tonic-gate 	char *name;
102*7c478bd9Sstevel@tonic-gate 	int len;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)&crash_ptr);
105*7c478bd9Sstevel@tonic-gate 	name = parse_a_string(env, &len);
106*7c478bd9Sstevel@tonic-gate 	make_common_access(env, name, len, 1,
107*7c478bd9Sstevel@tonic-gate 		env->instance_mode, &noop, &noop, &set_defer_actions);
108*7c478bd9Sstevel@tonic-gate }
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate void
111*7c478bd9Sstevel@tonic-gate field(fcode_env_t *env)
112*7c478bd9Sstevel@tonic-gate {
113*7c478bd9Sstevel@tonic-gate 	char *name;
114*7c478bd9Sstevel@tonic-gate 	int len;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	over(env);
117*7c478bd9Sstevel@tonic-gate 	name = parse_a_string(env, &len);
118*7c478bd9Sstevel@tonic-gate 	make_common_access(env, name, len, 1, 0, &do_field, &do_field, NULL);
119*7c478bd9Sstevel@tonic-gate 	add(env);
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate void
123*7c478bd9Sstevel@tonic-gate bye(fcode_env_t *env)
124*7c478bd9Sstevel@tonic-gate {
125*7c478bd9Sstevel@tonic-gate 	exit(0);
126*7c478bd9Sstevel@tonic-gate }
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate void
129*7c478bd9Sstevel@tonic-gate do_resume(fcode_env_t *env)
130*7c478bd9Sstevel@tonic-gate {
131*7c478bd9Sstevel@tonic-gate 	if (env->interactive) env->interactive--;
132*7c478bd9Sstevel@tonic-gate 	COMPLETE_INTERRUPT;
133*7c478bd9Sstevel@tonic-gate }
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate /*
136*7c478bd9Sstevel@tonic-gate  * In interactive mode, jmp_buf_ptr should be non-null.
137*7c478bd9Sstevel@tonic-gate  */
138*7c478bd9Sstevel@tonic-gate void
139*7c478bd9Sstevel@tonic-gate return_to_interact(fcode_env_t *env)
140*7c478bd9Sstevel@tonic-gate {
141*7c478bd9Sstevel@tonic-gate 	if (jmp_buf_ptr)
142*7c478bd9Sstevel@tonic-gate 		longjmp(*jmp_buf_ptr, 1);
143*7c478bd9Sstevel@tonic-gate }
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate void
146*7c478bd9Sstevel@tonic-gate do_interact(fcode_env_t *env)
147*7c478bd9Sstevel@tonic-gate {
148*7c478bd9Sstevel@tonic-gate 	int level;
149*7c478bd9Sstevel@tonic-gate 	jmp_buf jmp_env;
150*7c478bd9Sstevel@tonic-gate 	jmp_buf *ojmp_ptr;
151*7c478bd9Sstevel@tonic-gate 	error_frame new;
152*7c478bd9Sstevel@tonic-gate 	input_typ *old_input = env->input;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "Type resume to return\n");
155*7c478bd9Sstevel@tonic-gate 	env->interactive++;
156*7c478bd9Sstevel@tonic-gate 	level = env->interactive;
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 	ojmp_ptr = jmp_buf_ptr;
159*7c478bd9Sstevel@tonic-gate 	jmp_buf_ptr = &jmp_env;
160*7c478bd9Sstevel@tonic-gate 	env->input->separator = ' ';
161*7c478bd9Sstevel@tonic-gate 	env->input->maxlen = 256;
162*7c478bd9Sstevel@tonic-gate 	env->input->buffer = MALLOC(env->input->maxlen);
163*7c478bd9Sstevel@tonic-gate 	env->input->scanptr = env->input->buffer;
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate 	if (setjmp(jmp_env)) {
166*7c478bd9Sstevel@tonic-gate 		if (in_forth_abort > 1) {
167*7c478bd9Sstevel@tonic-gate 			RS = env->rs0;
168*7c478bd9Sstevel@tonic-gate 			DS = env->ds0;
169*7c478bd9Sstevel@tonic-gate 			MYSELF = 0;
170*7c478bd9Sstevel@tonic-gate 			IP = 0;
171*7c478bd9Sstevel@tonic-gate 			env->input = old_input;
172*7c478bd9Sstevel@tonic-gate 			env->order_depth = 0;
173*7c478bd9Sstevel@tonic-gate 		} else {
174*7c478bd9Sstevel@tonic-gate 			RS		= new.rs;
175*7c478bd9Sstevel@tonic-gate 			DS		= new.ds;
176*7c478bd9Sstevel@tonic-gate 			MYSELF		= new.myself;
177*7c478bd9Sstevel@tonic-gate 			IP		= new.ip;
178*7c478bd9Sstevel@tonic-gate 			env->input	= old_input;
179*7c478bd9Sstevel@tonic-gate 		}
180*7c478bd9Sstevel@tonic-gate 		do_forth(env);
181*7c478bd9Sstevel@tonic-gate 		do_definitions(env);
182*7c478bd9Sstevel@tonic-gate 		in_forth_abort = 0;
183*7c478bd9Sstevel@tonic-gate 	} else {
184*7c478bd9Sstevel@tonic-gate 		new.rs		= RS;
185*7c478bd9Sstevel@tonic-gate 		new.ds		= DS;
186*7c478bd9Sstevel@tonic-gate 		new.myself	= MYSELF;
187*7c478bd9Sstevel@tonic-gate 		new.ip		= IP;
188*7c478bd9Sstevel@tonic-gate 	}
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	while (env->interactive == level) {
191*7c478bd9Sstevel@tonic-gate 		int wlen;
192*7c478bd9Sstevel@tonic-gate 		char *p;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 		DEBUGF(SHOW_RS, output_return_stack(env, 0, MSG_FC_DEBUG));
195*7c478bd9Sstevel@tonic-gate 		DEBUGF(SHOW_STACK, output_data_stack(env, MSG_FC_DEBUG));
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate #define	USE_READLINE
198*7c478bd9Sstevel@tonic-gate #ifdef USE_READLINE
199*7c478bd9Sstevel@tonic-gate 		{
200*7c478bd9Sstevel@tonic-gate 			char *line;
201*7c478bd9Sstevel@tonic-gate 			void read_line(fcode_env_t *);
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate 			read_line(env);
204*7c478bd9Sstevel@tonic-gate 			if ((line = pop_a_string(env, NULL)) == NULL)
205*7c478bd9Sstevel@tonic-gate 				continue;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 			env->input->scanptr = strcpy(env->input->buffer, line);
208*7c478bd9Sstevel@tonic-gate 		}
209*7c478bd9Sstevel@tonic-gate #else
210*7c478bd9Sstevel@tonic-gate 		if (isatty(fileno(stdin)))
211*7c478bd9Sstevel@tonic-gate 			printf("ok ");
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 		env->input->scanptr = fgets(env->input->buffer,
214*7c478bd9Sstevel@tonic-gate 		    env->input->maxlen, stdin);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 		if (feof(stdin))
217*7c478bd9Sstevel@tonic-gate 			break;
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 		if (env->input->scanptr == NULL)
220*7c478bd9Sstevel@tonic-gate 			continue;
221*7c478bd9Sstevel@tonic-gate #endif
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 		if ((p = strpbrk(env->input->scanptr, "\n\r")) != NULL)
224*7c478bd9Sstevel@tonic-gate 			*p = '\0';
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate 		if ((wlen = strlen(env->input->scanptr)) == 0)
227*7c478bd9Sstevel@tonic-gate 			continue;
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 		PUSH(DS, (fstack_t)env->input->buffer);
230*7c478bd9Sstevel@tonic-gate 		PUSH(DS, wlen);
231*7c478bd9Sstevel@tonic-gate 		evaluate(env);
232*7c478bd9Sstevel@tonic-gate 	}
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate 	jmp_buf_ptr = ojmp_ptr;
235*7c478bd9Sstevel@tonic-gate 	FREE(env->input->buffer);
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate static void
239*7c478bd9Sstevel@tonic-gate temp_base(fcode_env_t *env, fstack_t base)
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	fstack_t obase;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	obase = env->num_base;
244*7c478bd9Sstevel@tonic-gate 	env->num_base = base;
245*7c478bd9Sstevel@tonic-gate 	parse_word(env);
246*7c478bd9Sstevel@tonic-gate 	evaluate(env);
247*7c478bd9Sstevel@tonic-gate 	env->num_base = obase;
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate static void
251*7c478bd9Sstevel@tonic-gate temp_decimal(fcode_env_t *env)
252*7c478bd9Sstevel@tonic-gate {
253*7c478bd9Sstevel@tonic-gate 	temp_base(env, 10);
254*7c478bd9Sstevel@tonic-gate }
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate static void
257*7c478bd9Sstevel@tonic-gate temp_hex(fcode_env_t *env)
258*7c478bd9Sstevel@tonic-gate {
259*7c478bd9Sstevel@tonic-gate 	temp_base(env, 0x10);
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate static void
263*7c478bd9Sstevel@tonic-gate temp_binary(fcode_env_t *env)
264*7c478bd9Sstevel@tonic-gate {
265*7c478bd9Sstevel@tonic-gate 	temp_base(env, 2);
266*7c478bd9Sstevel@tonic-gate }
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate static void
269*7c478bd9Sstevel@tonic-gate do_hex(fcode_env_t *env)
270*7c478bd9Sstevel@tonic-gate {
271*7c478bd9Sstevel@tonic-gate 	env->num_base = 0x10;
272*7c478bd9Sstevel@tonic-gate }
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate static void
275*7c478bd9Sstevel@tonic-gate do_decimal(fcode_env_t *env)
276*7c478bd9Sstevel@tonic-gate {
277*7c478bd9Sstevel@tonic-gate 	env->num_base = 10;
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate static void
281*7c478bd9Sstevel@tonic-gate do_binary(fcode_env_t *env)
282*7c478bd9Sstevel@tonic-gate {
283*7c478bd9Sstevel@tonic-gate 	env->num_base = 2;
284*7c478bd9Sstevel@tonic-gate }
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate static void
287*7c478bd9Sstevel@tonic-gate do_clear(fcode_env_t *env)
288*7c478bd9Sstevel@tonic-gate {
289*7c478bd9Sstevel@tonic-gate 	DS = env->ds0;
290*7c478bd9Sstevel@tonic-gate }
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate static void
293*7c478bd9Sstevel@tonic-gate action_one(fcode_env_t *env)
294*7c478bd9Sstevel@tonic-gate {
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	do_tick(env);
297*7c478bd9Sstevel@tonic-gate 	if (env->state) {
298*7c478bd9Sstevel@tonic-gate 		COMPILE_TOKEN(&to_ptr);
299*7c478bd9Sstevel@tonic-gate 	} else {
300*7c478bd9Sstevel@tonic-gate 		PUSH(DS, 1);
301*7c478bd9Sstevel@tonic-gate 		perform_action(env);
302*7c478bd9Sstevel@tonic-gate 	}
303*7c478bd9Sstevel@tonic-gate }
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate void
306*7c478bd9Sstevel@tonic-gate do_if(fcode_env_t *env)
307*7c478bd9Sstevel@tonic-gate {
308*7c478bd9Sstevel@tonic-gate 	branch_common(env, 1, 1, 0);
309*7c478bd9Sstevel@tonic-gate }
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate void
312*7c478bd9Sstevel@tonic-gate do_else(fcode_env_t *env)
313*7c478bd9Sstevel@tonic-gate {
314*7c478bd9Sstevel@tonic-gate 	branch_common(env, 1, 0, 1);
315*7c478bd9Sstevel@tonic-gate 	bresolve(env);
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate void
319*7c478bd9Sstevel@tonic-gate do_then(fcode_env_t *env)
320*7c478bd9Sstevel@tonic-gate {
321*7c478bd9Sstevel@tonic-gate 	bresolve(env);
322*7c478bd9Sstevel@tonic-gate }
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate void
325*7c478bd9Sstevel@tonic-gate do_of(fcode_env_t *env)
326*7c478bd9Sstevel@tonic-gate {
327*7c478bd9Sstevel@tonic-gate 	branch_common(env, 0, 2, 0);
328*7c478bd9Sstevel@tonic-gate }
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate void
331*7c478bd9Sstevel@tonic-gate load_file(fcode_env_t *env)
332*7c478bd9Sstevel@tonic-gate {
333*7c478bd9Sstevel@tonic-gate 	int fd;
334*7c478bd9Sstevel@tonic-gate 	int len, n;
335*7c478bd9Sstevel@tonic-gate 	char *name;
336*7c478bd9Sstevel@tonic-gate 	char *buffer;
337*7c478bd9Sstevel@tonic-gate 	struct stat buf;
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate 	CHECK_DEPTH(env, 2, "load-file");
340*7c478bd9Sstevel@tonic-gate 	name = pop_a_string(env, &len);
341*7c478bd9Sstevel@tonic-gate 	log_message(MSG_INFO, "load_file: '%s'\n", name);
342*7c478bd9Sstevel@tonic-gate 	fd = open(name, O_RDONLY);
343*7c478bd9Sstevel@tonic-gate 	if (fd < 0) {
344*7c478bd9Sstevel@tonic-gate 		forth_perror(env, "Can't open '%s'", name);
345*7c478bd9Sstevel@tonic-gate 	}
346*7c478bd9Sstevel@tonic-gate 	fstat(fd, &buf);
347*7c478bd9Sstevel@tonic-gate 	len = buf.st_size;
348*7c478bd9Sstevel@tonic-gate 	buffer = MALLOC(len);
349*7c478bd9Sstevel@tonic-gate 	if (buffer == 0)
350*7c478bd9Sstevel@tonic-gate 		forth_perror(env, "load_file: MALLOC(%d)", len);
351*7c478bd9Sstevel@tonic-gate 
352*7c478bd9Sstevel@tonic-gate 	if ((n = read(fd, buffer, len)) < 0)
353*7c478bd9Sstevel@tonic-gate 		forth_perror(env, "read error '%s'", name);
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	close(fd);
356*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)buffer);
357*7c478bd9Sstevel@tonic-gate 	PUSH(DS, (fstack_t)n);
358*7c478bd9Sstevel@tonic-gate }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate void
361*7c478bd9Sstevel@tonic-gate load(fcode_env_t *env)
362*7c478bd9Sstevel@tonic-gate {
363*7c478bd9Sstevel@tonic-gate 	parse_word(env);
364*7c478bd9Sstevel@tonic-gate 	if (TOS > 0)
365*7c478bd9Sstevel@tonic-gate 		load_file(env);
366*7c478bd9Sstevel@tonic-gate }
367*7c478bd9Sstevel@tonic-gate 
368*7c478bd9Sstevel@tonic-gate void
369*7c478bd9Sstevel@tonic-gate fevaluate(fcode_env_t *env)
370*7c478bd9Sstevel@tonic-gate {
371*7c478bd9Sstevel@tonic-gate 	char *buffer;
372*7c478bd9Sstevel@tonic-gate 	int bytes, len;
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate 	two_dup(env);
375*7c478bd9Sstevel@tonic-gate 	buffer = pop_a_string(env, &len);
376*7c478bd9Sstevel@tonic-gate 	for (bytes = 0; bytes < len; bytes++) {
377*7c478bd9Sstevel@tonic-gate 		if ((buffer[bytes] == '\n') || (buffer[bytes] == '\r'))
378*7c478bd9Sstevel@tonic-gate 			buffer[bytes] = ' ';
379*7c478bd9Sstevel@tonic-gate 	}
380*7c478bd9Sstevel@tonic-gate 	evaluate(env);
381*7c478bd9Sstevel@tonic-gate }
382*7c478bd9Sstevel@tonic-gate 
383*7c478bd9Sstevel@tonic-gate void
384*7c478bd9Sstevel@tonic-gate fload(fcode_env_t *env)
385*7c478bd9Sstevel@tonic-gate {
386*7c478bd9Sstevel@tonic-gate 	char *buffer;
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 	load(env);
389*7c478bd9Sstevel@tonic-gate 	two_dup(env);
390*7c478bd9Sstevel@tonic-gate 	buffer = pop_a_string(env, NULL);
391*7c478bd9Sstevel@tonic-gate 	fevaluate(env);
392*7c478bd9Sstevel@tonic-gate 	FREE(buffer);
393*7c478bd9Sstevel@tonic-gate }
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate #include <sys/termio.h>
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate #define	MAX_LINE_BUF	20
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate static char *history_lines[MAX_LINE_BUF];
400*7c478bd9Sstevel@tonic-gate int num_lines = 0;
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate static void
403*7c478bd9Sstevel@tonic-gate add_line_to_history(fcode_env_t *env, char *line)
404*7c478bd9Sstevel@tonic-gate {
405*7c478bd9Sstevel@tonic-gate 	int i;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 	if (num_lines < MAX_LINE_BUF)
408*7c478bd9Sstevel@tonic-gate 		history_lines[num_lines++] = STRDUP(line);
409*7c478bd9Sstevel@tonic-gate 	else {
410*7c478bd9Sstevel@tonic-gate 		FREE(history_lines[0]);
411*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < MAX_LINE_BUF - 1; i++)
412*7c478bd9Sstevel@tonic-gate 			history_lines[i] = history_lines[i + 1];
413*7c478bd9Sstevel@tonic-gate 		history_lines[MAX_LINE_BUF - 1] = STRDUP(line);
414*7c478bd9Sstevel@tonic-gate 	}
415*7c478bd9Sstevel@tonic-gate }
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate static void
418*7c478bd9Sstevel@tonic-gate do_emit_chars(fcode_env_t *env, char c, int n)
419*7c478bd9Sstevel@tonic-gate {
420*7c478bd9Sstevel@tonic-gate 	int i;
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++)
423*7c478bd9Sstevel@tonic-gate 		do_emit(env, c);
424*7c478bd9Sstevel@tonic-gate }
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate static void
427*7c478bd9Sstevel@tonic-gate do_emit_str(fcode_env_t *env, char *str, int n)
428*7c478bd9Sstevel@tonic-gate {
429*7c478bd9Sstevel@tonic-gate 	int i;
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < n; i++)
432*7c478bd9Sstevel@tonic-gate 		do_emit(env, *str++);
433*7c478bd9Sstevel@tonic-gate }
434*7c478bd9Sstevel@tonic-gate 
435*7c478bd9Sstevel@tonic-gate static char *
436*7c478bd9Sstevel@tonic-gate find_next_word(char *cursor, char *eol)
437*7c478bd9Sstevel@tonic-gate {
438*7c478bd9Sstevel@tonic-gate 	while (cursor < eol && *cursor != ' ')
439*7c478bd9Sstevel@tonic-gate 		cursor++;
440*7c478bd9Sstevel@tonic-gate 	while (cursor < eol && *cursor == ' ')
441*7c478bd9Sstevel@tonic-gate 		cursor++;
442*7c478bd9Sstevel@tonic-gate 	return (cursor);
443*7c478bd9Sstevel@tonic-gate }
444*7c478bd9Sstevel@tonic-gate 
445*7c478bd9Sstevel@tonic-gate static char *
446*7c478bd9Sstevel@tonic-gate find_prev_word(char *buf, char *cursor)
447*7c478bd9Sstevel@tonic-gate {
448*7c478bd9Sstevel@tonic-gate 	int skippedword = 0;
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 	if (cursor == buf)
451*7c478bd9Sstevel@tonic-gate 		return (cursor);
452*7c478bd9Sstevel@tonic-gate 	cursor--;
453*7c478bd9Sstevel@tonic-gate 	while (cursor > buf && *cursor == ' ')
454*7c478bd9Sstevel@tonic-gate 		cursor--;
455*7c478bd9Sstevel@tonic-gate 	while (cursor > buf && *cursor != ' ') {
456*7c478bd9Sstevel@tonic-gate 		skippedword++;
457*7c478bd9Sstevel@tonic-gate 		cursor--;
458*7c478bd9Sstevel@tonic-gate 	}
459*7c478bd9Sstevel@tonic-gate 	if (skippedword && *cursor == ' ')
460*7c478bd9Sstevel@tonic-gate 		cursor++;
461*7c478bd9Sstevel@tonic-gate 	return (cursor);
462*7c478bd9Sstevel@tonic-gate }
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate void
465*7c478bd9Sstevel@tonic-gate redraw_line(fcode_env_t *env, char *prev_l, char *prev_cursor, char *prev_eol,
466*7c478bd9Sstevel@tonic-gate     char *new_l, char *new_cursor, char *new_eol)
467*7c478bd9Sstevel@tonic-gate {
468*7c478bd9Sstevel@tonic-gate 	int len;
469*7c478bd9Sstevel@tonic-gate 
470*7c478bd9Sstevel@tonic-gate 	/* backup to beginning of previous line */
471*7c478bd9Sstevel@tonic-gate 	do_emit_chars(env, '\b', prev_cursor - prev_l);
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	/* overwrite new line */
474*7c478bd9Sstevel@tonic-gate 	do_emit_str(env, new_l, new_eol - new_l);
475*7c478bd9Sstevel@tonic-gate 
476*7c478bd9Sstevel@tonic-gate 	/* Output blanks to erase previous line chars if old line was longer */
477*7c478bd9Sstevel@tonic-gate 	len = max(0, (prev_eol - prev_l) - (new_eol - new_l));
478*7c478bd9Sstevel@tonic-gate 	do_emit_chars(env, ' ', len);
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate 	/* Backup cursor for new line */
481*7c478bd9Sstevel@tonic-gate 	do_emit_chars(env, '\b', len + (new_eol - new_cursor));
482*7c478bd9Sstevel@tonic-gate }
483*7c478bd9Sstevel@tonic-gate 
484*7c478bd9Sstevel@tonic-gate #define	MAX_LINE_SIZE	256
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate static void
487*7c478bd9Sstevel@tonic-gate do_save_buf(char *save_buf, char *buf, int n)
488*7c478bd9Sstevel@tonic-gate {
489*7c478bd9Sstevel@tonic-gate 	n = max(0, min(n, MAX_LINE_SIZE));
490*7c478bd9Sstevel@tonic-gate 	memcpy(save_buf, buf, n);
491*7c478bd9Sstevel@tonic-gate 	save_buf[n] = '\0';
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate char prompt_string[80] = "ok ";
495*7c478bd9Sstevel@tonic-gate 
496*7c478bd9Sstevel@tonic-gate void
497*7c478bd9Sstevel@tonic-gate read_line(fcode_env_t *env)
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate 	char buf[MAX_LINE_SIZE+1], save_buf[MAX_LINE_SIZE+1];
500*7c478bd9Sstevel@tonic-gate 	char save_line[MAX_LINE_SIZE+1];
501*7c478bd9Sstevel@tonic-gate 	char *p, *cursor, *eol, *tp, *cp;
502*7c478bd9Sstevel@tonic-gate 	fstack_t d;
503*7c478bd9Sstevel@tonic-gate 	int saw_esc = 0, do_quote = 0, i, cur_line, len, my_line, save_cursor;
504*7c478bd9Sstevel@tonic-gate 	struct termio termio, savetermio;
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate 	if (!isatty(fileno(stdin))) {
507*7c478bd9Sstevel@tonic-gate 		fgets(buf, sizeof (buf), stdin);
508*7c478bd9Sstevel@tonic-gate 		push_string(env, buf, strlen(buf));
509*7c478bd9Sstevel@tonic-gate 		return;
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 	printf(prompt_string);
512*7c478bd9Sstevel@tonic-gate 	fflush(stdout);
513*7c478bd9Sstevel@tonic-gate 	ioctl(fileno(stdin), TCGETA, &termio);
514*7c478bd9Sstevel@tonic-gate 	savetermio = termio;
515*7c478bd9Sstevel@tonic-gate 	termio.c_lflag &= ~(ICANON|ECHO|ECHOE|IEXTEN);
516*7c478bd9Sstevel@tonic-gate 	termio.c_cc[VTIME] = 0;
517*7c478bd9Sstevel@tonic-gate 	termio.c_cc[VMIN] = 1;
518*7c478bd9Sstevel@tonic-gate 	ioctl(fileno(stdin), TCSETA, &termio);
519*7c478bd9Sstevel@tonic-gate 	my_line = cur_line = num_lines;
520*7c478bd9Sstevel@tonic-gate 	save_buf[0] = '\0';
521*7c478bd9Sstevel@tonic-gate 	for (cursor = eol = buf; ; ) {
522*7c478bd9Sstevel@tonic-gate 		for (d = FALSE; d == FALSE; d = POP(DS))
523*7c478bd9Sstevel@tonic-gate 			keyquestion(env);
524*7c478bd9Sstevel@tonic-gate 		key(env);
525*7c478bd9Sstevel@tonic-gate 		d = POP(DS);
526*7c478bd9Sstevel@tonic-gate 		if (do_quote) {
527*7c478bd9Sstevel@tonic-gate 			do_quote = 0;
528*7c478bd9Sstevel@tonic-gate 			if ((cursor - buf) < MAX_LINE_SIZE) {
529*7c478bd9Sstevel@tonic-gate 				*cursor++ = d;
530*7c478bd9Sstevel@tonic-gate 				if (cursor > eol)
531*7c478bd9Sstevel@tonic-gate 					eol = cursor;
532*7c478bd9Sstevel@tonic-gate 				do_emit(env, d);
533*7c478bd9Sstevel@tonic-gate 			}
534*7c478bd9Sstevel@tonic-gate 			continue;
535*7c478bd9Sstevel@tonic-gate 		}
536*7c478bd9Sstevel@tonic-gate 		if (saw_esc) {
537*7c478bd9Sstevel@tonic-gate 			saw_esc = 0;
538*7c478bd9Sstevel@tonic-gate 			switch (d) {
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 			default:		/* Ignore anything else */
541*7c478bd9Sstevel@tonic-gate 				continue;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 			case 'b':	/* Move backward one word */
544*7c478bd9Sstevel@tonic-gate 			case 'B':
545*7c478bd9Sstevel@tonic-gate 				tp = find_prev_word(buf, cursor);
546*7c478bd9Sstevel@tonic-gate 				if (tp < cursor) {
547*7c478bd9Sstevel@tonic-gate 					do_emit_chars(env, '\b', cursor - tp);
548*7c478bd9Sstevel@tonic-gate 					cursor = tp;
549*7c478bd9Sstevel@tonic-gate 				}
550*7c478bd9Sstevel@tonic-gate 				continue;
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate 			case 'f':	/* Move forward one word */
553*7c478bd9Sstevel@tonic-gate 			case 'F':
554*7c478bd9Sstevel@tonic-gate 				tp = find_next_word(cursor, eol);
555*7c478bd9Sstevel@tonic-gate 				if (tp > cursor) {
556*7c478bd9Sstevel@tonic-gate 					do_emit_str(env, tp, tp - cursor);
557*7c478bd9Sstevel@tonic-gate 					cursor = tp;
558*7c478bd9Sstevel@tonic-gate 				}
559*7c478bd9Sstevel@tonic-gate 				continue;
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 			case 'h':	/* Erase from beginning of word to */
562*7c478bd9Sstevel@tonic-gate 			case 'H':	/* just before cursor, saving chars */
563*7c478bd9Sstevel@tonic-gate 				d = CTRL('w');
564*7c478bd9Sstevel@tonic-gate 				break;
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 			case 'd':
567*7c478bd9Sstevel@tonic-gate 			case 'D':
568*7c478bd9Sstevel@tonic-gate 				tp = find_next_word(cursor, eol);
569*7c478bd9Sstevel@tonic-gate 				if (tp <= cursor)
570*7c478bd9Sstevel@tonic-gate 					continue;
571*7c478bd9Sstevel@tonic-gate 				len = tp - cursor;
572*7c478bd9Sstevel@tonic-gate 				do_save_buf(save_buf, cursor, len);
573*7c478bd9Sstevel@tonic-gate 				memmove(cursor, tp, eol - tp);
574*7c478bd9Sstevel@tonic-gate 				redraw_line(env, buf, cursor, eol, buf, cursor,
575*7c478bd9Sstevel@tonic-gate 				    eol - len);
576*7c478bd9Sstevel@tonic-gate 				eol -= len;
577*7c478bd9Sstevel@tonic-gate 				continue;
578*7c478bd9Sstevel@tonic-gate 			}
579*7c478bd9Sstevel@tonic-gate 		}
580*7c478bd9Sstevel@tonic-gate 		switch (d) {
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 		default:
583*7c478bd9Sstevel@tonic-gate 			if ((cursor - buf) < MAX_LINE_SIZE) {
584*7c478bd9Sstevel@tonic-gate 				*cursor++ = d;
585*7c478bd9Sstevel@tonic-gate 				if (cursor > eol)
586*7c478bd9Sstevel@tonic-gate 					eol = cursor;
587*7c478bd9Sstevel@tonic-gate 				do_emit(env, d);
588*7c478bd9Sstevel@tonic-gate 			}
589*7c478bd9Sstevel@tonic-gate 			continue;
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 		case CTRL('['):		/* saw esc. character */
592*7c478bd9Sstevel@tonic-gate 			saw_esc = 1;
593*7c478bd9Sstevel@tonic-gate 			continue;
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 		case CTRL('f'):		/* move forward one char */
596*7c478bd9Sstevel@tonic-gate 			if (cursor < eol)
597*7c478bd9Sstevel@tonic-gate 				do_emit(env, *cursor++);
598*7c478bd9Sstevel@tonic-gate 			continue;
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 		case CTRL('a'):		/* cursor to beginning of line */
601*7c478bd9Sstevel@tonic-gate 			do_emit_chars(env, '\b', cursor - buf);
602*7c478bd9Sstevel@tonic-gate 			cursor = buf;
603*7c478bd9Sstevel@tonic-gate 			continue;
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 		case CTRL('e'):		/* cursor to end of line */
606*7c478bd9Sstevel@tonic-gate 			do_emit_str(env, cursor, eol - cursor);
607*7c478bd9Sstevel@tonic-gate 			cursor = eol;
608*7c478bd9Sstevel@tonic-gate 			continue;
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 
611*7c478bd9Sstevel@tonic-gate 		case CTRL('n'):		/* Move to next line in buffer */
612*7c478bd9Sstevel@tonic-gate 		case CTRL('p'):		/* Move to previous line in buffer */
613*7c478bd9Sstevel@tonic-gate 			if (d == CTRL('p')) {
614*7c478bd9Sstevel@tonic-gate 				if (cur_line <= 0)
615*7c478bd9Sstevel@tonic-gate 					continue;
616*7c478bd9Sstevel@tonic-gate 				if (my_line == cur_line) {
617*7c478bd9Sstevel@tonic-gate 					do_save_buf(save_line, buf, eol - buf);
618*7c478bd9Sstevel@tonic-gate 					save_cursor = cursor - buf;
619*7c478bd9Sstevel@tonic-gate 				}
620*7c478bd9Sstevel@tonic-gate 				cur_line--;
621*7c478bd9Sstevel@tonic-gate 			} else {
622*7c478bd9Sstevel@tonic-gate 				if (cur_line >= num_lines)
623*7c478bd9Sstevel@tonic-gate 					continue;
624*7c478bd9Sstevel@tonic-gate 				cur_line++;
625*7c478bd9Sstevel@tonic-gate 				if (cur_line == num_lines) {
626*7c478bd9Sstevel@tonic-gate 					len = strlen(save_line);
627*7c478bd9Sstevel@tonic-gate 					redraw_line(env, buf, cursor, eol,
628*7c478bd9Sstevel@tonic-gate 					    save_line, save_line + save_cursor,
629*7c478bd9Sstevel@tonic-gate 					    save_line + len);
630*7c478bd9Sstevel@tonic-gate 					strcpy(buf, save_line);
631*7c478bd9Sstevel@tonic-gate 					eol = buf + len;
632*7c478bd9Sstevel@tonic-gate 					cursor = buf + save_cursor;
633*7c478bd9Sstevel@tonic-gate 					continue;
634*7c478bd9Sstevel@tonic-gate 				}
635*7c478bd9Sstevel@tonic-gate 			}
636*7c478bd9Sstevel@tonic-gate 			p = history_lines[cur_line];
637*7c478bd9Sstevel@tonic-gate 			len = strlen(p);
638*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, p, p, p + len);
639*7c478bd9Sstevel@tonic-gate 			strcpy(buf, history_lines[cur_line]);
640*7c478bd9Sstevel@tonic-gate 			cursor = buf;
641*7c478bd9Sstevel@tonic-gate 			eol = buf + len;
642*7c478bd9Sstevel@tonic-gate 			continue;
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate 		case CTRL('o'):		/* Insert newline */
645*7c478bd9Sstevel@tonic-gate 			continue;
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 		case CTRL('k'):		/* Erase from cursor to eol, saving */
648*7c478bd9Sstevel@tonic-gate 					/* chars, at eol, joins two lines */
649*7c478bd9Sstevel@tonic-gate 			if (cursor == eol) {
650*7c478bd9Sstevel@tonic-gate 				if (cur_line >= num_lines)
651*7c478bd9Sstevel@tonic-gate 					continue;
652*7c478bd9Sstevel@tonic-gate 				if (cur_line == num_lines - 1) {
653*7c478bd9Sstevel@tonic-gate 					p = save_line;
654*7c478bd9Sstevel@tonic-gate 					len = strlen(save_line);
655*7c478bd9Sstevel@tonic-gate 					num_lines -= 1;
656*7c478bd9Sstevel@tonic-gate 					my_line = num_lines;
657*7c478bd9Sstevel@tonic-gate 				} else {
658*7c478bd9Sstevel@tonic-gate 					cur_line++;
659*7c478bd9Sstevel@tonic-gate 					p = history_lines[cur_line];
660*7c478bd9Sstevel@tonic-gate 					len = strlen(p);
661*7c478bd9Sstevel@tonic-gate 				}
662*7c478bd9Sstevel@tonic-gate 				len = min(len, MAX_LINE_SIZE - (eol - buf));
663*7c478bd9Sstevel@tonic-gate 				memcpy(eol, p, len);
664*7c478bd9Sstevel@tonic-gate 				redraw_line(env, buf, cursor, eol, buf, cursor,
665*7c478bd9Sstevel@tonic-gate 				    eol + len);
666*7c478bd9Sstevel@tonic-gate 				eol += len;
667*7c478bd9Sstevel@tonic-gate 				continue;
668*7c478bd9Sstevel@tonic-gate 			}
669*7c478bd9Sstevel@tonic-gate 			do_save_buf(save_buf, cursor, eol - cursor);
670*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, buf, cursor,
671*7c478bd9Sstevel@tonic-gate 			    cursor);
672*7c478bd9Sstevel@tonic-gate 			eol = cursor;
673*7c478bd9Sstevel@tonic-gate 			continue;
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 		case CTRL('w'):		/* Erase word */
676*7c478bd9Sstevel@tonic-gate 			tp = find_prev_word(buf, cursor);
677*7c478bd9Sstevel@tonic-gate 			if (tp == cursor)
678*7c478bd9Sstevel@tonic-gate 				continue;
679*7c478bd9Sstevel@tonic-gate 			len = cursor - tp;
680*7c478bd9Sstevel@tonic-gate 			do_save_buf(save_buf, tp, len);
681*7c478bd9Sstevel@tonic-gate 			memmove(tp, cursor, eol - cursor);
682*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, buf, cursor - len,
683*7c478bd9Sstevel@tonic-gate 			    eol - len);
684*7c478bd9Sstevel@tonic-gate 			eol -= len;
685*7c478bd9Sstevel@tonic-gate 			cursor -= len;
686*7c478bd9Sstevel@tonic-gate 			continue;
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 		case CTRL('u'):		/* Erases line, saving chars */
689*7c478bd9Sstevel@tonic-gate 			do_save_buf(save_buf, buf, eol - buf);
690*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, buf, buf, buf);
691*7c478bd9Sstevel@tonic-gate 			cursor = buf;
692*7c478bd9Sstevel@tonic-gate 			eol = buf;
693*7c478bd9Sstevel@tonic-gate 			continue;
694*7c478bd9Sstevel@tonic-gate 
695*7c478bd9Sstevel@tonic-gate 		case CTRL('y'):		/* Insert save buffer before cursor */
696*7c478bd9Sstevel@tonic-gate 			len = min(strlen(save_buf),
697*7c478bd9Sstevel@tonic-gate 			    MAX_LINE_SIZE - (eol - buf));
698*7c478bd9Sstevel@tonic-gate 			if (len == 0)
699*7c478bd9Sstevel@tonic-gate 				continue;
700*7c478bd9Sstevel@tonic-gate 			memmove(cursor + len, cursor, eol - cursor);
701*7c478bd9Sstevel@tonic-gate 			memcpy(cursor, save_buf, len);
702*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, buf, cursor + len,
703*7c478bd9Sstevel@tonic-gate 			    eol + len);
704*7c478bd9Sstevel@tonic-gate 			cursor += len;
705*7c478bd9Sstevel@tonic-gate 			eol += len;
706*7c478bd9Sstevel@tonic-gate 			continue;
707*7c478bd9Sstevel@tonic-gate 
708*7c478bd9Sstevel@tonic-gate 		case CTRL('q'):		/* Quote next char */
709*7c478bd9Sstevel@tonic-gate 			do_quote = 1;
710*7c478bd9Sstevel@tonic-gate 			continue;
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 		case CTRL('l'):		/* Display edit buffer */
713*7c478bd9Sstevel@tonic-gate 			do_emit(env, '\n');
714*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < num_lines; i++) {
715*7c478bd9Sstevel@tonic-gate 				do_emit_str(env, history_lines[i],
716*7c478bd9Sstevel@tonic-gate 				    strlen(history_lines[i]));
717*7c478bd9Sstevel@tonic-gate 				do_emit(env, '\n');
718*7c478bd9Sstevel@tonic-gate 			}
719*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, buf, buf, buf, cursor, eol);
720*7c478bd9Sstevel@tonic-gate 			continue;
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 		case CTRL('r'):		/* redraw line */
723*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, buf, cursor, eol);
724*7c478bd9Sstevel@tonic-gate 			continue;
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate 		case CTRL('c'):		/* Exit script editor */
727*7c478bd9Sstevel@tonic-gate 			continue;
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 		case CTRL('b'):		/* backup cursor */
730*7c478bd9Sstevel@tonic-gate 			if (cursor <= buf)
731*7c478bd9Sstevel@tonic-gate 				continue;
732*7c478bd9Sstevel@tonic-gate 			cursor--;
733*7c478bd9Sstevel@tonic-gate 			do_emit(env, '\b');
734*7c478bd9Sstevel@tonic-gate 			continue;
735*7c478bd9Sstevel@tonic-gate 
736*7c478bd9Sstevel@tonic-gate 		case CTRL('h'):		/* Backspace */
737*7c478bd9Sstevel@tonic-gate 		case 0x7f:		/* DEL */
738*7c478bd9Sstevel@tonic-gate 			if (cursor <= buf)
739*7c478bd9Sstevel@tonic-gate 				continue;
740*7c478bd9Sstevel@tonic-gate 			memmove(cursor - 1, cursor, eol - cursor);
741*7c478bd9Sstevel@tonic-gate 			redraw_line(env, buf, cursor, eol, buf, cursor - 1,
742*7c478bd9Sstevel@tonic-gate 			    eol - 1);
743*7c478bd9Sstevel@tonic-gate 			cursor--;
744*7c478bd9Sstevel@tonic-gate 			eol--;
745*7c478bd9Sstevel@tonic-gate 			continue;
746*7c478bd9Sstevel@tonic-gate 
747*7c478bd9Sstevel@tonic-gate 		case '\r':
748*7c478bd9Sstevel@tonic-gate 		case '\n':
749*7c478bd9Sstevel@tonic-gate 			*eol = '\0';
750*7c478bd9Sstevel@tonic-gate 			do_emit(env, '\n');
751*7c478bd9Sstevel@tonic-gate 			break;
752*7c478bd9Sstevel@tonic-gate 		}
753*7c478bd9Sstevel@tonic-gate 		break;
754*7c478bd9Sstevel@tonic-gate 	}
755*7c478bd9Sstevel@tonic-gate 	add_line_to_history(env, buf);
756*7c478bd9Sstevel@tonic-gate 	ioctl(fileno(stdin), TCSETA, &savetermio);
757*7c478bd9Sstevel@tonic-gate 	push_string(env, buf, strlen(buf));
758*7c478bd9Sstevel@tonic-gate }
759*7c478bd9Sstevel@tonic-gate 
760*7c478bd9Sstevel@tonic-gate static void
761*7c478bd9Sstevel@tonic-gate set_prompt(fcode_env_t *env)
762*7c478bd9Sstevel@tonic-gate {
763*7c478bd9Sstevel@tonic-gate 	char *prompt;
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	if ((prompt = parse_a_string(env, NULL)) != NULL)
766*7c478bd9Sstevel@tonic-gate 		strncpy(prompt_string, prompt, sizeof (prompt_string));
767*7c478bd9Sstevel@tonic-gate }
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate #pragma init(_init)
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate static void
772*7c478bd9Sstevel@tonic-gate _init(void)
773*7c478bd9Sstevel@tonic-gate {
774*7c478bd9Sstevel@tonic-gate 	fcode_env_t *env = initial_env;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	ASSERT(env);
777*7c478bd9Sstevel@tonic-gate 	NOTICE;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"if",			do_if);
780*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"else",			do_else);
781*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"then",			do_then);
782*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"case",			bcase);
783*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"of",			do_of);
784*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"endof",		do_else);
785*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"endcase",		bendcase);
786*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"value",		value);
787*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"variable",		variable);
788*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"constant",		constant);
789*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"defer",		defer);
790*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"buffer:",		buffer_colon);
791*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"field",		field);
792*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"struct",		zero);
793*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"to",			action_one);
794*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"d#",			temp_decimal);
795*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"h#",			temp_hex);
796*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"b#",			temp_binary);
797*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"decimal",		do_decimal);
798*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"hex",			do_hex);
799*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"binary",		do_binary);
800*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"clear",		do_clear);
801*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"bye",			bye);
802*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"interact",		do_interact);
803*7c478bd9Sstevel@tonic-gate 	FORTH(IMMEDIATE,	"resume",		do_resume);
804*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"fload",		fload);
805*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"load",			load);
806*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"read-line",		read_line);
807*7c478bd9Sstevel@tonic-gate 	FORTH(0,		"set-prompt",		set_prompt);
808*7c478bd9Sstevel@tonic-gate }
809