2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2000 by Sun Microsystems, Inc.
2N/A * All rights reserved.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <unistd.h>
2N/A#include <string.h>
2N/A#include <fcntl.h>
2N/A#include <setjmp.h>
2N/A#include <sys/stat.h>
2N/A
2N/A#include <fcode/private.h>
2N/A#include <fcode/log.h>
2N/A
2N/Avoid (*to_ptr)(fcode_env_t *env) = do_set_action;
2N/Ajmp_buf *jmp_buf_ptr = NULL;
2N/A
2N/Achar *
2N/Aparse_a_string(fcode_env_t *env, int *lenp)
2N/A{
2N/A parse_word(env);
2N/A return (pop_a_string(env, lenp));
2N/A}
2N/A
2N/Avoid
2N/Aconstant(fcode_env_t *env)
2N/A{
2N/A char *name;
2N/A int len;
2N/A
2N/A name = parse_a_string(env, &len);
2N/A env->instance_mode = 0;
2N/A make_common_access(env, name, len, 1, 0,
2N/A &do_constant, &do_constant, NULL);
2N/A}
2N/A
2N/Avoid
2N/Abuffer_colon(fcode_env_t *env)
2N/A{
2N/A char *name;
2N/A int len;
2N/A
2N/A PUSH(DS, 0);
2N/A name = parse_a_string(env, &len);
2N/A make_common_access(env, name, len, 2,
2N/A env->instance_mode, &noop, &noop, &set_buffer_actions);
2N/A}
2N/A
2N/Avoid
2N/Avalue(fcode_env_t *env)
2N/A{
2N/A char *name;
2N/A int len;
2N/A
2N/A name = parse_a_string(env, &len);
2N/A make_common_access(env, name, len, 1,
2N/A env->instance_mode, &noop, &noop, &set_value_actions);
2N/A}
2N/A
2N/Avoid
2N/Avariable(fcode_env_t *env)
2N/A{
2N/A char *name;
2N/A int len;
2N/A
2N/A PUSH(DS, 0);
2N/A name = parse_a_string(env, &len);
2N/A make_common_access(env, name, len, 1,
2N/A env->instance_mode, &instance_variable, &do_create, NULL);
2N/A}
2N/A
2N/Avoid
2N/Adefer(fcode_env_t *env)
2N/A{
2N/A static void (*crash_ptr)(fcode_env_t *env) = do_crash;
2N/A char *name;
2N/A int len;
2N/A
2N/A PUSH(DS, (fstack_t)&crash_ptr);
2N/A name = parse_a_string(env, &len);
2N/A make_common_access(env, name, len, 1,
2N/A env->instance_mode, &noop, &noop, &set_defer_actions);
2N/A}
2N/A
2N/Avoid
2N/Afield(fcode_env_t *env)
2N/A{
2N/A char *name;
2N/A int len;
2N/A
2N/A over(env);
2N/A name = parse_a_string(env, &len);
2N/A make_common_access(env, name, len, 1, 0, &do_field, &do_field, NULL);
2N/A add(env);
2N/A}
2N/A
2N/Avoid
2N/Abye(fcode_env_t *env)
2N/A{
2N/A exit(0);
2N/A}
2N/A
2N/Avoid
2N/Ado_resume(fcode_env_t *env)
2N/A{
2N/A if (env->interactive) env->interactive--;
2N/A COMPLETE_INTERRUPT;
2N/A}
2N/A
2N/A/*
2N/A * In interactive mode, jmp_buf_ptr should be non-null.
2N/A */
2N/Avoid
2N/Areturn_to_interact(fcode_env_t *env)
2N/A{
2N/A if (jmp_buf_ptr)
2N/A longjmp(*jmp_buf_ptr, 1);
2N/A}
2N/A
2N/Avoid
2N/Ado_interact(fcode_env_t *env)
2N/A{
2N/A int level;
2N/A jmp_buf jmp_env;
2N/A jmp_buf *ojmp_ptr;
2N/A error_frame new;
2N/A input_typ *old_input = env->input;
2N/A
2N/A log_message(MSG_INFO, "Type resume to return\n");
2N/A env->interactive++;
2N/A level = env->interactive;
2N/A
2N/A ojmp_ptr = jmp_buf_ptr;
2N/A jmp_buf_ptr = &jmp_env;
2N/A env->input->separator = ' ';
2N/A env->input->maxlen = 256;
2N/A env->input->buffer = MALLOC(env->input->maxlen);
2N/A env->input->scanptr = env->input->buffer;
2N/A
2N/A if (setjmp(jmp_env)) {
2N/A if (in_forth_abort > 1) {
2N/A RS = env->rs0;
2N/A DS = env->ds0;
2N/A MYSELF = 0;
2N/A IP = 0;
2N/A env->input = old_input;
2N/A env->order_depth = 0;
2N/A } else {
2N/A RS = new.rs;
2N/A DS = new.ds;
2N/A MYSELF = new.myself;
2N/A IP = new.ip;
2N/A env->input = old_input;
2N/A }
2N/A do_forth(env);
2N/A do_definitions(env);
2N/A in_forth_abort = 0;
2N/A } else {
2N/A new.rs = RS;
2N/A new.ds = DS;
2N/A new.myself = MYSELF;
2N/A new.ip = IP;
2N/A }
2N/A
2N/A while (env->interactive == level) {
2N/A int wlen;
2N/A char *p;
2N/A
2N/A DEBUGF(SHOW_RS, output_return_stack(env, 0, MSG_FC_DEBUG));
2N/A DEBUGF(SHOW_STACK, output_data_stack(env, MSG_FC_DEBUG));
2N/A
2N/A#define USE_READLINE
2N/A#ifdef USE_READLINE
2N/A {
2N/A char *line;
2N/A void read_line(fcode_env_t *);
2N/A
2N/A read_line(env);
2N/A if ((line = pop_a_string(env, NULL)) == NULL)
2N/A continue;
2N/A
2N/A env->input->scanptr = strcpy(env->input->buffer, line);
2N/A }
2N/A#else
2N/A if (isatty(fileno(stdin)))
2N/A printf("ok ");
2N/A
2N/A env->input->scanptr = fgets(env->input->buffer,
2N/A env->input->maxlen, stdin);
2N/A
2N/A if (feof(stdin))
2N/A break;
2N/A
2N/A if (env->input->scanptr == NULL)
2N/A continue;
2N/A#endif
2N/A
2N/A if ((p = strpbrk(env->input->scanptr, "\n\r")) != NULL)
2N/A *p = '\0';
2N/A
2N/A if ((wlen = strlen(env->input->scanptr)) == 0)
2N/A continue;
2N/A
2N/A PUSH(DS, (fstack_t)env->input->buffer);
2N/A PUSH(DS, wlen);
2N/A evaluate(env);
2N/A }
2N/A
2N/A jmp_buf_ptr = ojmp_ptr;
2N/A FREE(env->input->buffer);
2N/A}
2N/A
2N/Astatic void
2N/Atemp_base(fcode_env_t *env, fstack_t base)
2N/A{
2N/A fstack_t obase;
2N/A
2N/A obase = env->num_base;
2N/A env->num_base = base;
2N/A parse_word(env);
2N/A evaluate(env);
2N/A env->num_base = obase;
2N/A}
2N/A
2N/Astatic void
2N/Atemp_decimal(fcode_env_t *env)
2N/A{
2N/A temp_base(env, 10);
2N/A}
2N/A
2N/Astatic void
2N/Atemp_hex(fcode_env_t *env)
2N/A{
2N/A temp_base(env, 0x10);
2N/A}
2N/A
2N/Astatic void
2N/Atemp_binary(fcode_env_t *env)
2N/A{
2N/A temp_base(env, 2);
2N/A}
2N/A
2N/Astatic void
2N/Ado_hex(fcode_env_t *env)
2N/A{
2N/A env->num_base = 0x10;
2N/A}
2N/A
2N/Astatic void
2N/Ado_decimal(fcode_env_t *env)
2N/A{
2N/A env->num_base = 10;
2N/A}
2N/A
2N/Astatic void
2N/Ado_binary(fcode_env_t *env)
2N/A{
2N/A env->num_base = 2;
2N/A}
2N/A
2N/Astatic void
2N/Ado_clear(fcode_env_t *env)
2N/A{
2N/A DS = env->ds0;
2N/A}
2N/A
2N/Astatic void
2N/Aaction_one(fcode_env_t *env)
2N/A{
2N/A
2N/A do_tick(env);
2N/A if (env->state) {
2N/A COMPILE_TOKEN(&to_ptr);
2N/A } else {
2N/A PUSH(DS, 1);
2N/A perform_action(env);
2N/A }
2N/A}
2N/A
2N/Avoid
2N/Ado_if(fcode_env_t *env)
2N/A{
2N/A branch_common(env, 1, 1, 0);
2N/A}
2N/A
2N/Avoid
2N/Ado_else(fcode_env_t *env)
2N/A{
2N/A branch_common(env, 1, 0, 1);
2N/A bresolve(env);
2N/A}
2N/A
2N/Avoid
2N/Ado_then(fcode_env_t *env)
2N/A{
2N/A bresolve(env);
2N/A}
2N/A
2N/Avoid
2N/Ado_of(fcode_env_t *env)
2N/A{
2N/A branch_common(env, 0, 2, 0);
2N/A}
2N/A
2N/Avoid
2N/Aload_file(fcode_env_t *env)
2N/A{
2N/A int fd;
2N/A int len, n;
2N/A char *name;
2N/A char *buffer;
2N/A struct stat buf;
2N/A
2N/A CHECK_DEPTH(env, 2, "load-file");
2N/A name = pop_a_string(env, &len);
2N/A log_message(MSG_INFO, "load_file: '%s'\n", name);
2N/A fd = open(name, O_RDONLY);
2N/A if (fd < 0) {
2N/A forth_perror(env, "Can't open '%s'", name);
2N/A }
2N/A fstat(fd, &buf);
2N/A len = buf.st_size;
2N/A buffer = MALLOC(len);
2N/A if (buffer == 0)
2N/A forth_perror(env, "load_file: MALLOC(%d)", len);
2N/A
2N/A if ((n = read(fd, buffer, len)) < 0)
2N/A forth_perror(env, "read error '%s'", name);
2N/A
2N/A close(fd);
2N/A PUSH(DS, (fstack_t)buffer);
2N/A PUSH(DS, (fstack_t)n);
2N/A}
2N/A
2N/Avoid
2N/Aload(fcode_env_t *env)
2N/A{
2N/A parse_word(env);
2N/A if (TOS > 0)
2N/A load_file(env);
2N/A}
2N/A
2N/Avoid
2N/Afevaluate(fcode_env_t *env)
2N/A{
2N/A char *buffer;
2N/A int bytes, len;
2N/A
2N/A two_dup(env);
2N/A buffer = pop_a_string(env, &len);
2N/A for (bytes = 0; bytes < len; bytes++) {
2N/A if ((buffer[bytes] == '\n') || (buffer[bytes] == '\r'))
2N/A buffer[bytes] = ' ';
2N/A }
2N/A evaluate(env);
2N/A}
2N/A
2N/Avoid
2N/Afload(fcode_env_t *env)
2N/A{
2N/A char *buffer;
2N/A
2N/A load(env);
2N/A two_dup(env);
2N/A buffer = pop_a_string(env, NULL);
2N/A fevaluate(env);
2N/A FREE(buffer);
2N/A}
2N/A
2N/A#include <sys/termio.h>
2N/A
2N/A#define MAX_LINE_BUF 20
2N/A
2N/Astatic char *history_lines[MAX_LINE_BUF];
2N/Aint num_lines = 0;
2N/A
2N/Astatic void
2N/Aadd_line_to_history(fcode_env_t *env, char *line)
2N/A{
2N/A int i;
2N/A
2N/A if (num_lines < MAX_LINE_BUF)
2N/A history_lines[num_lines++] = STRDUP(line);
2N/A else {
2N/A FREE(history_lines[0]);
2N/A for (i = 0; i < MAX_LINE_BUF - 1; i++)
2N/A history_lines[i] = history_lines[i + 1];
2N/A history_lines[MAX_LINE_BUF - 1] = STRDUP(line);
2N/A }
2N/A}
2N/A
2N/Astatic void
2N/Ado_emit_chars(fcode_env_t *env, char c, int n)
2N/A{
2N/A int i;
2N/A
2N/A for (i = 0; i < n; i++)
2N/A do_emit(env, c);
2N/A}
2N/A
2N/Astatic void
2N/Ado_emit_str(fcode_env_t *env, char *str, int n)
2N/A{
2N/A int i;
2N/A
2N/A for (i = 0; i < n; i++)
2N/A do_emit(env, *str++);
2N/A}
2N/A
2N/Astatic char *
2N/Afind_next_word(char *cursor, char *eol)
2N/A{
2N/A while (cursor < eol && *cursor != ' ')
2N/A cursor++;
2N/A while (cursor < eol && *cursor == ' ')
2N/A cursor++;
2N/A return (cursor);
2N/A}
2N/A
2N/Astatic char *
2N/Afind_prev_word(char *buf, char *cursor)
2N/A{
2N/A int skippedword = 0;
2N/A
2N/A if (cursor == buf)
2N/A return (cursor);
2N/A cursor--;
2N/A while (cursor > buf && *cursor == ' ')
2N/A cursor--;
2N/A while (cursor > buf && *cursor != ' ') {
2N/A skippedword++;
2N/A cursor--;
2N/A }
2N/A if (skippedword && *cursor == ' ')
2N/A cursor++;
2N/A return (cursor);
2N/A}
2N/A
2N/Avoid
2N/Aredraw_line(fcode_env_t *env, char *prev_l, char *prev_cursor, char *prev_eol,
2N/A char *new_l, char *new_cursor, char *new_eol)
2N/A{
2N/A int len;
2N/A
2N/A /* backup to beginning of previous line */
2N/A do_emit_chars(env, '\b', prev_cursor - prev_l);
2N/A
2N/A /* overwrite new line */
2N/A do_emit_str(env, new_l, new_eol - new_l);
2N/A
2N/A /* Output blanks to erase previous line chars if old line was longer */
2N/A len = max(0, (prev_eol - prev_l) - (new_eol - new_l));
2N/A do_emit_chars(env, ' ', len);
2N/A
2N/A /* Backup cursor for new line */
2N/A do_emit_chars(env, '\b', len + (new_eol - new_cursor));
2N/A}
2N/A
2N/A#define MAX_LINE_SIZE 256
2N/A
2N/Astatic void
2N/Ado_save_buf(char *save_buf, char *buf, int n)
2N/A{
2N/A n = max(0, min(n, MAX_LINE_SIZE));
2N/A memcpy(save_buf, buf, n);
2N/A save_buf[n] = '\0';
2N/A}
2N/A
2N/Achar prompt_string[80] = "ok ";
2N/A
2N/Avoid
2N/Aread_line(fcode_env_t *env)
2N/A{
2N/A char buf[MAX_LINE_SIZE+1], save_buf[MAX_LINE_SIZE+1];
2N/A char save_line[MAX_LINE_SIZE+1];
2N/A char *p, *cursor, *eol, *tp, *cp;
2N/A fstack_t d;
2N/A int saw_esc = 0, do_quote = 0, i, cur_line, len, my_line, save_cursor;
2N/A struct termio termio, savetermio;
2N/A
2N/A if (!isatty(fileno(stdin))) {
2N/A fgets(buf, sizeof (buf), stdin);
2N/A push_string(env, buf, strlen(buf));
2N/A return;
2N/A }
2N/A printf(prompt_string);
2N/A fflush(stdout);
2N/A ioctl(fileno(stdin), TCGETA, &termio);
2N/A savetermio = termio;
2N/A termio.c_lflag &= ~(ICANON|ECHO|ECHOE|IEXTEN);
2N/A termio.c_cc[VTIME] = 0;
2N/A termio.c_cc[VMIN] = 1;
2N/A ioctl(fileno(stdin), TCSETA, &termio);
2N/A my_line = cur_line = num_lines;
2N/A save_buf[0] = '\0';
2N/A for (cursor = eol = buf; ; ) {
2N/A for (d = FALSE; d == FALSE; d = POP(DS))
2N/A keyquestion(env);
2N/A key(env);
2N/A d = POP(DS);
2N/A if (do_quote) {
2N/A do_quote = 0;
2N/A if ((cursor - buf) < MAX_LINE_SIZE) {
2N/A *cursor++ = d;
2N/A if (cursor > eol)
2N/A eol = cursor;
2N/A do_emit(env, d);
2N/A }
2N/A continue;
2N/A }
2N/A if (saw_esc) {
2N/A saw_esc = 0;
2N/A switch (d) {
2N/A
2N/A default: /* Ignore anything else */
2N/A continue;
2N/A
2N/A case 'b': /* Move backward one word */
2N/A case 'B':
2N/A tp = find_prev_word(buf, cursor);
2N/A if (tp < cursor) {
2N/A do_emit_chars(env, '\b', cursor - tp);
2N/A cursor = tp;
2N/A }
2N/A continue;
2N/A
2N/A case 'f': /* Move forward one word */
2N/A case 'F':
2N/A tp = find_next_word(cursor, eol);
2N/A if (tp > cursor) {
2N/A do_emit_str(env, tp, tp - cursor);
2N/A cursor = tp;
2N/A }
2N/A continue;
2N/A
2N/A case 'h': /* Erase from beginning of word to */
2N/A case 'H': /* just before cursor, saving chars */
2N/A d = CTRL('w');
2N/A break;
2N/A
2N/A case 'd':
2N/A case 'D':
2N/A tp = find_next_word(cursor, eol);
2N/A if (tp <= cursor)
2N/A continue;
2N/A len = tp - cursor;
2N/A do_save_buf(save_buf, cursor, len);
2N/A memmove(cursor, tp, eol - tp);
2N/A redraw_line(env, buf, cursor, eol, buf, cursor,
2N/A eol - len);
2N/A eol -= len;
2N/A continue;
2N/A }
2N/A }
2N/A switch (d) {
2N/A
2N/A default:
2N/A if ((cursor - buf) < MAX_LINE_SIZE) {
2N/A *cursor++ = d;
2N/A if (cursor > eol)
2N/A eol = cursor;
2N/A do_emit(env, d);
2N/A }
2N/A continue;
2N/A
2N/A case CTRL('['): /* saw esc. character */
2N/A saw_esc = 1;
2N/A continue;
2N/A
2N/A case CTRL('f'): /* move forward one char */
2N/A if (cursor < eol)
2N/A do_emit(env, *cursor++);
2N/A continue;
2N/A
2N/A case CTRL('a'): /* cursor to beginning of line */
2N/A do_emit_chars(env, '\b', cursor - buf);
2N/A cursor = buf;
2N/A continue;
2N/A
2N/A case CTRL('e'): /* cursor to end of line */
2N/A do_emit_str(env, cursor, eol - cursor);
2N/A cursor = eol;
2N/A continue;
2N/A
2N/A
2N/A case CTRL('n'): /* Move to next line in buffer */
2N/A case CTRL('p'): /* Move to previous line in buffer */
2N/A if (d == CTRL('p')) {
2N/A if (cur_line <= 0)
2N/A continue;
2N/A if (my_line == cur_line) {
2N/A do_save_buf(save_line, buf, eol - buf);
2N/A save_cursor = cursor - buf;
2N/A }
2N/A cur_line--;
2N/A } else {
2N/A if (cur_line >= num_lines)
2N/A continue;
2N/A cur_line++;
2N/A if (cur_line == num_lines) {
2N/A len = strlen(save_line);
2N/A redraw_line(env, buf, cursor, eol,
2N/A save_line, save_line + save_cursor,
2N/A save_line + len);
2N/A strcpy(buf, save_line);
2N/A eol = buf + len;
2N/A cursor = buf + save_cursor;
2N/A continue;
2N/A }
2N/A }
2N/A p = history_lines[cur_line];
2N/A len = strlen(p);
2N/A redraw_line(env, buf, cursor, eol, p, p, p + len);
2N/A strcpy(buf, history_lines[cur_line]);
2N/A cursor = buf;
2N/A eol = buf + len;
2N/A continue;
2N/A
2N/A case CTRL('o'): /* Insert newline */
2N/A continue;
2N/A
2N/A case CTRL('k'): /* Erase from cursor to eol, saving */
2N/A /* chars, at eol, joins two lines */
2N/A if (cursor == eol) {
2N/A if (cur_line >= num_lines)
2N/A continue;
2N/A if (cur_line == num_lines - 1) {
2N/A p = save_line;
2N/A len = strlen(save_line);
2N/A num_lines -= 1;
2N/A my_line = num_lines;
2N/A } else {
2N/A cur_line++;
2N/A p = history_lines[cur_line];
2N/A len = strlen(p);
2N/A }
2N/A len = min(len, MAX_LINE_SIZE - (eol - buf));
2N/A memcpy(eol, p, len);
2N/A redraw_line(env, buf, cursor, eol, buf, cursor,
2N/A eol + len);
2N/A eol += len;
2N/A continue;
2N/A }
2N/A do_save_buf(save_buf, cursor, eol - cursor);
2N/A redraw_line(env, buf, cursor, eol, buf, cursor,
2N/A cursor);
2N/A eol = cursor;
2N/A continue;
2N/A
2N/A case CTRL('w'): /* Erase word */
2N/A tp = find_prev_word(buf, cursor);
2N/A if (tp == cursor)
2N/A continue;
2N/A len = cursor - tp;
2N/A do_save_buf(save_buf, tp, len);
2N/A memmove(tp, cursor, eol - cursor);
2N/A redraw_line(env, buf, cursor, eol, buf, cursor - len,
2N/A eol - len);
2N/A eol -= len;
2N/A cursor -= len;
2N/A continue;
2N/A
2N/A case CTRL('u'): /* Erases line, saving chars */
2N/A do_save_buf(save_buf, buf, eol - buf);
2N/A redraw_line(env, buf, cursor, eol, buf, buf, buf);
2N/A cursor = buf;
2N/A eol = buf;
2N/A continue;
2N/A
2N/A case CTRL('y'): /* Insert save buffer before cursor */
2N/A len = min(strlen(save_buf),
2N/A MAX_LINE_SIZE - (eol - buf));
2N/A if (len == 0)
2N/A continue;
2N/A memmove(cursor + len, cursor, eol - cursor);
2N/A memcpy(cursor, save_buf, len);
2N/A redraw_line(env, buf, cursor, eol, buf, cursor + len,
2N/A eol + len);
2N/A cursor += len;
2N/A eol += len;
2N/A continue;
2N/A
2N/A case CTRL('q'): /* Quote next char */
2N/A do_quote = 1;
2N/A continue;
2N/A
2N/A case CTRL('l'): /* Display edit buffer */
2N/A do_emit(env, '\n');
2N/A for (i = 0; i < num_lines; i++) {
2N/A do_emit_str(env, history_lines[i],
2N/A strlen(history_lines[i]));
2N/A do_emit(env, '\n');
2N/A }
2N/A redraw_line(env, buf, buf, buf, buf, cursor, eol);
2N/A continue;
2N/A
2N/A case CTRL('r'): /* redraw line */
2N/A redraw_line(env, buf, cursor, eol, buf, cursor, eol);
2N/A continue;
2N/A
2N/A case CTRL('c'): /* Exit script editor */
2N/A continue;
2N/A
2N/A case CTRL('b'): /* backup cursor */
2N/A if (cursor <= buf)
2N/A continue;
2N/A cursor--;
2N/A do_emit(env, '\b');
2N/A continue;
2N/A
2N/A case CTRL('h'): /* Backspace */
2N/A case 0x7f: /* DEL */
2N/A if (cursor <= buf)
2N/A continue;
2N/A memmove(cursor - 1, cursor, eol - cursor);
2N/A redraw_line(env, buf, cursor, eol, buf, cursor - 1,
2N/A eol - 1);
2N/A cursor--;
2N/A eol--;
2N/A continue;
2N/A
2N/A case '\r':
2N/A case '\n':
2N/A *eol = '\0';
2N/A do_emit(env, '\n');
2N/A break;
2N/A }
2N/A break;
2N/A }
2N/A add_line_to_history(env, buf);
2N/A ioctl(fileno(stdin), TCSETA, &savetermio);
2N/A push_string(env, buf, strlen(buf));
2N/A}
2N/A
2N/Astatic void
2N/Aset_prompt(fcode_env_t *env)
2N/A{
2N/A char *prompt;
2N/A
2N/A if ((prompt = parse_a_string(env, NULL)) != NULL)
2N/A strncpy(prompt_string, prompt, sizeof (prompt_string));
2N/A}
2N/A
2N/A#pragma init(_init)
2N/A
2N/Astatic void
2N/A_init(void)
2N/A{
2N/A fcode_env_t *env = initial_env;
2N/A
2N/A ASSERT(env);
2N/A NOTICE;
2N/A
2N/A FORTH(IMMEDIATE, "if", do_if);
2N/A FORTH(IMMEDIATE, "else", do_else);
2N/A FORTH(IMMEDIATE, "then", do_then);
2N/A FORTH(IMMEDIATE, "case", bcase);
2N/A FORTH(IMMEDIATE, "of", do_of);
2N/A FORTH(IMMEDIATE, "endof", do_else);
2N/A FORTH(IMMEDIATE, "endcase", bendcase);
2N/A FORTH(IMMEDIATE, "value", value);
2N/A FORTH(IMMEDIATE, "variable", variable);
2N/A FORTH(IMMEDIATE, "constant", constant);
2N/A FORTH(IMMEDIATE, "defer", defer);
2N/A FORTH(IMMEDIATE, "buffer:", buffer_colon);
2N/A FORTH(IMMEDIATE, "field", field);
2N/A FORTH(IMMEDIATE, "struct", zero);
2N/A FORTH(IMMEDIATE, "to", action_one);
2N/A FORTH(IMMEDIATE, "d#", temp_decimal);
2N/A FORTH(IMMEDIATE, "h#", temp_hex);
2N/A FORTH(IMMEDIATE, "b#", temp_binary);
2N/A FORTH(0, "decimal", do_decimal);
2N/A FORTH(0, "hex", do_hex);
2N/A FORTH(0, "binary", do_binary);
2N/A FORTH(0, "clear", do_clear);
2N/A FORTH(IMMEDIATE, "bye", bye);
2N/A FORTH(0, "interact", do_interact);
2N/A FORTH(IMMEDIATE, "resume", do_resume);
2N/A FORTH(0, "fload", fload);
2N/A FORTH(0, "load", load);
2N/A FORTH(0, "read-line", read_line);
2N/A FORTH(0, "set-prompt", set_prompt);
2N/A}