/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2000 by Sun Microsystems, Inc. * All rights reserved. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include #include #include #include #include #include void (*semi_ptr)(fcode_env_t *env) = do_semi; void (*does_ptr)(fcode_env_t *env) = install_does; void (*quote_ptr)(fcode_env_t *env) = do_quote; void (*blit_ptr)(fcode_env_t *env) = do_literal; void (*tlit_ptr)(fcode_env_t *env) = do_literal; void (*do_bdo_ptr)(fcode_env_t *env) = do_bdo; void (*do_bqdo_ptr)(fcode_env_t *env) = do_bqdo; void (*create_ptr)(fcode_env_t *env) = do_creator; void (*do_leave_ptr)(fcode_env_t *env) = do_bleave; void (*do_loop_ptr)(fcode_env_t *env) = do_bloop; void (*do_ploop_ptr)(fcode_env_t *env) = do_bploop; void unaligned_lstore(fcode_env_t *); void unaligned_wstore(fcode_env_t *); void unaligned_lfetch(fcode_env_t *); void unaligned_wfetch(fcode_env_t *); /* start with the simple maths functions */ void add(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "+"); d = POP(DS); TOS += d; } void subtract(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "-"); d = POP(DS); TOS -= d; } void multiply(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "*"); d = POP(DS); TOS *= d; } void slash_mod(fcode_env_t *env) { fstack_t d, o, t, rem; int sign = 1; CHECK_DEPTH(env, 2, "/mod"); d = POP(DS); o = t = POP(DS); if (d == 0) { throw_from_fclib(env, 1, "/mod divide by zero"); } sign = ((d ^ t) < 0); if (d < 0) { d = -d; if (sign) { t += (d-1); } } if (t < 0) { if (sign) { t -= (d-1); } t = -t; } t = t / d; if ((o ^ sign) < 0) { rem = (t * d) + o; } else { rem = o - (t*d); } if (sign) { t = -t; } PUSH(DS, rem); PUSH(DS, t); } /* * 'u/mod' Fcode implementation. */ void uslash_mod(fcode_env_t *env) { u_lforth_t u1, u2; CHECK_DEPTH(env, 2, "u/mod"); u2 = POP(DS); u1 = POP(DS); if (u2 == 0) forth_abort(env, "u/mod: divide by zero"); PUSH(DS, u1 % u2); PUSH(DS, u1 / u2); } void divide(fcode_env_t *env) { CHECK_DEPTH(env, 2, "/"); slash_mod(env); nip(env); } void mod(fcode_env_t *env) { CHECK_DEPTH(env, 2, "mod"); slash_mod(env); drop(env); } void and(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "and"); d = POP(DS); TOS &= d; } void or(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "or"); d = POP(DS); TOS |= d; } void xor(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "xor"); d = POP(DS); TOS ^= d; } void invert(fcode_env_t *env) { CHECK_DEPTH(env, 1, "invert"); TOS = ~TOS; } void lshift(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "lshift"); d = POP(DS); TOS = TOS << d; } void rshift(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "rshift"); d = POP(DS); TOS = ((ufstack_t)TOS) >> d; } void rshifta(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, ">>a"); d = POP(DS); TOS = ((s_lforth_t)TOS) >> d; } void negate(fcode_env_t *env) { CHECK_DEPTH(env, 1, "negate"); TOS = -TOS; } void f_abs(fcode_env_t *env) { CHECK_DEPTH(env, 1, "abs"); if (TOS < 0) TOS = -TOS; } void f_min(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "min"); d = POP(DS); if (d < TOS) TOS = d; } void f_max(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "max"); d = POP(DS); if (d > TOS) TOS = d; } void to_r(fcode_env_t *env) { CHECK_DEPTH(env, 1, ">r"); PUSH(RS, POP(DS)); } void from_r(fcode_env_t *env) { CHECK_RETURN_DEPTH(env, 1, "r>"); PUSH(DS, POP(RS)); } void rfetch(fcode_env_t *env) { CHECK_RETURN_DEPTH(env, 1, "r@"); PUSH(DS, *RS); } void f_exit(fcode_env_t *env) { CHECK_RETURN_DEPTH(env, 1, "exit"); IP = (token_t *)POP(RS); } #define COMPARE(cmp, rhs) ((((s_lforth_t)TOS) cmp((s_lforth_t)(rhs))) ? \ TRUE : FALSE) #define UCOMPARE(cmp, rhs) ((((u_lforth_t)TOS) cmp((u_lforth_t)(rhs))) ? \ TRUE : FALSE) #define EQUALS == #define NOTEQUALS != #define LESSTHAN < #define LESSEQUALS <= #define GREATERTHAN > #define GREATEREQUALS >= void zero_equals(fcode_env_t *env) { CHECK_DEPTH(env, 1, "0="); TOS = COMPARE(EQUALS, 0); } void zero_not_equals(fcode_env_t *env) { CHECK_DEPTH(env, 1, "0<>"); TOS = COMPARE(NOTEQUALS, 0); } void zero_less(fcode_env_t *env) { CHECK_DEPTH(env, 1, "0<"); TOS = COMPARE(LESSTHAN, 0); } void zero_less_equals(fcode_env_t *env) { CHECK_DEPTH(env, 1, "0<="); TOS = COMPARE(LESSEQUALS, 0); } void zero_greater(fcode_env_t *env) { CHECK_DEPTH(env, 1, "0>"); TOS = COMPARE(GREATERTHAN, 0); } void zero_greater_equals(fcode_env_t *env) { CHECK_DEPTH(env, 1, "0>="); TOS = COMPARE(GREATEREQUALS, 0); } void less(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "<"); d = POP(DS); TOS = COMPARE(LESSTHAN, d); } void greater(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, ">"); d = POP(DS); TOS = COMPARE(GREATERTHAN, d); } void equals(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "="); d = POP(DS); TOS = COMPARE(EQUALS, d); } void not_equals(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "<>"); d = POP(DS); TOS = COMPARE(NOTEQUALS, d); } void unsign_greater(fcode_env_t *env) { ufstack_t d; CHECK_DEPTH(env, 2, "u>"); d = POP(DS); TOS = UCOMPARE(GREATERTHAN, d); } void unsign_less_equals(fcode_env_t *env) { ufstack_t d; CHECK_DEPTH(env, 2, "u<="); d = POP(DS); TOS = UCOMPARE(LESSEQUALS, d); } void unsign_less(fcode_env_t *env) { ufstack_t d; CHECK_DEPTH(env, 2, "u<"); d = POP(DS); TOS = UCOMPARE(LESSTHAN, d); } void unsign_greater_equals(fcode_env_t *env) { ufstack_t d; CHECK_DEPTH(env, 2, "u>="); d = POP(DS); TOS = UCOMPARE(GREATEREQUALS, d); } void greater_equals(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, ">="); d = POP(DS); TOS = COMPARE(GREATEREQUALS, d); } void less_equals(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "<="); d = POP(DS); TOS = COMPARE(LESSEQUALS, d); } void between(fcode_env_t *env) { s_lforth_t hi, lo; CHECK_DEPTH(env, 3, "between"); hi = (s_lforth_t)POP(DS); lo = (s_lforth_t)POP(DS); TOS = (((s_lforth_t)TOS >= lo) && ((s_lforth_t)TOS <= hi) ? -1 : 0); } void within(fcode_env_t *env) { s_lforth_t lo, hi; CHECK_DEPTH(env, 3, "within"); hi = (s_lforth_t)POP(DS); lo = (s_lforth_t)POP(DS); TOS = ((((s_lforth_t)TOS >= lo) && ((s_lforth_t)TOS < hi)) ? -1 : 0); } void do_literal(fcode_env_t *env) { PUSH(DS, *IP); IP++; } void literal(fcode_env_t *env) { if (env->state) { COMPILE_TOKEN(&blit_ptr); compile_comma(env); } } void do_also(fcode_env_t *env) { token_t *d = *ORDER; if (env->order_depth < (MAX_ORDER - 1)) { env->order[++env->order_depth] = d; debug_msg(DEBUG_CONTEXT, "CONTEXT:also: %d/%p/%p\n", env->order_depth, CONTEXT, env->current); } else log_message(MSG_WARN, "Vocabulary search order exceeds: %d\n", MAX_ORDER); } void do_previous(fcode_env_t *env) { if (env->order_depth) { env->order_depth--; debug_msg(DEBUG_CONTEXT, "CONTEXT:previous: %d/%p/%p\n", env->order_depth, CONTEXT, env->current); } } #ifdef DEBUG void do_order(fcode_env_t *env) { int i; log_message(MSG_INFO, "Order: Depth: %ld: ", env->order_depth); for (i = env->order_depth; i >= 0 && env->order[i]; i--) log_message(MSG_INFO, "%p ", (void *)env->order[i]); log_message(MSG_INFO, "\n"); } #endif void noop(fcode_env_t *env) { /* what a waste of cycles */ } #define FW_PER_FL (sizeof (lforth_t)/sizeof (wforth_t)) void lwsplit(fcode_env_t *env) { union { u_wforth_t l_wf[FW_PER_FL]; u_lforth_t l_lf; } d; int i; CHECK_DEPTH(env, 1, "lwsplit"); d.l_lf = POP(DS); for (i = 0; i < FW_PER_FL; i++) PUSH(DS, d.l_wf[(FW_PER_FL - 1) - i]); } void wljoin(fcode_env_t *env) { union { u_wforth_t l_wf[FW_PER_FL]; u_lforth_t l_lf; } d; int i; CHECK_DEPTH(env, FW_PER_FL, "wljoin"); for (i = 0; i < FW_PER_FL; i++) d.l_wf[i] = POP(DS); PUSH(DS, d.l_lf); } void lwflip(fcode_env_t *env) { union { u_wforth_t l_wf[FW_PER_FL]; u_lforth_t l_lf; } d, c; int i; CHECK_DEPTH(env, 1, "lwflip"); d.l_lf = POP(DS); for (i = 0; i < FW_PER_FL; i++) c.l_wf[i] = d.l_wf[(FW_PER_FL - 1) - i]; PUSH(DS, c.l_lf); } void lbsplit(fcode_env_t *env) { union { uchar_t l_bytes[sizeof (lforth_t)]; u_lforth_t l_lf; } d; int i; CHECK_DEPTH(env, 1, "lbsplit"); d.l_lf = POP(DS); for (i = 0; i < sizeof (lforth_t); i++) PUSH(DS, d.l_bytes[(sizeof (lforth_t) - 1) - i]); } void bljoin(fcode_env_t *env) { union { uchar_t l_bytes[sizeof (lforth_t)]; u_lforth_t l_lf; } d; int i; CHECK_DEPTH(env, sizeof (lforth_t), "bljoin"); for (i = 0; i < sizeof (lforth_t); i++) d.l_bytes[i] = POP(DS); PUSH(DS, (fstack_t)d.l_lf); } void lbflip(fcode_env_t *env) { union { uchar_t l_bytes[sizeof (lforth_t)]; u_lforth_t l_lf; } d, c; int i; CHECK_DEPTH(env, 1, "lbflip"); d.l_lf = POP(DS); for (i = 0; i < sizeof (lforth_t); i++) c.l_bytes[i] = d.l_bytes[(sizeof (lforth_t) - 1) - i]; PUSH(DS, c.l_lf); } void wbsplit(fcode_env_t *env) { union { uchar_t w_bytes[sizeof (wforth_t)]; u_wforth_t w_wf; } d; int i; CHECK_DEPTH(env, 1, "wbsplit"); d.w_wf = POP(DS); for (i = 0; i < sizeof (wforth_t); i++) PUSH(DS, d.w_bytes[(sizeof (wforth_t) - 1) - i]); } void bwjoin(fcode_env_t *env) { union { uchar_t w_bytes[sizeof (wforth_t)]; u_wforth_t w_wf; } d; int i; CHECK_DEPTH(env, sizeof (wforth_t), "bwjoin"); for (i = 0; i < sizeof (wforth_t); i++) d.w_bytes[i] = POP(DS); PUSH(DS, d.w_wf); } void wbflip(fcode_env_t *env) { union { uchar_t w_bytes[sizeof (wforth_t)]; u_wforth_t w_wf; } c, d; int i; CHECK_DEPTH(env, 1, "wbflip"); d.w_wf = POP(DS); for (i = 0; i < sizeof (wforth_t); i++) c.w_bytes[i] = d.w_bytes[(sizeof (wforth_t) - 1) - i]; PUSH(DS, c.w_wf); } void upper_case(fcode_env_t *env) { CHECK_DEPTH(env, 1, "upc"); TOS = toupper(TOS); } void lower_case(fcode_env_t *env) { CHECK_DEPTH(env, 1, "lcc"); TOS = tolower(TOS); } void pack_str(fcode_env_t *env) { char *buf; size_t len; char *str; CHECK_DEPTH(env, 3, "pack"); buf = (char *)POP(DS); len = (size_t)POP(DS); str = (char *)TOS; TOS = (fstack_t)buf; *buf++ = (uchar_t)len; strncpy(buf, str, (len&0xff)); } void count_str(fcode_env_t *env) { uchar_t *len; CHECK_DEPTH(env, 1, "count"); len = (uchar_t *)TOS; TOS += 1; PUSH(DS, *len); } void to_body(fcode_env_t *env) { CHECK_DEPTH(env, 1, ">body"); TOS = (fstack_t)(((acf_t)TOS)+1); } void to_acf(fcode_env_t *env) { CHECK_DEPTH(env, 1, "body>"); TOS = (fstack_t)(((acf_t)TOS)-1); } /* * 'unloop' Fcode implementation, drop 3 loop ctrl elements off return stack. */ static void unloop(fcode_env_t *env) { CHECK_RETURN_DEPTH(env, 3, "unloop"); RS -= 3; } /* * 'um*' Fcode implementation. */ static void um_multiply(fcode_env_t *env) { ufstack_t u1, u2; dforth_t d; CHECK_DEPTH(env, 2, "um*"); u1 = POP(DS); u2 = POP(DS); d = u1 * u2; push_double(env, d); } /* * um/mod (d.lo d.hi u -- urem uquot) */ static void um_slash_mod(fcode_env_t *env) { u_dforth_t d; uint32_t u, urem, uquot; CHECK_DEPTH(env, 3, "um/mod"); u = (uint32_t)POP(DS); d = pop_double(env); urem = d % u; uquot = d / u; PUSH(DS, urem); PUSH(DS, uquot); } /* * d+ (d1.lo d1.hi d2.lo d2.hi -- dsum.lo dsum.hi) */ static void d_plus(fcode_env_t *env) { dforth_t d1, d2; CHECK_DEPTH(env, 4, "d+"); d2 = pop_double(env); d1 = pop_double(env); d1 += d2; push_double(env, d1); } /* * d- (d1.lo d1.hi d2.lo d2.hi -- ddif.lo ddif.hi) */ static void d_minus(fcode_env_t *env) { dforth_t d1, d2; CHECK_DEPTH(env, 4, "d-"); d2 = pop_double(env); d1 = pop_double(env); d1 -= d2; push_double(env, d1); } void set_here(fcode_env_t *env, uchar_t *new_here, char *where) { if (new_here < HERE) { if (strcmp(where, "temporary_execute")) { /* * Other than temporary_execute, no one should set * here backwards. */ log_message(MSG_WARN, "Warning: set_here(%s) back: old:" " %p new: %p\n", where, HERE, new_here); } } if (new_here >= env->base + dict_size) forth_abort(env, "Here (%p) set past dictionary end (%p)", new_here, env->base + dict_size); HERE = new_here; } static void unaligned_store(fcode_env_t *env) { extern void unaligned_xstore(fcode_env_t *); if (sizeof (fstack_t) == sizeof (lforth_t)) unaligned_lstore(env); else unaligned_xstore(env); } static void unaligned_fetch(fcode_env_t *env) { extern void unaligned_xfetch(fcode_env_t *); if (sizeof (fstack_t) == sizeof (lforth_t)) unaligned_lfetch(env); else unaligned_xfetch(env); } void comma(fcode_env_t *env) { CHECK_DEPTH(env, 1, ","); DEBUGF(COMMA, dump_comma(env, ",")); PUSH(DS, (fstack_t)HERE); unaligned_store(env); set_here(env, HERE + sizeof (fstack_t), "comma"); } void lcomma(fcode_env_t *env) { CHECK_DEPTH(env, 1, "l,"); DEBUGF(COMMA, dump_comma(env, "l,")); PUSH(DS, (fstack_t)HERE); unaligned_lstore(env); set_here(env, HERE + sizeof (u_lforth_t), "lcomma"); } void wcomma(fcode_env_t *env) { CHECK_DEPTH(env, 1, "w,"); DEBUGF(COMMA, dump_comma(env, "w,")); PUSH(DS, (fstack_t)HERE); unaligned_wstore(env); set_here(env, HERE + sizeof (u_wforth_t), "wcomma"); } void ccomma(fcode_env_t *env) { CHECK_DEPTH(env, 1, "c,"); DEBUGF(COMMA, dump_comma(env, "c,")); PUSH(DS, (fstack_t)HERE); cstore(env); set_here(env, HERE + sizeof (uchar_t), "ccomma"); } void token_roundup(fcode_env_t *env, char *where) { if ((((token_t)HERE) & (sizeof (token_t) - 1)) != 0) { set_here(env, (uchar_t *)TOKEN_ROUNDUP(HERE), where); } } void compile_comma(fcode_env_t *env) { CHECK_DEPTH(env, 1, "compile,"); DEBUGF(COMMA, dump_comma(env, "compile,")); token_roundup(env, "compile,"); PUSH(DS, (fstack_t)HERE); unaligned_store(env); set_here(env, HERE + sizeof (fstack_t), "compile,"); } void unaligned_lfetch(fcode_env_t *env) { fstack_t addr; int i; CHECK_DEPTH(env, 1, "unaligned-l@"); addr = POP(DS); for (i = 0; i < sizeof (lforth_t); i++, addr++) { PUSH(DS, addr); cfetch(env); } bljoin(env); lbflip(env); } void unaligned_lstore(fcode_env_t *env) { fstack_t addr; int i; CHECK_DEPTH(env, 2, "unaligned-l!"); addr = POP(DS); lbsplit(env); for (i = 0; i < sizeof (lforth_t); i++, addr++) { PUSH(DS, addr); cstore(env); } } void unaligned_wfetch(fcode_env_t *env) { fstack_t addr; int i; CHECK_DEPTH(env, 1, "unaligned-w@"); addr = POP(DS); for (i = 0; i < sizeof (wforth_t); i++, addr++) { PUSH(DS, addr); cfetch(env); } bwjoin(env); wbflip(env); } void unaligned_wstore(fcode_env_t *env) { fstack_t addr; int i; CHECK_DEPTH(env, 2, "unaligned-w!"); addr = POP(DS); wbsplit(env); for (i = 0; i < sizeof (wforth_t); i++, addr++) { PUSH(DS, addr); cstore(env); } } /* * 'lbflips' Fcode implementation. */ static void lbflips(fcode_env_t *env) { fstack_t len, addr; int i; CHECK_DEPTH(env, 2, "lbflips"); len = POP(DS); addr = POP(DS); for (i = 0; i < len; i += sizeof (lforth_t), addr += sizeof (lforth_t)) { PUSH(DS, addr); unaligned_lfetch(env); lbflip(env); PUSH(DS, addr); unaligned_lstore(env); } } /* * 'wbflips' Fcode implementation. */ static void wbflips(fcode_env_t *env) { fstack_t len, addr; int i; CHECK_DEPTH(env, 2, "wbflips"); len = POP(DS); addr = POP(DS); for (i = 0; i < len; i += sizeof (wforth_t), addr += sizeof (wforth_t)) { PUSH(DS, addr); unaligned_wfetch(env); wbflip(env); PUSH(DS, addr); unaligned_wstore(env); } } /* * 'lwflips' Fcode implementation. */ static void lwflips(fcode_env_t *env) { fstack_t len, addr; int i; CHECK_DEPTH(env, 2, "lwflips"); len = POP(DS); addr = POP(DS); for (i = 0; i < len; i += sizeof (lforth_t), addr += sizeof (lforth_t)) { PUSH(DS, addr); unaligned_lfetch(env); lwflip(env); PUSH(DS, addr); unaligned_lstore(env); } } void base(fcode_env_t *env) { PUSH(DS, (fstack_t)&env->num_base); } void dot_s(fcode_env_t *env) { output_data_stack(env, MSG_INFO); } void state(fcode_env_t *env) { PUSH(DS, (fstack_t)&env->state); } int is_digit(char digit, int num_base, fstack_t *dptr) { int error = 0; char base; if (num_base < 10) { base = '0' + (num_base-1); } else { base = 'a' + (num_base - 10); } *dptr = 0; if (digit > '9') digit |= 0x20; if (((digit < '0') || (digit > base)) || ((digit > '9') && (digit < 'a') && (num_base > 10))) error = 1; else { if (digit <= '9') digit -= '0'; else digit = digit - 'a' + 10; *dptr = digit; } return (error); } void dollar_number(fcode_env_t *env) { char *buf; fstack_t value; int len, sign = 1, error = 0; CHECK_DEPTH(env, 2, "$number"); buf = pop_a_string(env, &len); if (*buf == '-') { sign = -1; buf++; len--; } value = 0; while (len-- && !error) { fstack_t digit; if (*buf == '.') { buf++; continue; } value *= env->num_base; error = is_digit(*buf++, env->num_base, &digit); value += digit; } if (error) { PUSH(DS, -1); } else { value *= sign; PUSH(DS, value); PUSH(DS, 0); } } void digit(fcode_env_t *env) { fstack_t base; fstack_t value; CHECK_DEPTH(env, 2, "digit"); base = POP(DS); if (is_digit(TOS, base, &value)) PUSH(DS, 0); else { TOS = value; PUSH(DS, -1); } } void space(fcode_env_t *env) { PUSH(DS, ' '); } void backspace(fcode_env_t *env) { PUSH(DS, '\b'); } void bell(fcode_env_t *env) { PUSH(DS, '\a'); } void fc_bounds(fcode_env_t *env) { fstack_t lo, hi; CHECK_DEPTH(env, 2, "bounds"); lo = DS[-1]; hi = TOS; DS[-1] = lo+hi; TOS = lo; } void here(fcode_env_t *env) { PUSH(DS, (fstack_t)HERE); } void aligned(fcode_env_t *env) { ufstack_t a; CHECK_DEPTH(env, 1, "aligned"); a = (TOS & (sizeof (lforth_t) - 1)); if (a) TOS += (sizeof (lforth_t) - a); } void instance(fcode_env_t *env) { env->instance_mode |= 1; } void semi(fcode_env_t *env) { env->state &= ~1; COMPILE_TOKEN(&semi_ptr); /* * check if we need to supress expose action; * If so this is an internal word and has no link field * or it is a temporary compile */ if (env->state == 0) { expose_acf(env, ""); } if (env->state & 8) { env->state ^= 8; } } void do_create(fcode_env_t *env) { PUSH(DS, (fstack_t)WA); } void drop(fcode_env_t *env) { CHECK_DEPTH(env, 1, "drop"); (void) POP(DS); } void f_dup(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 1, "dup"); d = TOS; PUSH(DS, d); } void over(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "over"); d = DS[-1]; PUSH(DS, d); } void swap(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "swap"); d = DS[-1]; DS[-1] = DS[0]; DS[0] = d; } void rot(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 3, "rot"); d = DS[-2]; DS[-2] = DS[-1]; DS[-1] = TOS; TOS = d; } void minus_rot(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 3, "-rot"); d = TOS; TOS = DS[-1]; DS[-1] = DS[-2]; DS[-2] = d; } void tuck(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "tuck"); d = TOS; swap(env); PUSH(DS, d); } void nip(fcode_env_t *env) { CHECK_DEPTH(env, 2, "nip"); swap(env); drop(env); } void qdup(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 1, "?dup"); d = TOS; if (d) PUSH(DS, d); } void depth(fcode_env_t *env) { fstack_t d; d = DS - env->ds0; PUSH(DS, d); } void pick(fcode_env_t *env) { fstack_t p; CHECK_DEPTH(env, 1, "pick"); p = POP(DS); if (p < 0 || p >= (env->ds - env->ds0)) forth_abort(env, "pick: invalid pick value: %d\n", (int)p); p = DS[-p]; PUSH(DS, p); } void roll(fcode_env_t *env) { fstack_t d, r; CHECK_DEPTH(env, 1, "roll"); r = POP(DS); if (r <= 0 || r >= (env->ds - env->ds0)) forth_abort(env, "roll: invalid roll value: %d\n", (int)r); d = DS[-r]; while (r) { DS[-r] = DS[ -(r-1) ]; r--; } TOS = d; } void two_drop(fcode_env_t *env) { CHECK_DEPTH(env, 2, "2drop"); DS -= 2; } void two_dup(fcode_env_t *env) { CHECK_DEPTH(env, 2, "2dup"); DS[1] = DS[-1]; DS[2] = TOS; DS += 2; } void two_over(fcode_env_t *env) { fstack_t a, b; CHECK_DEPTH(env, 4, "2over"); a = DS[-3]; b = DS[-2]; PUSH(DS, a); PUSH(DS, b); } void two_swap(fcode_env_t *env) { fstack_t a, b; CHECK_DEPTH(env, 4, "2swap"); a = DS[-3]; b = DS[-2]; DS[-3] = DS[-1]; DS[-2] = TOS; DS[-1] = a; TOS = b; } void two_rot(fcode_env_t *env) { fstack_t a, b; CHECK_DEPTH(env, 6, "2rot"); a = DS[-5]; b = DS[-4]; DS[-5] = DS[-3]; DS[-4] = DS[-2]; DS[-3] = DS[-1]; DS[-2] = TOS; DS[-1] = a; TOS = b; } void two_slash(fcode_env_t *env) { CHECK_DEPTH(env, 1, "2/"); TOS = TOS >> 1; } void utwo_slash(fcode_env_t *env) { CHECK_DEPTH(env, 1, "u2/"); TOS = (ufstack_t)((ufstack_t)TOS) >> 1; } void two_times(fcode_env_t *env) { CHECK_DEPTH(env, 1, "2*"); TOS = (ufstack_t)((ufstack_t)TOS) << 1; } void slash_c(fcode_env_t *env) { PUSH(DS, sizeof (char)); } void slash_w(fcode_env_t *env) { PUSH(DS, sizeof (wforth_t)); } void slash_l(fcode_env_t *env) { PUSH(DS, sizeof (lforth_t)); } void slash_n(fcode_env_t *env) { PUSH(DS, sizeof (fstack_t)); } void ca_plus(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "ca+"); d = POP(DS); TOS += d * sizeof (char); } void wa_plus(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "wa+"); d = POP(DS); TOS += d * sizeof (wforth_t); } void la_plus(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "la+"); d = POP(DS); TOS += d * sizeof (lforth_t); } void na_plus(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "na+"); d = POP(DS); TOS += d * sizeof (fstack_t); } void char_plus(fcode_env_t *env) { CHECK_DEPTH(env, 1, "char+"); TOS += sizeof (char); } void wa1_plus(fcode_env_t *env) { CHECK_DEPTH(env, 1, "wa1+"); TOS += sizeof (wforth_t); } void la1_plus(fcode_env_t *env) { CHECK_DEPTH(env, 1, "la1+"); TOS += sizeof (lforth_t); } void cell_plus(fcode_env_t *env) { CHECK_DEPTH(env, 1, "cell+"); TOS += sizeof (fstack_t); } void do_chars(fcode_env_t *env) { CHECK_DEPTH(env, 1, "chars"); } void slash_w_times(fcode_env_t *env) { CHECK_DEPTH(env, 1, "/w*"); TOS *= sizeof (wforth_t); } void slash_l_times(fcode_env_t *env) { CHECK_DEPTH(env, 1, "/l*"); TOS *= sizeof (lforth_t); } void cells(fcode_env_t *env) { CHECK_DEPTH(env, 1, "cells"); TOS *= sizeof (fstack_t); } void do_on(fcode_env_t *env) { variable_t *d; CHECK_DEPTH(env, 1, "on"); d = (variable_t *)POP(DS); *d = -1; } void do_off(fcode_env_t *env) { variable_t *d; CHECK_DEPTH(env, 1, "off"); d = (variable_t *)POP(DS); *d = 0; } void fetch(fcode_env_t *env) { CHECK_DEPTH(env, 1, "@"); TOS = *((variable_t *)TOS); } void lfetch(fcode_env_t *env) { CHECK_DEPTH(env, 1, "l@"); TOS = *((lforth_t *)TOS); } void wfetch(fcode_env_t *env) { CHECK_DEPTH(env, 1, "w@"); TOS = *((wforth_t *)TOS); } void swfetch(fcode_env_t *env) { CHECK_DEPTH(env, 1, " 0) res = 1; else if (res < 0) res = -1; PUSH(DS, res); } void set_temporary_compile(fcode_env_t *env) { if (!env->state) { token_roundup(env, "set_temporary_compile"); PUSH(RS, (fstack_t)HERE); env->state = 3; COMPILE_TOKEN(&do_colon); } } void bmark(fcode_env_t *env) { set_temporary_compile(env); env->level++; PUSH(DS, (fstack_t)HERE); } void temporary_execute(fcode_env_t *env) { uchar_t *saved_here; if ((env->level == 0) && (env->state & 2)) { fstack_t d = POP(RS); semi(env); saved_here = HERE; /* execute the temporary definition */ env->state &= ~2; PUSH(DS, d); execute(env); /* now wind the dictionary back! */ if (saved_here != HERE) { debug_msg(DEBUG_COMMA, "Ignoring set_here in" " temporary_execute\n"); } else set_here(env, (uchar_t *)d, "temporary_execute"); } } void bresolve(fcode_env_t *env) { token_t *prev = (token_t *)POP(DS); env->level--; *prev = (token_t)HERE; temporary_execute(env); } #define BRANCH_IP(ipp) ((token_t *)(*((token_t *)(ipp)))) void do_bbranch(fcode_env_t *env) { IP = BRANCH_IP(IP); } void do_bqbranch(fcode_env_t *env) { fstack_t flag; CHECK_DEPTH(env, 1, "b?branch"); flag = POP(DS); if (flag) { IP++; } else { IP = BRANCH_IP(IP); } } void do_bofbranch(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 2, "bofbranch"); d = POP(DS); if (d == TOS) { (void) POP(DS); IP++; } else { IP = BRANCH_IP(IP); } } void do_bleave(fcode_env_t *env) { CHECK_RETURN_DEPTH(env, 3, "do_bleave"); (void) POP(RS); (void) POP(RS); IP = (token_t *)POP(RS); } void loop_inc(fcode_env_t *env, fstack_t inc) { ufstack_t a; CHECK_RETURN_DEPTH(env, 2, "loop_inc"); /* * Note: end condition is when the sign bit of R[0] changes. */ a = RS[0]; RS[0] += inc; if (((a ^ RS[0]) & SIGN_BIT) == 0) { IP = BRANCH_IP(IP); } else { do_bleave(env); } } void do_bloop(fcode_env_t *env) { loop_inc(env, 1); } void do_bploop(fcode_env_t *env) { fstack_t d; CHECK_DEPTH(env, 1, "+loop"); d = POP(DS); loop_inc(env, d); } void loop_common(fcode_env_t *env, fstack_t ptr) { short offset = get_short(env); COMPILE_TOKEN(ptr); env->level--; compile_comma(env); bresolve(env); } void bloop(fcode_env_t *env) { loop_common(env, (fstack_t)&do_loop_ptr); } void bplusloop(fcode_env_t *env) { loop_common(env, (fstack_t)&do_ploop_ptr); } void common_do(fcode_env_t *env, fstack_t endpt, fstack_t start, fstack_t limit) { ufstack_t i, l; /* * Same computation as OBP, sets up so that loop_inc will terminate * when the sign bit of RS[0] changes. */ i = (start - limit) - SIGN_BIT; l = limit + SIGN_BIT; PUSH(RS, endpt); PUSH(RS, l); PUSH(RS, i); } void do_bdo(fcode_env_t *env) { fstack_t lo, hi; fstack_t endpt; CHECK_DEPTH(env, 2, "bdo"); endpt = (fstack_t)BRANCH_IP(IP); IP++; lo = POP(DS); hi = POP(DS); common_do(env, endpt, lo, hi); } void do_bqdo(fcode_env_t *env) { fstack_t lo, hi; fstack_t endpt; CHECK_DEPTH(env, 2, "b?do"); endpt = (fstack_t)BRANCH_IP(IP); IP++; lo = POP(DS); hi = POP(DS); if (lo == hi) { IP = (token_t *)endpt; } else { common_do(env, endpt, lo, hi); } } void compile_do_common(fcode_env_t *env, fstack_t ptr) { set_temporary_compile(env); COMPILE_TOKEN(ptr); bmark(env); COMPILE_TOKEN(0); bmark(env); } void bdo(fcode_env_t *env) { short offset = (short)get_short(env); compile_do_common(env, (fstack_t)&do_bdo_ptr); } void bqdo(fcode_env_t *env) { short offset = (short)get_short(env); compile_do_common(env, (fstack_t)&do_bqdo_ptr); } void loop_i(fcode_env_t *env) { fstack_t i; CHECK_RETURN_DEPTH(env, 2, "i"); i = RS[0] + RS[-1]; PUSH(DS, i); } void loop_j(fcode_env_t *env) { fstack_t j; CHECK_RETURN_DEPTH(env, 5, "j"); j = RS[-3] + RS[-4]; PUSH(DS, j); } void bleave(fcode_env_t *env) { if (env->state) { COMPILE_TOKEN(&do_leave_ptr); } } void push_string(fcode_env_t *env, char *str, int len) { #define NSTRINGS 16 static int string_count = 0; static int buflen[NSTRINGS]; static char *buffer[NSTRINGS]; char *dest; if (!len) { PUSH(DS, 0); PUSH(DS, 0); return; } if (len != buflen[string_count]) { if (buffer[string_count]) FREE(buffer[string_count]); buffer[ string_count ] = (char *)MALLOC(len+1); buflen[ string_count ] = len; } dest = buffer[ string_count++ ]; string_count = string_count%NSTRINGS; memcpy(dest, str, len); *(dest+len) = 0; PUSH(DS, (fstack_t)dest); PUSH(DS, len); #undef NSTRINGS } void parse_word(fcode_env_t *env) { int len = 0; char *next, *dest, *here = ""; if (env->input) { here = env->input->scanptr; while (*here == env->input->separator) here++; next = strchr(here, env->input->separator); if (next) { len = next - here; while (*next == env->input->separator) next++; } else { len = strlen(here); next = here + len; } env->input->scanptr = next; } push_string(env, here, len); } void install_does(fcode_env_t *env) { token_t *dptr; dptr = (token_t *)LINK_TO_ACF(env->lastlink); log_message(MSG_WARN, "install_does: Last acf at: %p\n", (void *)dptr); *dptr = ((token_t)(IP+1)) | 1; } void does(fcode_env_t *env) { token_t *dptr; token_roundup(env, "does"); if (env->state) { COMPILE_TOKEN(&does_ptr); COMPILE_TOKEN(&semi_ptr); } else { dptr = (token_t *)LINK_TO_ACF(env->lastlink); log_message(MSG_WARN, "does: Last acf at: %p\n", (void *)dptr); *dptr = ((token_t)(HERE)) | 1; env->state |= 1; } COMPILE_TOKEN(&do_colon); } void do_current(fcode_env_t *env) { debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CURRENT\n"); PUSH(DS, (fstack_t)&env->current); } void do_context(fcode_env_t *env) { debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CONTEXT\n"); PUSH(DS, (fstack_t)&CONTEXT); } void do_definitions(fcode_env_t *env) { env->current = CONTEXT; debug_msg(DEBUG_CONTEXT, "CONTEXT:definitions: %d/%p/%p\n", env->order_depth, CONTEXT, env->current); } void make_header(fcode_env_t *env, int flags) { int len; char *name; name = parse_a_string(env, &len); header(env, name, len, flags); } void do_creator(fcode_env_t *env) { make_header(env, 0); COMPILE_TOKEN(&do_create); expose_acf(env, ""); } void create(fcode_env_t *env) { if (env->state) { COMPILE_TOKEN(&create_ptr); } else do_creator(env); } void colon(fcode_env_t *env) { make_header(env, 0); env->state |= 1; COMPILE_TOKEN(&do_colon); } void recursive(fcode_env_t *env) { expose_acf(env, ""); } void compile_string(fcode_env_t *env) { int len; uchar_t *str, *tostr; COMPILE_TOKEN("e_ptr); len = POP(DS); str = (uchar_t *)POP(DS); tostr = HERE; *tostr++ = len; while (len--) *tostr++ = *str++; *tostr++ = '\0'; set_here(env, tostr, "compile_string"); token_roundup(env, "compile_string"); } void run_quote(fcode_env_t *env) { char osep; osep = env->input->separator; env->input->separator = '"'; parse_word(env); env->input->separator = osep; if (env->state) { compile_string(env); } } void does_vocabulary(fcode_env_t *env) { CONTEXT = WA; debug_msg(DEBUG_CONTEXT, "CONTEXT:vocabulary: %d/%p/%p\n", env->order_depth, CONTEXT, env->current); } void do_vocab(fcode_env_t *env) { make_header(env, 0); COMPILE_TOKEN(does_vocabulary); PUSH(DS, 0); compile_comma(env); expose_acf(env, ""); } void do_forth(fcode_env_t *env) { CONTEXT = (token_t *)(&env->forth_voc_link); debug_msg(DEBUG_CONTEXT, "CONTEXT:forth: %d/%p/%p\n", env->order_depth, CONTEXT, env->current); } acf_t voc_find(fcode_env_t *env) { token_t *voc; token_t *dptr; char *find_name, *name; voc = (token_t *)POP(DS); find_name = pop_a_string(env, NULL); for (dptr = (token_t *)(*voc); dptr; dptr = (token_t *)(*dptr)) { if ((name = get_name(dptr)) == NULL) continue; if (strcmp(find_name, name) == 0) { debug_msg(DEBUG_VOC_FIND, "%s -> %p\n", find_name, LINK_TO_ACF(dptr)); return (LINK_TO_ACF(dptr)); } } debug_msg(DEBUG_VOC_FIND, "%s not found\n", find_name); return (NULL); } void dollar_find(fcode_env_t *env) { acf_t acf = NULL; int i; CHECK_DEPTH(env, 2, "$find"); for (i = env->order_depth; i >= 0 && env->order[i] && !acf; i--) { two_dup(env); PUSH(DS, (fstack_t)env->order[i]); acf = voc_find(env); } if (acf) { two_drop(env); PUSH(DS, (fstack_t)acf); PUSH(DS, TRUE); } else PUSH(DS, FALSE); } void interpret(fcode_env_t *env) { char *name; parse_word(env); while (TOS) { two_dup(env); dollar_find(env); if (TOS) { flag_t *flags; drop(env); nip(env); nip(env); flags = LINK_TO_FLAGS(ACF_TO_LINK(TOS)); if ((env->state) && ((*flags & IMMEDIATE) == 0)) { /* Compile in references */ compile_comma(env); } else { execute(env); } } else { int bad; drop(env); dollar_number(env); bad = POP(DS); if (bad) { two_dup(env); name = pop_a_string(env, NULL); log_message(MSG_INFO, "%s?\n", name); break; } else { nip(env); nip(env); literal(env); } } parse_word(env); } two_drop(env); } void evaluate(fcode_env_t *env) { input_typ *old_input = env->input; input_typ *eval_bufp = MALLOC(sizeof (input_typ)); CHECK_DEPTH(env, 2, "evaluate"); eval_bufp->separator = ' '; eval_bufp->maxlen = POP(DS); eval_bufp->buffer = (char *)POP(DS); eval_bufp->scanptr = eval_bufp->buffer; env->input = eval_bufp; interpret(env); FREE(eval_bufp); env->input = old_input; } void make_common_access(fcode_env_t *env, char *name, int len, int ncells, int instance_mode, void (*acf_instance)(fcode_env_t *env), void (*acf_static)(fcode_env_t *env), void (*set_action)(fcode_env_t *env, int)) { if (instance_mode && !MYSELF) { system_message(env, "No instance context"); } debug_msg(DEBUG_ACTIONS, "make_common_access:%s '%s', %d\n", (instance_mode ? "instance" : ""), (name ? name : ""), ncells); if (len) header(env, name, len, 0); if (instance_mode) { token_t *dptr; int offset; COMPILE_TOKEN(acf_instance); dptr = alloc_instance_data(env, INIT_DATA, ncells, &offset); debug_msg(DEBUG_ACTIONS, "Data: %p, offset %d\n", (char *)dptr, offset); PUSH(DS, offset); compile_comma(env); while (ncells--) *dptr++ = MYSELF->data[INIT_DATA][offset++] = POP(DS); env->instance_mode = 0; } else { COMPILE_TOKEN(acf_static); while (ncells--) compile_comma(env); } expose_acf(env, name); if (set_action) set_action(env, instance_mode); } void do_constant(fcode_env_t *env) { PUSH(DS, (variable_t)(*WA)); } void do_crash(fcode_env_t *env) { forth_abort(env, "Unitialized defer"); } /* * 'behavior' Fcode retrieve execution behavior for a defer word. */ static void behavior(fcode_env_t *env) { acf_t defer_xt; token_t token; acf_t contents_xt; CHECK_DEPTH(env, 1, "behavior"); defer_xt = (acf_t)POP(DS); token = *defer_xt; contents_xt = (token_t *)(token & ~1); if ((token & 1) == 0 || *contents_xt != (token_t)&do_default_action) forth_abort(env, "behavior: bad xt: %p indir: %x/%p\n", defer_xt, token & 1, *contents_xt); defer_xt++; PUSH(DS, *((variable_t *)defer_xt)); } void fc_abort(fcode_env_t *env, char *type) { forth_abort(env, "%s Fcode '%s' Executed", type, acf_to_name(env, WA - 1)); } void f_abort(fcode_env_t *env) { fc_abort(env, "Abort"); } /* * Fcodes chosen not to support. */ void fc_unimplemented(fcode_env_t *env) { fc_abort(env, "Unimplemented"); } /* * Fcodes that are Obsolete per P1275-1994. */ void fc_obsolete(fcode_env_t *env) { fc_abort(env, "Obsolete"); } /* * Fcodes that are Historical per P1275-1994 */ void fc_historical(fcode_env_t *env) { fc_abort(env, "Historical"); } void catch(fcode_env_t *env) { error_frame *new; CHECK_DEPTH(env, 1, "catch"); new = MALLOC(sizeof (error_frame)); new->ds = DS-1; new->rs = RS; new->myself = MYSELF; new->next = env->catch_frame; new->code = 0; env->catch_frame = new; execute(env); PUSH(DS, new->code); env->catch_frame = new->next; FREE(new); } void throw_from_fclib(fcode_env_t *env, fstack_t errcode, char *fmt, ...) { error_frame *efp; va_list ap; char msg[256]; va_start(ap, fmt); vsprintf(msg, fmt, ap); if (errcode) { env->last_error = errcode; /* * No catch frame set => fatal error */ efp = env->catch_frame; if (!efp) forth_abort(env, "%s: No catch frame", msg); debug_msg(DEBUG_TRACING, "throw_from_fclib: throw: %s\n", msg); /* * Setting IP=0 will force the unwinding of the calls * (see execute) which is how we will return (eventually) * to the test in catch that follows 'execute'. */ DS = efp->ds; RS = efp->rs; MYSELF = efp->myself; IP = 0; efp->code = errcode; } } void throw(fcode_env_t *env) { fstack_t t; CHECK_DEPTH(env, 1, "throw"); t = POP(DS); if (t >= -20 && t <= 20) throw_from_fclib(env, t, "throw Fcode errcode: 0x%x", (int)t); else { if (t) log_message(MSG_ERROR, "throw: errcode: 0x%x\n", (int)t); throw_from_fclib(env, t, "throw Fcode err: %s", (char *)t); } } void tick_literal(fcode_env_t *env) { if (env->state) { COMPILE_TOKEN(&tlit_ptr); compile_comma(env); } } void do_tick(fcode_env_t *env) { parse_word(env); dollar_find(env); invert(env); throw(env); tick_literal(env); } void bracket_tick(fcode_env_t *env) { do_tick(env); } #pragma init(_init) static void _init(void) { fcode_env_t *env = initial_env; NOTICE; ASSERT(env); ANSI(0x019, 0, "i", loop_i); ANSI(0x01a, 0, "j", loop_j); ANSI(0x01d, 0, "execute", execute); ANSI(0x01e, 0, "+", add); ANSI(0x01f, 0, "-", subtract); ANSI(0x020, 0, "*", multiply); ANSI(0x021, 0, "/", divide); ANSI(0x022, 0, "mod", mod); FORTH(0, "/mod", slash_mod); ANSI(0x023, 0, "and", and); ANSI(0x024, 0, "or", or); ANSI(0x025, 0, "xor", xor); ANSI(0x026, 0, "invert", invert); ANSI(0x027, 0, "lshift", lshift); ANSI(0x028, 0, "rshift", rshift); ANSI(0x029, 0, ">>a", rshifta); ANSI(0x02a, 0, "/mod", slash_mod); ANSI(0x02b, 0, "u/mod", uslash_mod); ANSI(0x02c, 0, "negate", negate); ANSI(0x02d, 0, "abs", f_abs); ANSI(0x02e, 0, "min", f_min); ANSI(0x02f, 0, "max", f_max); ANSI(0x030, 0, ">r", to_r); ANSI(0x031, 0, "r>", from_r); ANSI(0x032, 0, "r@", rfetch); ANSI(0x033, 0, "exit", f_exit); ANSI(0x034, 0, "0=", zero_equals); ANSI(0x035, 0, "0<>", zero_not_equals); ANSI(0x036, 0, "0<", zero_less); ANSI(0x037, 0, "0<=", zero_less_equals); ANSI(0x038, 0, "0>", zero_greater); ANSI(0x039, 0, "0>=", zero_greater_equals); ANSI(0x03a, 0, "<", less); ANSI(0x03b, 0, ">", greater); ANSI(0x03c, 0, "=", equals); ANSI(0x03d, 0, "<>", not_equals); ANSI(0x03e, 0, "u>", unsign_greater); ANSI(0x03f, 0, "u<=", unsign_less_equals); ANSI(0x040, 0, "u<", unsign_less); ANSI(0x041, 0, "u>=", unsign_greater_equals); ANSI(0x042, 0, ">=", greater_equals); ANSI(0x043, 0, "<=", less_equals); ANSI(0x044, 0, "between", between); ANSI(0x045, 0, "within", within); ANSI(0x046, 0, "drop", drop); ANSI(0x047, 0, "dup", f_dup); ANSI(0x048, 0, "over", over); ANSI(0x049, 0, "swap", swap); ANSI(0x04a, 0, "rot", rot); ANSI(0x04b, 0, "-rot", minus_rot); ANSI(0x04c, 0, "tuck", tuck); ANSI(0x04d, 0, "nip", nip); ANSI(0x04e, 0, "pick", pick); ANSI(0x04f, 0, "roll", roll); ANSI(0x050, 0, "?dup", qdup); ANSI(0x051, 0, "depth", depth); ANSI(0x052, 0, "2drop", two_drop); ANSI(0x053, 0, "2dup", two_dup); ANSI(0x054, 0, "2over", two_over); ANSI(0x055, 0, "2swap", two_swap); ANSI(0x056, 0, "2rot", two_rot); ANSI(0x057, 0, "2/", two_slash); ANSI(0x058, 0, "u2/", utwo_slash); ANSI(0x059, 0, "2*", two_times); ANSI(0x05a, 0, "/c", slash_c); ANSI(0x05b, 0, "/w", slash_w); ANSI(0x05c, 0, "/l", slash_l); ANSI(0x05d, 0, "/n", slash_n); ANSI(0x05e, 0, "ca+", ca_plus); ANSI(0x05f, 0, "wa+", wa_plus); ANSI(0x060, 0, "la+", la_plus); ANSI(0x061, 0, "na+", na_plus); ANSI(0x062, 0, "char+", char_plus); ANSI(0x063, 0, "wa1+", wa1_plus); ANSI(0x064, 0, "la1+", la1_plus); ANSI(0x065, 0, "cell+", cell_plus); ANSI(0x066, 0, "chars", do_chars); ANSI(0x067, 0, "/w*", slash_w_times); ANSI(0x068, 0, "/l*", slash_l_times); ANSI(0x069, 0, "cells", cells); ANSI(0x06a, 0, "on", do_on); ANSI(0x06b, 0, "off", do_off); ANSI(0x06c, 0, "+!", addstore); ANSI(0x06d, 0, "@", fetch); ANSI(0x06e, 0, "l@", lfetch); ANSI(0x06f, 0, "w@", wfetch); ANSI(0x070, 0, "", to_acf); ANSI(0x086, 0, ">body", to_body); ANSI(0x089, 0, "unloop", unloop); ANSI(0x09f, 0, ".s", dot_s); ANSI(0x0a0, 0, "base", base); FCODE(0x0a1, 0, "convert", fc_historical); ANSI(0x0a2, 0, "$number", dollar_number); ANSI(0x0a3, 0, "digit", digit); ANSI(0x0a9, 0, "bl", space); ANSI(0x0aa, 0, "bs", backspace); ANSI(0x0ab, 0, "bell", bell); ANSI(0x0ac, 0, "bounds", fc_bounds); ANSI(0x0ad, 0, "here", here); ANSI(0x0af, 0, "wbsplit", wbsplit); ANSI(0x0b0, 0, "bwjoin", bwjoin); P1275(0x0cb, 0, "$find", dollar_find); ANSI(0x0d0, 0, "c,", ccomma); ANSI(0x0d1, 0, "w,", wcomma); ANSI(0x0d2, 0, "l,", lcomma); ANSI(0x0d3, 0, ",", comma); ANSI(0x0d4, 0, "um*", um_multiply); ANSI(0x0d5, 0, "um/mod", um_slash_mod); ANSI(0x0d8, 0, "d+", d_plus); ANSI(0x0d9, 0, "d-", d_minus); ANSI(0x0dc, 0, "state", state); ANSI(0x0de, 0, "behavior", behavior); ANSI(0x0dd, 0, "compile,", compile_comma); ANSI(0x216, 0, "abort", f_abort); ANSI(0x217, 0, "catch", catch); ANSI(0x218, 0, "throw", throw); ANSI(0x226, 0, "lwflip", lwflip); ANSI(0x227, 0, "lbflip", lbflip); ANSI(0x228, 0, "lbflips", lbflips); ANSI(0x236, 0, "wbflips", wbflips); ANSI(0x237, 0, "lwflips", lwflips); FORTH(0, "forth", do_forth); FORTH(0, "current", do_current); FORTH(0, "context", do_context); FORTH(0, "definitions", do_definitions); FORTH(0, "vocabulary", do_vocab); FORTH(IMMEDIATE, ":", colon); FORTH(IMMEDIATE, ";", semi); FORTH(IMMEDIATE, "create", create); FORTH(IMMEDIATE, "does>", does); FORTH(IMMEDIATE, "recursive", recursive); FORTH(0, "parse-word", parse_word); FORTH(IMMEDIATE, "\"", run_quote); FORTH(IMMEDIATE, "order", do_order); FORTH(IMMEDIATE, "also", do_also); FORTH(IMMEDIATE, "previous", do_previous); FORTH(IMMEDIATE, "'", do_tick); FORTH(IMMEDIATE, "[']", bracket_tick); FORTH(0, "unaligned-l@", unaligned_lfetch); FORTH(0, "unaligned-l!", unaligned_lstore); FORTH(0, "unaligned-w@", unaligned_wfetch); FORTH(0, "unaligned-w!", unaligned_wstore); }