fm: remove sparc-only modules
[unleashed.git] / usr / src / lib / efcode / engine / forth.c
blob33bd2c37d148af83b4d6aafddebf9b0f9ef13ed0
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <ctype.h>
34 #include <fcode/private.h>
35 #include <fcode/log.h>
37 void (*semi_ptr)(fcode_env_t *env) = do_semi;
38 void (*does_ptr)(fcode_env_t *env) = install_does;
39 void (*quote_ptr)(fcode_env_t *env) = do_quote;
40 void (*blit_ptr)(fcode_env_t *env) = do_literal;
41 void (*tlit_ptr)(fcode_env_t *env) = do_literal;
42 void (*do_bdo_ptr)(fcode_env_t *env) = do_bdo;
43 void (*do_bqdo_ptr)(fcode_env_t *env) = do_bqdo;
44 void (*create_ptr)(fcode_env_t *env) = do_creator;
45 void (*do_leave_ptr)(fcode_env_t *env) = do_bleave;
46 void (*do_loop_ptr)(fcode_env_t *env) = do_bloop;
47 void (*do_ploop_ptr)(fcode_env_t *env) = do_bploop;
49 void unaligned_lstore(fcode_env_t *);
50 void unaligned_wstore(fcode_env_t *);
51 void unaligned_lfetch(fcode_env_t *);
52 void unaligned_wfetch(fcode_env_t *);
54 /* start with the simple maths functions */
57 void
58 add(fcode_env_t *env)
60 fstack_t d;
62 CHECK_DEPTH(env, 2, "+");
63 d = POP(DS);
64 TOS += d;
67 void
68 subtract(fcode_env_t *env)
70 fstack_t d;
72 CHECK_DEPTH(env, 2, "-");
73 d = POP(DS);
74 TOS -= d;
77 void
78 multiply(fcode_env_t *env)
80 fstack_t d;
82 CHECK_DEPTH(env, 2, "*");
83 d = POP(DS);
84 TOS *= d;
87 void
88 slash_mod(fcode_env_t *env)
90 fstack_t d, o, t, rem;
91 int sign = 1;
93 CHECK_DEPTH(env, 2, "/mod");
94 d = POP(DS);
95 o = t = POP(DS);
97 if (d == 0) {
98 throw_from_fclib(env, 1, "/mod divide by zero");
100 sign = ((d ^ t) < 0);
101 if (d < 0) {
102 d = -d;
103 if (sign) {
104 t += (d-1);
107 if (t < 0) {
108 if (sign) {
109 t -= (d-1);
111 t = -t;
113 t = t / d;
114 if ((o ^ sign) < 0) {
115 rem = (t * d) + o;
116 } else {
117 rem = o - (t*d);
119 if (sign) {
120 t = -t;
122 PUSH(DS, rem);
123 PUSH(DS, t);
127 * 'u/mod' Fcode implementation.
129 void
130 uslash_mod(fcode_env_t *env)
132 u_lforth_t u1, u2;
134 CHECK_DEPTH(env, 2, "u/mod");
135 u2 = POP(DS);
136 u1 = POP(DS);
138 if (u2 == 0)
139 forth_abort(env, "u/mod: divide by zero");
140 PUSH(DS, u1 % u2);
141 PUSH(DS, u1 / u2);
144 void
145 divide(fcode_env_t *env)
147 CHECK_DEPTH(env, 2, "/");
148 slash_mod(env);
149 nip(env);
152 void
153 mod(fcode_env_t *env)
155 CHECK_DEPTH(env, 2, "mod");
156 slash_mod(env);
157 drop(env);
160 void
161 and(fcode_env_t *env)
163 fstack_t d;
165 CHECK_DEPTH(env, 2, "and");
166 d = POP(DS);
167 TOS &= d;
170 void
171 or(fcode_env_t *env)
173 fstack_t d;
175 CHECK_DEPTH(env, 2, "or");
176 d = POP(DS);
177 TOS |= d;
180 void
181 xor(fcode_env_t *env)
183 fstack_t d;
185 CHECK_DEPTH(env, 2, "xor");
186 d = POP(DS);
187 TOS ^= d;
190 void
191 invert(fcode_env_t *env)
193 CHECK_DEPTH(env, 1, "invert");
194 TOS = ~TOS;
197 void
198 lshift(fcode_env_t *env)
200 fstack_t d;
202 CHECK_DEPTH(env, 2, "lshift");
203 d = POP(DS);
204 TOS = TOS << d;
207 void
208 rshift(fcode_env_t *env)
210 fstack_t d;
212 CHECK_DEPTH(env, 2, "rshift");
213 d = POP(DS);
214 TOS = ((ufstack_t)TOS) >> d;
217 void
218 rshifta(fcode_env_t *env)
220 fstack_t d;
222 CHECK_DEPTH(env, 2, ">>a");
223 d = POP(DS);
224 TOS = ((s_lforth_t)TOS) >> d;
227 void
228 negate(fcode_env_t *env)
230 CHECK_DEPTH(env, 1, "negate");
231 TOS = -TOS;
234 void
235 f_abs(fcode_env_t *env)
237 CHECK_DEPTH(env, 1, "abs");
238 if (TOS < 0) TOS = -TOS;
241 void
242 f_min(fcode_env_t *env)
244 fstack_t d;
246 CHECK_DEPTH(env, 2, "min");
247 d = POP(DS);
248 if (d < TOS) TOS = d;
251 void
252 f_max(fcode_env_t *env)
254 fstack_t d;
256 CHECK_DEPTH(env, 2, "max");
257 d = POP(DS);
258 if (d > TOS) TOS = d;
261 void
262 to_r(fcode_env_t *env)
264 CHECK_DEPTH(env, 1, ">r");
265 PUSH(RS, POP(DS));
268 void
269 from_r(fcode_env_t *env)
271 CHECK_RETURN_DEPTH(env, 1, "r>");
272 PUSH(DS, POP(RS));
275 void
276 rfetch(fcode_env_t *env)
278 CHECK_RETURN_DEPTH(env, 1, "r@");
279 PUSH(DS, *RS);
282 void
283 f_exit(fcode_env_t *env)
285 CHECK_RETURN_DEPTH(env, 1, "exit");
286 IP = (token_t *)POP(RS);
289 #define COMPARE(cmp, rhs) ((((s_lforth_t)TOS) cmp((s_lforth_t)(rhs))) ? \
290 TRUE : FALSE)
291 #define UCOMPARE(cmp, rhs) ((((u_lforth_t)TOS) cmp((u_lforth_t)(rhs))) ? \
292 TRUE : FALSE)
293 #define EQUALS ==
294 #define NOTEQUALS !=
295 #define LESSTHAN <
296 #define LESSEQUALS <=
297 #define GREATERTHAN >
298 #define GREATEREQUALS >=
300 void
301 zero_equals(fcode_env_t *env)
303 CHECK_DEPTH(env, 1, "0=");
304 TOS = COMPARE(EQUALS, 0);
307 void
308 zero_not_equals(fcode_env_t *env)
310 CHECK_DEPTH(env, 1, "0<>");
311 TOS = COMPARE(NOTEQUALS, 0);
314 void
315 zero_less(fcode_env_t *env)
317 CHECK_DEPTH(env, 1, "0<");
318 TOS = COMPARE(LESSTHAN, 0);
321 void
322 zero_less_equals(fcode_env_t *env)
324 CHECK_DEPTH(env, 1, "0<=");
325 TOS = COMPARE(LESSEQUALS, 0);
328 void
329 zero_greater(fcode_env_t *env)
331 CHECK_DEPTH(env, 1, "0>");
332 TOS = COMPARE(GREATERTHAN, 0);
335 void
336 zero_greater_equals(fcode_env_t *env)
338 CHECK_DEPTH(env, 1, "0>=");
339 TOS = COMPARE(GREATEREQUALS, 0);
342 void
343 less(fcode_env_t *env)
345 fstack_t d;
347 CHECK_DEPTH(env, 2, "<");
348 d = POP(DS);
349 TOS = COMPARE(LESSTHAN, d);
352 void
353 greater(fcode_env_t *env)
355 fstack_t d;
357 CHECK_DEPTH(env, 2, ">");
358 d = POP(DS);
359 TOS = COMPARE(GREATERTHAN, d);
362 void
363 equals(fcode_env_t *env)
365 fstack_t d;
367 CHECK_DEPTH(env, 2, "=");
368 d = POP(DS);
369 TOS = COMPARE(EQUALS, d);
372 void
373 not_equals(fcode_env_t *env)
375 fstack_t d;
377 CHECK_DEPTH(env, 2, "<>");
378 d = POP(DS);
379 TOS = COMPARE(NOTEQUALS, d);
383 void
384 unsign_greater(fcode_env_t *env)
386 ufstack_t d;
388 CHECK_DEPTH(env, 2, "u>");
389 d = POP(DS);
390 TOS = UCOMPARE(GREATERTHAN, d);
393 void
394 unsign_less_equals(fcode_env_t *env)
396 ufstack_t d;
398 CHECK_DEPTH(env, 2, "u<=");
399 d = POP(DS);
400 TOS = UCOMPARE(LESSEQUALS, d);
403 void
404 unsign_less(fcode_env_t *env)
406 ufstack_t d;
408 CHECK_DEPTH(env, 2, "u<");
409 d = POP(DS);
410 TOS = UCOMPARE(LESSTHAN, d);
413 void
414 unsign_greater_equals(fcode_env_t *env)
416 ufstack_t d;
418 CHECK_DEPTH(env, 2, "u>=");
419 d = POP(DS);
420 TOS = UCOMPARE(GREATEREQUALS, d);
423 void
424 greater_equals(fcode_env_t *env)
426 fstack_t d;
428 CHECK_DEPTH(env, 2, ">=");
429 d = POP(DS);
430 TOS = COMPARE(GREATEREQUALS, d);
433 void
434 less_equals(fcode_env_t *env)
436 fstack_t d;
438 CHECK_DEPTH(env, 2, "<=");
439 d = POP(DS);
440 TOS = COMPARE(LESSEQUALS, d);
443 void
444 between(fcode_env_t *env)
446 u_lforth_t hi, lo;
448 CHECK_DEPTH(env, 3, "between");
449 hi = (u_lforth_t)POP(DS);
450 lo = (u_lforth_t)POP(DS);
451 TOS = (((u_lforth_t)TOS >= lo) && ((u_lforth_t)TOS <= hi) ? -1 : 0);
454 void
455 within(fcode_env_t *env)
457 u_lforth_t lo, hi;
459 CHECK_DEPTH(env, 3, "within");
460 hi = (u_lforth_t)POP(DS);
461 lo = (u_lforth_t)POP(DS);
462 TOS = ((((u_lforth_t)TOS >= lo) && ((u_lforth_t)TOS < hi)) ? -1 : 0);
465 void
466 do_literal(fcode_env_t *env)
468 PUSH(DS, *IP);
469 IP++;
472 void
473 literal(fcode_env_t *env)
475 if (env->state) {
476 COMPILE_TOKEN(&blit_ptr);
477 compile_comma(env);
481 void
482 do_also(fcode_env_t *env)
484 token_t *d = *ORDER;
486 if (env->order_depth < (MAX_ORDER - 1)) {
487 env->order[++env->order_depth] = d;
488 debug_msg(DEBUG_CONTEXT, "CONTEXT:also: %d/%p/%p\n",
489 env->order_depth, CONTEXT, env->current);
490 } else
491 log_message(MSG_WARN, "Vocabulary search order exceeds: %d\n",
492 MAX_ORDER);
495 void
496 do_previous(fcode_env_t *env)
498 if (env->order_depth) {
499 env->order_depth--;
500 debug_msg(DEBUG_CONTEXT, "CONTEXT:previous: %d/%p/%p\n",
501 env->order_depth, CONTEXT, env->current);
505 #ifdef DEBUG
506 void
507 do_order(fcode_env_t *env)
509 int i;
511 log_message(MSG_INFO, "Order: Depth: %ld: ", env->order_depth);
512 for (i = env->order_depth; i >= 0 && env->order[i]; i--)
513 log_message(MSG_INFO, "%p ", (void *)env->order[i]);
514 log_message(MSG_INFO, "\n");
516 #endif
518 void
519 noop(fcode_env_t *env)
521 /* what a waste of cycles */
525 #define FW_PER_FL (sizeof (lforth_t)/sizeof (wforth_t))
527 void
528 lwsplit(fcode_env_t *env)
530 union {
531 u_wforth_t l_wf[FW_PER_FL];
532 u_lforth_t l_lf;
533 } d;
534 int i;
536 CHECK_DEPTH(env, 1, "lwsplit");
537 d.l_lf = POP(DS);
538 for (i = 0; i < FW_PER_FL; i++)
539 PUSH(DS, d.l_wf[(FW_PER_FL - 1) - i]);
542 void
543 wljoin(fcode_env_t *env)
545 union {
546 u_wforth_t l_wf[FW_PER_FL];
547 u_lforth_t l_lf;
548 } d;
549 int i;
551 CHECK_DEPTH(env, FW_PER_FL, "wljoin");
552 for (i = 0; i < FW_PER_FL; i++)
553 d.l_wf[i] = POP(DS);
554 PUSH(DS, d.l_lf);
557 void
558 lwflip(fcode_env_t *env)
560 union {
561 u_wforth_t l_wf[FW_PER_FL];
562 u_lforth_t l_lf;
563 } d, c;
564 int i;
566 CHECK_DEPTH(env, 1, "lwflip");
567 d.l_lf = POP(DS);
568 for (i = 0; i < FW_PER_FL; i++)
569 c.l_wf[i] = d.l_wf[(FW_PER_FL - 1) - i];
570 PUSH(DS, c.l_lf);
573 void
574 lbsplit(fcode_env_t *env)
576 union {
577 uchar_t l_bytes[sizeof (lforth_t)];
578 u_lforth_t l_lf;
579 } d;
580 int i;
582 CHECK_DEPTH(env, 1, "lbsplit");
583 d.l_lf = POP(DS);
584 for (i = 0; i < sizeof (lforth_t); i++)
585 PUSH(DS, d.l_bytes[(sizeof (lforth_t) - 1) - i]);
588 void
589 bljoin(fcode_env_t *env)
591 union {
592 uchar_t l_bytes[sizeof (lforth_t)];
593 u_lforth_t l_lf;
594 } d;
595 int i;
597 CHECK_DEPTH(env, sizeof (lforth_t), "bljoin");
598 for (i = 0; i < sizeof (lforth_t); i++)
599 d.l_bytes[i] = POP(DS);
600 PUSH(DS, (fstack_t)d.l_lf);
603 void
604 lbflip(fcode_env_t *env)
606 union {
607 uchar_t l_bytes[sizeof (lforth_t)];
608 u_lforth_t l_lf;
609 } d, c;
610 int i;
612 CHECK_DEPTH(env, 1, "lbflip");
613 d.l_lf = POP(DS);
614 for (i = 0; i < sizeof (lforth_t); i++)
615 c.l_bytes[i] = d.l_bytes[(sizeof (lforth_t) - 1) - i];
616 PUSH(DS, c.l_lf);
619 void
620 wbsplit(fcode_env_t *env)
622 union {
623 uchar_t w_bytes[sizeof (wforth_t)];
624 u_wforth_t w_wf;
625 } d;
626 int i;
628 CHECK_DEPTH(env, 1, "wbsplit");
629 d.w_wf = POP(DS);
630 for (i = 0; i < sizeof (wforth_t); i++)
631 PUSH(DS, d.w_bytes[(sizeof (wforth_t) - 1) - i]);
634 void
635 bwjoin(fcode_env_t *env)
637 union {
638 uchar_t w_bytes[sizeof (wforth_t)];
639 u_wforth_t w_wf;
640 } d;
641 int i;
643 CHECK_DEPTH(env, sizeof (wforth_t), "bwjoin");
644 for (i = 0; i < sizeof (wforth_t); i++)
645 d.w_bytes[i] = POP(DS);
646 PUSH(DS, d.w_wf);
649 void
650 wbflip(fcode_env_t *env)
652 union {
653 uchar_t w_bytes[sizeof (wforth_t)];
654 u_wforth_t w_wf;
655 } c, d;
656 int i;
658 CHECK_DEPTH(env, 1, "wbflip");
659 d.w_wf = POP(DS);
660 for (i = 0; i < sizeof (wforth_t); i++)
661 c.w_bytes[i] = d.w_bytes[(sizeof (wforth_t) - 1) - i];
662 PUSH(DS, c.w_wf);
665 void
666 upper_case(fcode_env_t *env)
668 CHECK_DEPTH(env, 1, "upc");
669 TOS = toupper(TOS);
672 void
673 lower_case(fcode_env_t *env)
675 CHECK_DEPTH(env, 1, "lcc");
676 TOS = tolower(TOS);
679 void
680 pack_str(fcode_env_t *env)
682 char *buf;
683 size_t len;
684 char *str;
686 CHECK_DEPTH(env, 3, "pack");
687 buf = (char *)POP(DS);
688 len = (size_t)POP(DS);
689 str = (char *)TOS;
690 TOS = (fstack_t)buf;
691 *buf++ = (uchar_t)len;
692 strncpy(buf, str, (len&0xff));
695 void
696 count_str(fcode_env_t *env)
698 uchar_t *len;
700 CHECK_DEPTH(env, 1, "count");
701 len = (uchar_t *)TOS;
702 TOS += 1;
703 PUSH(DS, *len);
706 void
707 to_body(fcode_env_t *env)
709 CHECK_DEPTH(env, 1, ">body");
710 TOS = (fstack_t)(((acf_t)TOS)+1);
713 void
714 to_acf(fcode_env_t *env)
716 CHECK_DEPTH(env, 1, "body>");
717 TOS = (fstack_t)(((acf_t)TOS)-1);
721 * 'unloop' Fcode implementation, drop 3 loop ctrl elements off return stack.
723 static void
724 unloop(fcode_env_t *env)
726 CHECK_RETURN_DEPTH(env, 3, "unloop");
727 RS -= 3;
731 * 'um*' Fcode implementation.
733 static void
734 um_multiply(fcode_env_t *env)
736 ufstack_t u1, u2;
737 dforth_t d;
739 CHECK_DEPTH(env, 2, "um*");
740 u1 = POP(DS);
741 u2 = POP(DS);
742 d = u1 * u2;
743 push_double(env, d);
747 * um/mod (d.lo d.hi u -- urem uquot)
749 static void
750 um_slash_mod(fcode_env_t *env)
752 u_dforth_t d;
753 uint32_t u, urem, uquot;
755 CHECK_DEPTH(env, 3, "um/mod");
756 u = (uint32_t)POP(DS);
757 d = pop_double(env);
758 urem = d % u;
759 uquot = d / u;
760 PUSH(DS, urem);
761 PUSH(DS, uquot);
765 * d+ (d1.lo d1.hi d2.lo d2.hi -- dsum.lo dsum.hi)
767 static void
768 d_plus(fcode_env_t *env)
770 dforth_t d1, d2;
772 CHECK_DEPTH(env, 4, "d+");
773 d2 = pop_double(env);
774 d1 = pop_double(env);
775 d1 += d2;
776 push_double(env, d1);
780 * d- (d1.lo d1.hi d2.lo d2.hi -- ddif.lo ddif.hi)
782 static void
783 d_minus(fcode_env_t *env)
785 dforth_t d1, d2;
787 CHECK_DEPTH(env, 4, "d-");
788 d2 = pop_double(env);
789 d1 = pop_double(env);
790 d1 -= d2;
791 push_double(env, d1);
794 void
795 set_here(fcode_env_t *env, uchar_t *new_here, char *where)
797 if (new_here < HERE) {
798 if (strcmp(where, "temporary_execute")) {
800 * Other than temporary_execute, no one should set
801 * here backwards.
803 log_message(MSG_WARN, "Warning: set_here(%s) back: old:"
804 " %p new: %p\n", where, HERE, new_here);
807 if (new_here >= env->base + dict_size)
808 forth_abort(env, "Here (%p) set past dictionary end (%p)",
809 new_here, env->base + dict_size);
810 HERE = new_here;
813 static void
814 unaligned_store(fcode_env_t *env)
816 extern void unaligned_xstore(fcode_env_t *);
818 if (sizeof (fstack_t) == sizeof (lforth_t))
819 unaligned_lstore(env);
820 else
821 unaligned_xstore(env);
824 static void
825 unaligned_fetch(fcode_env_t *env)
827 extern void unaligned_xfetch(fcode_env_t *);
829 if (sizeof (fstack_t) == sizeof (lforth_t))
830 unaligned_lfetch(env);
831 else
832 unaligned_xfetch(env);
835 void
836 comma(fcode_env_t *env)
838 CHECK_DEPTH(env, 1, ",");
839 DEBUGF(COMMA, dump_comma(env, ","));
840 PUSH(DS, (fstack_t)HERE);
841 unaligned_store(env);
842 set_here(env, HERE + sizeof (fstack_t), "comma");
845 void
846 lcomma(fcode_env_t *env)
848 CHECK_DEPTH(env, 1, "l,");
849 DEBUGF(COMMA, dump_comma(env, "l,"));
850 PUSH(DS, (fstack_t)HERE);
851 unaligned_lstore(env);
852 set_here(env, HERE + sizeof (u_lforth_t), "lcomma");
855 void
856 wcomma(fcode_env_t *env)
858 CHECK_DEPTH(env, 1, "w,");
859 DEBUGF(COMMA, dump_comma(env, "w,"));
860 PUSH(DS, (fstack_t)HERE);
861 unaligned_wstore(env);
862 set_here(env, HERE + sizeof (u_wforth_t), "wcomma");
865 void
866 ccomma(fcode_env_t *env)
868 CHECK_DEPTH(env, 1, "c,");
869 DEBUGF(COMMA, dump_comma(env, "c,"));
870 PUSH(DS, (fstack_t)HERE);
871 cstore(env);
872 set_here(env, HERE + sizeof (uchar_t), "ccomma");
875 void
876 token_roundup(fcode_env_t *env, char *where)
878 if ((((token_t)HERE) & (sizeof (token_t) - 1)) != 0) {
879 set_here(env, (uchar_t *)TOKEN_ROUNDUP(HERE), where);
883 void
884 compile_comma(fcode_env_t *env)
886 CHECK_DEPTH(env, 1, "compile,");
887 DEBUGF(COMMA, dump_comma(env, "compile,"));
888 token_roundup(env, "compile,");
889 PUSH(DS, (fstack_t)HERE);
890 unaligned_store(env);
891 set_here(env, HERE + sizeof (fstack_t), "compile,");
894 void
895 unaligned_lfetch(fcode_env_t *env)
897 fstack_t addr;
898 int i;
900 CHECK_DEPTH(env, 1, "unaligned-l@");
901 addr = POP(DS);
902 for (i = 0; i < sizeof (lforth_t); i++, addr++) {
903 PUSH(DS, addr);
904 cfetch(env);
906 bljoin(env);
907 lbflip(env);
910 void
911 unaligned_lstore(fcode_env_t *env)
913 fstack_t addr;
914 int i;
916 CHECK_DEPTH(env, 2, "unaligned-l!");
917 addr = POP(DS);
918 lbsplit(env);
919 for (i = 0; i < sizeof (lforth_t); i++, addr++) {
920 PUSH(DS, addr);
921 cstore(env);
925 void
926 unaligned_wfetch(fcode_env_t *env)
928 fstack_t addr;
929 int i;
931 CHECK_DEPTH(env, 1, "unaligned-w@");
932 addr = POP(DS);
933 for (i = 0; i < sizeof (wforth_t); i++, addr++) {
934 PUSH(DS, addr);
935 cfetch(env);
937 bwjoin(env);
938 wbflip(env);
941 void
942 unaligned_wstore(fcode_env_t *env)
944 fstack_t addr;
945 int i;
947 CHECK_DEPTH(env, 2, "unaligned-w!");
948 addr = POP(DS);
949 wbsplit(env);
950 for (i = 0; i < sizeof (wforth_t); i++, addr++) {
951 PUSH(DS, addr);
952 cstore(env);
957 * 'lbflips' Fcode implementation.
959 static void
960 lbflips(fcode_env_t *env)
962 fstack_t len, addr;
963 int i;
965 CHECK_DEPTH(env, 2, "lbflips");
966 len = POP(DS);
967 addr = POP(DS);
968 for (i = 0; i < len; i += sizeof (lforth_t),
969 addr += sizeof (lforth_t)) {
970 PUSH(DS, addr);
971 unaligned_lfetch(env);
972 lbflip(env);
973 PUSH(DS, addr);
974 unaligned_lstore(env);
979 * 'wbflips' Fcode implementation.
981 static void
982 wbflips(fcode_env_t *env)
984 fstack_t len, addr;
985 int i;
987 CHECK_DEPTH(env, 2, "wbflips");
988 len = POP(DS);
989 addr = POP(DS);
990 for (i = 0; i < len; i += sizeof (wforth_t),
991 addr += sizeof (wforth_t)) {
992 PUSH(DS, addr);
993 unaligned_wfetch(env);
994 wbflip(env);
995 PUSH(DS, addr);
996 unaligned_wstore(env);
1001 * 'lwflips' Fcode implementation.
1003 static void
1004 lwflips(fcode_env_t *env)
1006 fstack_t len, addr;
1007 int i;
1009 CHECK_DEPTH(env, 2, "lwflips");
1010 len = POP(DS);
1011 addr = POP(DS);
1012 for (i = 0; i < len; i += sizeof (lforth_t),
1013 addr += sizeof (lforth_t)) {
1014 PUSH(DS, addr);
1015 unaligned_lfetch(env);
1016 lwflip(env);
1017 PUSH(DS, addr);
1018 unaligned_lstore(env);
1022 void
1023 base(fcode_env_t *env)
1025 PUSH(DS, (fstack_t)&env->num_base);
1028 void
1029 dot_s(fcode_env_t *env)
1031 output_data_stack(env, MSG_INFO);
1034 void
1035 state(fcode_env_t *env)
1037 PUSH(DS, (fstack_t)&env->state);
1041 is_digit(char digit, int num_base, fstack_t *dptr)
1043 int error = 0;
1044 char base;
1046 if (num_base < 10) {
1047 base = '0' + (num_base-1);
1048 } else {
1049 base = 'a' + (num_base - 10);
1052 *dptr = 0;
1053 if (digit > '9') digit |= 0x20;
1054 if (((digit < '0') || (digit > base)) ||
1055 ((digit > '9') && (digit < 'a') && (num_base > 10)))
1056 error = 1;
1057 else {
1058 if (digit <= '9')
1059 digit -= '0';
1060 else
1061 digit = digit - 'a' + 10;
1062 *dptr = digit;
1064 return (error);
1067 void
1068 dollar_number(fcode_env_t *env)
1070 char *buf;
1071 fstack_t value;
1072 int len, sign = 1, error = 0;
1074 CHECK_DEPTH(env, 2, "$number");
1075 buf = pop_a_string(env, &len);
1076 if (*buf == '-') {
1077 sign = -1;
1078 buf++;
1079 len--;
1081 value = 0;
1082 while (len-- && !error) {
1083 fstack_t digit;
1085 if (*buf == '.') {
1086 buf++;
1087 continue;
1089 value *= env->num_base;
1090 error = is_digit(*buf++, env->num_base, &digit);
1091 value += digit;
1093 if (error) {
1094 PUSH(DS, -1);
1095 } else {
1096 value *= sign;
1097 PUSH(DS, value);
1098 PUSH(DS, 0);
1102 void
1103 digit(fcode_env_t *env)
1105 fstack_t base;
1106 fstack_t value;
1108 CHECK_DEPTH(env, 2, "digit");
1109 base = POP(DS);
1110 if (is_digit(TOS, base, &value))
1111 PUSH(DS, 0);
1112 else {
1113 TOS = value;
1114 PUSH(DS, -1);
1118 void
1119 space(fcode_env_t *env)
1121 PUSH(DS, ' ');
1124 void
1125 backspace(fcode_env_t *env)
1127 PUSH(DS, '\b');
1130 void
1131 bell(fcode_env_t *env)
1133 PUSH(DS, '\a');
1136 void
1137 fc_bounds(fcode_env_t *env)
1139 fstack_t lo, hi;
1141 CHECK_DEPTH(env, 2, "bounds");
1142 lo = DS[-1];
1143 hi = TOS;
1144 DS[-1] = lo+hi;
1145 TOS = lo;
1148 void
1149 here(fcode_env_t *env)
1151 PUSH(DS, (fstack_t)HERE);
1154 void
1155 aligned(fcode_env_t *env)
1157 ufstack_t a;
1159 CHECK_DEPTH(env, 1, "aligned");
1160 a = (TOS & (sizeof (lforth_t) - 1));
1161 if (a)
1162 TOS += (sizeof (lforth_t) - a);
1165 void
1166 instance(fcode_env_t *env)
1168 env->instance_mode |= 1;
1171 void
1172 semi(fcode_env_t *env)
1175 env->state &= ~1;
1176 COMPILE_TOKEN(&semi_ptr);
1179 * check if we need to supress expose action;
1180 * If so this is an internal word and has no link field
1181 * or it is a temporary compile
1184 if (env->state == 0) {
1185 expose_acf(env, "<semi>");
1187 if (env->state & 8) {
1188 env->state ^= 8;
1192 void
1193 do_create(fcode_env_t *env)
1195 PUSH(DS, (fstack_t)WA);
1198 void
1199 drop(fcode_env_t *env)
1201 CHECK_DEPTH(env, 1, "drop");
1202 (void) POP(DS);
1205 void
1206 f_dup(fcode_env_t *env)
1208 fstack_t d;
1210 CHECK_DEPTH(env, 1, "dup");
1211 d = TOS;
1212 PUSH(DS, d);
1215 void
1216 over(fcode_env_t *env)
1218 fstack_t d;
1220 CHECK_DEPTH(env, 2, "over");
1221 d = DS[-1];
1222 PUSH(DS, d);
1225 void
1226 swap(fcode_env_t *env)
1228 fstack_t d;
1230 CHECK_DEPTH(env, 2, "swap");
1231 d = DS[-1];
1232 DS[-1] = DS[0];
1233 DS[0] = d;
1237 void
1238 rot(fcode_env_t *env)
1240 fstack_t d;
1242 CHECK_DEPTH(env, 3, "rot");
1243 d = DS[-2];
1244 DS[-2] = DS[-1];
1245 DS[-1] = TOS;
1246 TOS = d;
1249 void
1250 minus_rot(fcode_env_t *env)
1252 fstack_t d;
1254 CHECK_DEPTH(env, 3, "-rot");
1255 d = TOS;
1256 TOS = DS[-1];
1257 DS[-1] = DS[-2];
1258 DS[-2] = d;
1261 void
1262 tuck(fcode_env_t *env)
1264 fstack_t d;
1266 CHECK_DEPTH(env, 2, "tuck");
1267 d = TOS;
1268 swap(env);
1269 PUSH(DS, d);
1272 void
1273 nip(fcode_env_t *env)
1275 CHECK_DEPTH(env, 2, "nip");
1276 swap(env);
1277 drop(env);
1280 void
1281 qdup(fcode_env_t *env)
1283 fstack_t d;
1285 CHECK_DEPTH(env, 1, "?dup");
1286 d = TOS;
1287 if (d)
1288 PUSH(DS, d);
1291 void
1292 depth(fcode_env_t *env)
1294 fstack_t d;
1296 d = DS - env->ds0;
1297 PUSH(DS, d);
1300 void
1301 pick(fcode_env_t *env)
1303 fstack_t p;
1305 CHECK_DEPTH(env, 1, "pick");
1306 p = POP(DS);
1307 if (p < 0 || p >= (env->ds - env->ds0))
1308 forth_abort(env, "pick: invalid pick value: %d\n", (int)p);
1309 p = DS[-p];
1310 PUSH(DS, p);
1313 void
1314 roll(fcode_env_t *env)
1316 fstack_t d, r;
1318 CHECK_DEPTH(env, 1, "roll");
1319 r = POP(DS);
1320 if (r <= 0 || r >= (env->ds - env->ds0))
1321 forth_abort(env, "roll: invalid roll value: %d\n", (int)r);
1323 d = DS[-r];
1324 while (r) {
1325 DS[-r] = DS[ -(r-1) ];
1326 r--;
1328 TOS = d;
1331 void
1332 two_drop(fcode_env_t *env)
1334 CHECK_DEPTH(env, 2, "2drop");
1335 DS -= 2;
1338 void
1339 two_dup(fcode_env_t *env)
1341 CHECK_DEPTH(env, 2, "2dup");
1342 DS[1] = DS[-1];
1343 DS[2] = TOS;
1344 DS += 2;
1347 void
1348 two_over(fcode_env_t *env)
1350 fstack_t a, b;
1352 CHECK_DEPTH(env, 4, "2over");
1353 a = DS[-3];
1354 b = DS[-2];
1355 PUSH(DS, a);
1356 PUSH(DS, b);
1359 void
1360 two_swap(fcode_env_t *env)
1362 fstack_t a, b;
1364 CHECK_DEPTH(env, 4, "2swap");
1365 a = DS[-3];
1366 b = DS[-2];
1367 DS[-3] = DS[-1];
1368 DS[-2] = TOS;
1369 DS[-1] = a;
1370 TOS = b;
1373 void
1374 two_rot(fcode_env_t *env)
1376 fstack_t a, b;
1378 CHECK_DEPTH(env, 6, "2rot");
1379 a = DS[-5];
1380 b = DS[-4];
1381 DS[-5] = DS[-3];
1382 DS[-4] = DS[-2];
1383 DS[-3] = DS[-1];
1384 DS[-2] = TOS;
1385 DS[-1] = a;
1386 TOS = b;
1389 void
1390 two_slash(fcode_env_t *env)
1392 CHECK_DEPTH(env, 1, "2/");
1393 TOS = TOS >> 1;
1396 void
1397 utwo_slash(fcode_env_t *env)
1399 CHECK_DEPTH(env, 1, "u2/");
1400 TOS = (ufstack_t)((ufstack_t)TOS) >> 1;
1403 void
1404 two_times(fcode_env_t *env)
1406 CHECK_DEPTH(env, 1, "2*");
1407 TOS = (ufstack_t)((ufstack_t)TOS) << 1;
1410 void
1411 slash_c(fcode_env_t *env)
1413 PUSH(DS, sizeof (char));
1416 void
1417 slash_w(fcode_env_t *env)
1419 PUSH(DS, sizeof (wforth_t));
1422 void
1423 slash_l(fcode_env_t *env)
1425 PUSH(DS, sizeof (lforth_t));
1428 void
1429 slash_n(fcode_env_t *env)
1431 PUSH(DS, sizeof (fstack_t));
1434 void
1435 ca_plus(fcode_env_t *env)
1437 fstack_t d;
1439 CHECK_DEPTH(env, 2, "ca+");
1440 d = POP(DS);
1441 TOS += d * sizeof (char);
1444 void
1445 wa_plus(fcode_env_t *env)
1447 fstack_t d;
1449 CHECK_DEPTH(env, 2, "wa+");
1450 d = POP(DS);
1451 TOS += d * sizeof (wforth_t);
1454 void
1455 la_plus(fcode_env_t *env)
1457 fstack_t d;
1459 CHECK_DEPTH(env, 2, "la+");
1460 d = POP(DS);
1461 TOS += d * sizeof (lforth_t);
1464 void
1465 na_plus(fcode_env_t *env)
1467 fstack_t d;
1469 CHECK_DEPTH(env, 2, "na+");
1470 d = POP(DS);
1471 TOS += d * sizeof (fstack_t);
1474 void
1475 char_plus(fcode_env_t *env)
1477 CHECK_DEPTH(env, 1, "char+");
1478 TOS += sizeof (char);
1481 void
1482 wa1_plus(fcode_env_t *env)
1484 CHECK_DEPTH(env, 1, "wa1+");
1485 TOS += sizeof (wforth_t);
1488 void
1489 la1_plus(fcode_env_t *env)
1491 CHECK_DEPTH(env, 1, "la1+");
1492 TOS += sizeof (lforth_t);
1495 void
1496 cell_plus(fcode_env_t *env)
1498 CHECK_DEPTH(env, 1, "cell+");
1499 TOS += sizeof (fstack_t);
1502 void
1503 do_chars(fcode_env_t *env)
1505 CHECK_DEPTH(env, 1, "chars");
1508 void
1509 slash_w_times(fcode_env_t *env)
1511 CHECK_DEPTH(env, 1, "/w*");
1512 TOS *= sizeof (wforth_t);
1515 void
1516 slash_l_times(fcode_env_t *env)
1518 CHECK_DEPTH(env, 1, "/l*");
1519 TOS *= sizeof (lforth_t);
1522 void
1523 cells(fcode_env_t *env)
1525 CHECK_DEPTH(env, 1, "cells");
1526 TOS *= sizeof (fstack_t);
1529 void
1530 do_on(fcode_env_t *env)
1532 variable_t *d;
1534 CHECK_DEPTH(env, 1, "on");
1535 d = (variable_t *)POP(DS);
1536 *d = -1;
1539 void
1540 do_off(fcode_env_t *env)
1542 variable_t *d;
1544 CHECK_DEPTH(env, 1, "off");
1545 d = (variable_t *)POP(DS);
1546 *d = 0;
1549 void
1550 fetch(fcode_env_t *env)
1552 CHECK_DEPTH(env, 1, "@");
1553 TOS = *((variable_t *)TOS);
1556 void
1557 lfetch(fcode_env_t *env)
1559 CHECK_DEPTH(env, 1, "l@");
1560 TOS = *((lforth_t *)TOS);
1563 void
1564 wfetch(fcode_env_t *env)
1566 CHECK_DEPTH(env, 1, "w@");
1567 TOS = *((wforth_t *)TOS);
1570 void
1571 swfetch(fcode_env_t *env)
1573 CHECK_DEPTH(env, 1, "<w@");
1574 TOS = *((s_wforth_t *)TOS);
1577 void
1578 cfetch(fcode_env_t *env)
1580 CHECK_DEPTH(env, 1, "c@");
1581 TOS = *((uchar_t *)TOS);
1584 void
1585 store(fcode_env_t *env)
1587 variable_t *dptr;
1589 CHECK_DEPTH(env, 2, "!");
1590 dptr = (variable_t *)POP(DS);
1591 *dptr = POP(DS);
1594 void
1595 addstore(fcode_env_t *env)
1597 variable_t *dptr;
1599 CHECK_DEPTH(env, 2, "+!");
1600 dptr = (variable_t *)POP(DS);
1601 *dptr = POP(DS) + *dptr;
1604 void
1605 lstore(fcode_env_t *env)
1607 lforth_t *dptr;
1609 CHECK_DEPTH(env, 2, "l!");
1610 dptr = (lforth_t *)POP(DS);
1611 *dptr = (lforth_t)POP(DS);
1614 void
1615 wstore(fcode_env_t *env)
1617 wforth_t *dptr;
1619 CHECK_DEPTH(env, 2, "w!");
1620 dptr = (wforth_t *)POP(DS);
1621 *dptr = (wforth_t)POP(DS);
1624 void
1625 cstore(fcode_env_t *env)
1627 uchar_t *dptr;
1629 CHECK_DEPTH(env, 2, "c!");
1630 dptr = (uchar_t *)POP(DS);
1631 *dptr = (uchar_t)POP(DS);
1634 void
1635 two_fetch(fcode_env_t *env)
1637 variable_t *d;
1639 CHECK_DEPTH(env, 1, "2@");
1640 d = (variable_t *)POP(DS);
1641 PUSH(DS, (fstack_t)(d + 1));
1642 unaligned_fetch(env);
1643 PUSH(DS, (fstack_t)d);
1644 unaligned_fetch(env);
1647 void
1648 two_store(fcode_env_t *env)
1650 variable_t *d;
1652 CHECK_DEPTH(env, 3, "2!");
1653 d = (variable_t *)POP(DS);
1654 PUSH(DS, (fstack_t)d);
1655 unaligned_store(env);
1656 PUSH(DS, (fstack_t)(d + 1));
1657 unaligned_store(env);
1661 * 'move' Fcode reimplemented in fcdriver to check for mapped addresses.
1663 void
1664 fc_move(fcode_env_t *env)
1666 void *dest, *src;
1667 size_t len;
1669 CHECK_DEPTH(env, 3, "move");
1670 len = (size_t)POP(DS);
1671 dest = (void *)POP(DS);
1672 src = (void *)POP(DS);
1674 memmove(dest, src, len);
1677 void
1678 fc_fill(fcode_env_t *env)
1680 void *dest;
1681 uchar_t val;
1682 size_t len;
1684 CHECK_DEPTH(env, 3, "fill");
1685 val = (uchar_t)POP(DS);
1686 len = (size_t)POP(DS);
1687 dest = (void *)POP(DS);
1688 memset(dest, val, len);
1691 void
1692 fc_comp(fcode_env_t *env)
1694 char *str1, *str2;
1695 size_t len;
1696 int res;
1698 CHECK_DEPTH(env, 3, "comp");
1699 len = (size_t)POP(DS);
1700 str1 = (char *)POP(DS);
1701 str2 = (char *)POP(DS);
1702 res = memcmp(str2, str1, len);
1703 if (res > 0)
1704 res = 1;
1705 else if (res < 0)
1706 res = -1;
1707 PUSH(DS, res);
1710 void
1711 set_temporary_compile(fcode_env_t *env)
1713 if (!env->state) {
1714 token_roundup(env, "set_temporary_compile");
1715 PUSH(RS, (fstack_t)HERE);
1716 env->state = 3;
1717 COMPILE_TOKEN(&do_colon);
1721 void
1722 bmark(fcode_env_t *env)
1724 set_temporary_compile(env);
1725 env->level++;
1726 PUSH(DS, (fstack_t)HERE);
1729 void
1730 temporary_execute(fcode_env_t *env)
1732 uchar_t *saved_here;
1734 if ((env->level == 0) && (env->state & 2)) {
1735 fstack_t d = POP(RS);
1737 semi(env);
1739 saved_here = HERE;
1740 /* execute the temporary definition */
1741 env->state &= ~2;
1742 PUSH(DS, d);
1743 execute(env);
1745 /* now wind the dictionary back! */
1746 if (saved_here != HERE) {
1747 debug_msg(DEBUG_COMMA, "Ignoring set_here in"
1748 " temporary_execute\n");
1749 } else
1750 set_here(env, (uchar_t *)d, "temporary_execute");
1754 void
1755 bresolve(fcode_env_t *env)
1757 token_t *prev = (token_t *)POP(DS);
1759 env->level--;
1760 *prev = (token_t)HERE;
1761 temporary_execute(env);
1764 #define BRANCH_IP(ipp) ((token_t *)(*((token_t *)(ipp))))
1766 void
1767 do_bbranch(fcode_env_t *env)
1769 IP = BRANCH_IP(IP);
1772 void
1773 do_bqbranch(fcode_env_t *env)
1775 fstack_t flag;
1777 CHECK_DEPTH(env, 1, "b?branch");
1778 flag = POP(DS);
1779 if (flag) {
1780 IP++;
1781 } else {
1782 IP = BRANCH_IP(IP);
1786 void
1787 do_bofbranch(fcode_env_t *env)
1789 fstack_t d;
1791 CHECK_DEPTH(env, 2, "bofbranch");
1792 d = POP(DS);
1793 if (d == TOS) {
1794 (void) POP(DS);
1795 IP++;
1796 } else {
1797 IP = BRANCH_IP(IP);
1801 void
1802 do_bleave(fcode_env_t *env)
1804 CHECK_RETURN_DEPTH(env, 3, "do_bleave");
1805 (void) POP(RS);
1806 (void) POP(RS);
1807 IP = (token_t *)POP(RS);
1810 void
1811 loop_inc(fcode_env_t *env, fstack_t inc)
1813 ufstack_t a;
1815 CHECK_RETURN_DEPTH(env, 2, "loop_inc");
1818 * Note: end condition is when the sign bit of R[0] changes.
1820 a = RS[0];
1821 RS[0] += inc;
1822 if (((a ^ RS[0]) & SIGN_BIT) == 0) {
1823 IP = BRANCH_IP(IP);
1824 } else {
1825 do_bleave(env);
1829 void
1830 do_bloop(fcode_env_t *env)
1832 loop_inc(env, 1);
1835 void
1836 do_bploop(fcode_env_t *env)
1838 fstack_t d;
1840 CHECK_DEPTH(env, 1, "+loop");
1841 d = POP(DS);
1842 loop_inc(env, d);
1845 void
1846 loop_common(fcode_env_t *env, fstack_t ptr)
1848 short offset = get_short(env);
1850 COMPILE_TOKEN(ptr);
1851 env->level--;
1852 compile_comma(env);
1853 bresolve(env);
1856 void
1857 bloop(fcode_env_t *env)
1859 loop_common(env, (fstack_t)&do_loop_ptr);
1862 void
1863 bplusloop(fcode_env_t *env)
1865 loop_common(env, (fstack_t)&do_ploop_ptr);
1868 void
1869 common_do(fcode_env_t *env, fstack_t endpt, fstack_t start, fstack_t limit)
1871 ufstack_t i, l;
1874 * Same computation as OBP, sets up so that loop_inc will terminate
1875 * when the sign bit of RS[0] changes.
1877 i = (start - limit) - SIGN_BIT;
1878 l = limit + SIGN_BIT;
1879 PUSH(RS, endpt);
1880 PUSH(RS, l);
1881 PUSH(RS, i);
1884 void
1885 do_bdo(fcode_env_t *env)
1887 fstack_t lo, hi;
1888 fstack_t endpt;
1890 CHECK_DEPTH(env, 2, "bdo");
1891 endpt = (fstack_t)BRANCH_IP(IP);
1892 IP++;
1893 lo = POP(DS);
1894 hi = POP(DS);
1895 common_do(env, endpt, lo, hi);
1898 void
1899 do_bqdo(fcode_env_t *env)
1901 fstack_t lo, hi;
1902 fstack_t endpt;
1904 CHECK_DEPTH(env, 2, "b?do");
1905 endpt = (fstack_t)BRANCH_IP(IP);
1906 IP++;
1907 lo = POP(DS);
1908 hi = POP(DS);
1909 if (lo == hi) {
1910 IP = (token_t *)endpt;
1911 } else {
1912 common_do(env, endpt, lo, hi);
1916 void
1917 compile_do_common(fcode_env_t *env, fstack_t ptr)
1919 set_temporary_compile(env);
1920 COMPILE_TOKEN(ptr);
1921 bmark(env);
1922 COMPILE_TOKEN(0);
1923 bmark(env);
1926 void
1927 bdo(fcode_env_t *env)
1929 short offset = (short)get_short(env);
1930 compile_do_common(env, (fstack_t)&do_bdo_ptr);
1933 void
1934 bqdo(fcode_env_t *env)
1936 short offset = (short)get_short(env);
1937 compile_do_common(env, (fstack_t)&do_bqdo_ptr);
1940 void
1941 loop_i(fcode_env_t *env)
1943 fstack_t i;
1945 CHECK_RETURN_DEPTH(env, 2, "i");
1946 i = RS[0] + RS[-1];
1947 PUSH(DS, i);
1950 void
1951 loop_j(fcode_env_t *env)
1953 fstack_t j;
1955 CHECK_RETURN_DEPTH(env, 5, "j");
1956 j = RS[-3] + RS[-4];
1957 PUSH(DS, j);
1960 void
1961 bleave(fcode_env_t *env)
1964 if (env->state) {
1965 COMPILE_TOKEN(&do_leave_ptr);
1969 void
1970 push_string(fcode_env_t *env, char *str, int len)
1972 #define NSTRINGS 16
1973 static int string_count = 0;
1974 static int buflen[NSTRINGS];
1975 static char *buffer[NSTRINGS];
1976 char *dest;
1978 if (!len) {
1979 PUSH(DS, 0);
1980 PUSH(DS, 0);
1981 return;
1983 if (len != buflen[string_count]) {
1984 if (buffer[string_count]) FREE(buffer[string_count]);
1985 buffer[ string_count ] = (char *)MALLOC(len+1);
1986 buflen[ string_count ] = len;
1988 dest = buffer[ string_count++ ];
1989 string_count = string_count%NSTRINGS;
1990 memcpy(dest, str, len);
1991 *(dest+len) = 0;
1992 PUSH(DS, (fstack_t)dest);
1993 PUSH(DS, len);
1994 #undef NSTRINGS
1997 void
1998 parse_word(fcode_env_t *env)
2000 int len = 0;
2001 char *next, *dest, *here = "";
2003 if (env->input) {
2004 here = env->input->scanptr;
2005 while (*here == env->input->separator) here++;
2006 next = strchr(here, env->input->separator);
2007 if (next) {
2008 len = next - here;
2009 while (*next == env->input->separator) next++;
2010 } else {
2011 len = strlen(here);
2012 next = here + len;
2014 env->input->scanptr = next;
2016 push_string(env, here, len);
2019 void
2020 install_does(fcode_env_t *env)
2022 token_t *dptr;
2024 dptr = (token_t *)LINK_TO_ACF(env->lastlink);
2026 log_message(MSG_WARN, "install_does: Last acf at: %p\n", (void *)dptr);
2028 *dptr = ((token_t)(IP+1)) | 1;
2031 void
2032 does(fcode_env_t *env)
2034 token_t *dptr;
2036 token_roundup(env, "does");
2038 if (env->state) {
2039 COMPILE_TOKEN(&does_ptr);
2040 COMPILE_TOKEN(&semi_ptr);
2041 } else {
2042 dptr = (token_t *)LINK_TO_ACF(env->lastlink);
2043 log_message(MSG_WARN, "does: Last acf at: %p\n", (void *)dptr);
2044 *dptr = ((token_t)(HERE)) | 1;
2045 env->state |= 1;
2047 COMPILE_TOKEN(&do_colon);
2050 void
2051 do_current(fcode_env_t *env)
2053 debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CURRENT\n");
2054 PUSH(DS, (fstack_t)&env->current);
2057 void
2058 do_context(fcode_env_t *env)
2060 debug_msg(DEBUG_CONTEXT, "CONTEXT:pushing &CONTEXT\n");
2061 PUSH(DS, (fstack_t)&CONTEXT);
2064 void
2065 do_definitions(fcode_env_t *env)
2067 env->current = CONTEXT;
2068 debug_msg(DEBUG_CONTEXT, "CONTEXT:definitions: %d/%p/%p\n",
2069 env->order_depth, CONTEXT, env->current);
2072 void
2073 make_header(fcode_env_t *env, int flags)
2075 int len;
2076 char *name;
2078 name = parse_a_string(env, &len);
2079 header(env, name, len, flags);
2082 void
2083 do_creator(fcode_env_t *env)
2085 make_header(env, 0);
2086 COMPILE_TOKEN(&do_create);
2087 expose_acf(env, "<create>");
2090 void
2091 create(fcode_env_t *env)
2093 if (env->state) {
2094 COMPILE_TOKEN(&create_ptr);
2095 } else
2096 do_creator(env);
2099 void
2100 colon(fcode_env_t *env)
2102 make_header(env, 0);
2103 env->state |= 1;
2104 COMPILE_TOKEN(&do_colon);
2107 void
2108 recursive(fcode_env_t *env)
2110 expose_acf(env, "<recursive>");
2113 void
2114 compile_string(fcode_env_t *env)
2116 int len;
2117 uchar_t *str, *tostr;
2119 COMPILE_TOKEN(&quote_ptr);
2120 len = POP(DS);
2121 str = (uchar_t *)POP(DS);
2122 tostr = HERE;
2123 *tostr++ = len;
2124 while (len--)
2125 *tostr++ = *str++;
2126 *tostr++ = '\0';
2127 set_here(env, tostr, "compile_string");
2128 token_roundup(env, "compile_string");
2131 void
2132 run_quote(fcode_env_t *env)
2134 char osep;
2136 osep = env->input->separator;
2137 env->input->separator = '"';
2138 parse_word(env);
2139 env->input->separator = osep;
2141 if (env->state) {
2142 compile_string(env);
2146 void
2147 does_vocabulary(fcode_env_t *env)
2149 CONTEXT = WA;
2150 debug_msg(DEBUG_CONTEXT, "CONTEXT:vocabulary: %d/%p/%p\n",
2151 env->order_depth, CONTEXT, env->current);
2154 void
2155 do_vocab(fcode_env_t *env)
2157 make_header(env, 0);
2158 COMPILE_TOKEN(does_vocabulary);
2159 PUSH(DS, 0);
2160 compile_comma(env);
2161 expose_acf(env, "<vocabulary>");
2164 void
2165 do_forth(fcode_env_t *env)
2167 CONTEXT = (token_t *)(&env->forth_voc_link);
2168 debug_msg(DEBUG_CONTEXT, "CONTEXT:forth: %d/%p/%p\n",
2169 env->order_depth, CONTEXT, env->current);
2172 acf_t
2173 voc_find(fcode_env_t *env)
2175 token_t *voc;
2176 token_t *dptr;
2177 char *find_name, *name;
2179 voc = (token_t *)POP(DS);
2180 find_name = pop_a_string(env, NULL);
2182 for (dptr = (token_t *)(*voc); dptr; dptr = (token_t *)(*dptr)) {
2183 if ((name = get_name(dptr)) == NULL)
2184 continue;
2185 if (strcmp(find_name, name) == 0) {
2186 debug_msg(DEBUG_VOC_FIND, "%s -> %p\n", find_name,
2187 LINK_TO_ACF(dptr));
2188 return (LINK_TO_ACF(dptr));
2191 debug_msg(DEBUG_VOC_FIND, "%s not found\n", find_name);
2192 return (NULL);
2195 void
2196 dollar_find(fcode_env_t *env)
2198 acf_t acf = NULL;
2199 int i;
2201 CHECK_DEPTH(env, 2, "$find");
2202 for (i = env->order_depth; i >= 0 && env->order[i] && !acf; i--) {
2203 two_dup(env);
2204 PUSH(DS, (fstack_t)env->order[i]);
2205 acf = voc_find(env);
2207 if (acf) {
2208 two_drop(env);
2209 PUSH(DS, (fstack_t)acf);
2210 PUSH(DS, TRUE);
2211 } else
2212 PUSH(DS, FALSE);
2215 void
2216 interpret(fcode_env_t *env)
2218 char *name;
2220 parse_word(env);
2221 while (TOS) {
2222 two_dup(env);
2223 dollar_find(env);
2224 if (TOS) {
2225 flag_t *flags;
2227 drop(env);
2228 nip(env);
2229 nip(env);
2230 flags = LINK_TO_FLAGS(ACF_TO_LINK(TOS));
2232 if ((env->state) &&
2233 ((*flags & IMMEDIATE) == 0)) {
2234 /* Compile in references */
2235 compile_comma(env);
2236 } else {
2237 execute(env);
2239 } else {
2240 int bad;
2241 drop(env);
2242 dollar_number(env);
2243 bad = POP(DS);
2244 if (bad) {
2245 two_dup(env);
2246 name = pop_a_string(env, NULL);
2247 log_message(MSG_INFO, "%s?\n", name);
2248 break;
2249 } else {
2250 nip(env);
2251 nip(env);
2252 literal(env);
2255 parse_word(env);
2257 two_drop(env);
2260 void
2261 evaluate(fcode_env_t *env)
2263 input_typ *old_input = env->input;
2264 input_typ *eval_bufp = MALLOC(sizeof (input_typ));
2266 CHECK_DEPTH(env, 2, "evaluate");
2267 eval_bufp->separator = ' ';
2268 eval_bufp->maxlen = POP(DS);
2269 eval_bufp->buffer = (char *)POP(DS);
2270 eval_bufp->scanptr = eval_bufp->buffer;
2271 env->input = eval_bufp;
2272 interpret(env);
2273 FREE(eval_bufp);
2274 env->input = old_input;
2277 void
2278 make_common_access(fcode_env_t *env,
2279 char *name, int len,
2280 int ncells,
2281 int instance_mode,
2282 void (*acf_instance)(fcode_env_t *env),
2283 void (*acf_static)(fcode_env_t *env),
2284 void (*set_action)(fcode_env_t *env, int))
2286 if (instance_mode && !MYSELF) {
2287 system_message(env, "No instance context");
2290 debug_msg(DEBUG_ACTIONS, "make_common_access:%s '%s', %d\n",
2291 (instance_mode ? "instance" : ""),
2292 (name ? name : ""), ncells);
2294 if (len)
2295 header(env, name, len, 0);
2296 if (instance_mode) {
2297 token_t *dptr;
2298 int offset;
2300 COMPILE_TOKEN(acf_instance);
2301 dptr = alloc_instance_data(env, INIT_DATA, ncells, &offset);
2302 debug_msg(DEBUG_ACTIONS, "Data: %p, offset %d\n", (char *)dptr,
2303 offset);
2304 PUSH(DS, offset);
2305 compile_comma(env);
2306 while (ncells--)
2307 *dptr++ = MYSELF->data[INIT_DATA][offset++] = POP(DS);
2308 env->instance_mode = 0;
2309 } else {
2310 COMPILE_TOKEN(acf_static);
2311 while (ncells--)
2312 compile_comma(env);
2314 expose_acf(env, name);
2315 if (set_action)
2316 set_action(env, instance_mode);
2319 void
2320 do_constant(fcode_env_t *env)
2322 PUSH(DS, (variable_t)(*WA));
2325 void
2326 do_crash(fcode_env_t *env)
2328 forth_abort(env, "Unitialized defer");
2332 * 'behavior' Fcode retrieve execution behavior for a defer word.
2334 static void
2335 behavior(fcode_env_t *env)
2337 acf_t defer_xt;
2338 token_t token;
2339 acf_t contents_xt;
2341 CHECK_DEPTH(env, 1, "behavior");
2342 defer_xt = (acf_t)POP(DS);
2343 token = *defer_xt;
2344 contents_xt = (token_t *)(token & ~1);
2345 if ((token & 1) == 0 || *contents_xt != (token_t)&do_default_action)
2346 forth_abort(env, "behavior: bad xt: %p indir: %x/%p\n",
2347 defer_xt, token & 1, *contents_xt);
2348 defer_xt++;
2349 PUSH(DS, *((variable_t *)defer_xt));
2352 void
2353 fc_abort(fcode_env_t *env, char *type)
2355 forth_abort(env, "%s Fcode '%s' Executed", type,
2356 acf_to_name(env, WA - 1));
2359 void
2360 f_abort(fcode_env_t *env)
2362 fc_abort(env, "Abort");
2366 * Fcodes chosen not to support.
2368 void
2369 fc_unimplemented(fcode_env_t *env)
2371 fc_abort(env, "Unimplemented");
2375 * Fcodes that are Obsolete per P1275-1994.
2377 void
2378 fc_obsolete(fcode_env_t *env)
2380 fc_abort(env, "Obsolete");
2384 * Fcodes that are Historical per P1275-1994
2386 void
2387 fc_historical(fcode_env_t *env)
2389 fc_abort(env, "Historical");
2392 void
2393 catch(fcode_env_t *env)
2395 error_frame *new;
2397 CHECK_DEPTH(env, 1, "catch");
2398 new = MALLOC(sizeof (error_frame));
2399 new->ds = DS-1;
2400 new->rs = RS;
2401 new->myself = MYSELF;
2402 new->next = env->catch_frame;
2403 new->code = 0;
2404 env->catch_frame = new;
2405 execute(env);
2406 PUSH(DS, new->code);
2407 env->catch_frame = new->next;
2408 FREE(new);
2411 void
2412 throw_from_fclib(fcode_env_t *env, fstack_t errcode, char *fmt, ...)
2414 error_frame *efp;
2415 va_list ap;
2416 char msg[256];
2418 va_start(ap, fmt);
2419 vsprintf(msg, fmt, ap);
2421 if (errcode) {
2423 env->last_error = errcode;
2426 * No catch frame set => fatal error
2428 efp = env->catch_frame;
2429 if (!efp)
2430 forth_abort(env, "%s: No catch frame", msg);
2432 debug_msg(DEBUG_TRACING, "throw_from_fclib: throw: %s\n", msg);
2435 * Setting IP=0 will force the unwinding of the calls
2436 * (see execute) which is how we will return (eventually)
2437 * to the test in catch that follows 'execute'.
2439 DS = efp->ds;
2440 RS = efp->rs;
2441 MYSELF = efp->myself;
2442 IP = 0;
2443 efp->code = errcode;
2447 void
2448 throw(fcode_env_t *env)
2450 fstack_t t;
2452 CHECK_DEPTH(env, 1, "throw");
2453 t = POP(DS);
2454 if (t >= -20 && t <= 20)
2455 throw_from_fclib(env, t, "throw Fcode errcode: 0x%x", (int)t);
2456 else {
2457 if (t)
2458 log_message(MSG_ERROR, "throw: errcode: 0x%x\n",
2459 (int)t);
2460 throw_from_fclib(env, t, "throw Fcode err: %s", (char *)t);
2464 void
2465 tick_literal(fcode_env_t *env)
2467 if (env->state) {
2468 COMPILE_TOKEN(&tlit_ptr);
2469 compile_comma(env);
2473 void
2474 do_tick(fcode_env_t *env)
2476 parse_word(env);
2477 dollar_find(env);
2478 invert(env);
2479 throw(env);
2480 tick_literal(env);
2483 void
2484 bracket_tick(fcode_env_t *env)
2486 do_tick(env);
2489 #pragma init(_init)
2491 static void
2492 _init(void)
2494 fcode_env_t *env = initial_env;
2496 NOTICE;
2497 ASSERT(env);
2499 ANSI(0x019, 0, "i", loop_i);
2500 ANSI(0x01a, 0, "j", loop_j);
2501 ANSI(0x01d, 0, "execute", execute);
2502 ANSI(0x01e, 0, "+", add);
2503 ANSI(0x01f, 0, "-", subtract);
2504 ANSI(0x020, 0, "*", multiply);
2505 ANSI(0x021, 0, "/", divide);
2506 ANSI(0x022, 0, "mod", mod);
2507 FORTH(0, "/mod", slash_mod);
2508 ANSI(0x023, 0, "and", and);
2509 ANSI(0x024, 0, "or", or);
2510 ANSI(0x025, 0, "xor", xor);
2511 ANSI(0x026, 0, "invert", invert);
2512 ANSI(0x027, 0, "lshift", lshift);
2513 ANSI(0x028, 0, "rshift", rshift);
2514 ANSI(0x029, 0, ">>a", rshifta);
2515 ANSI(0x02a, 0, "/mod", slash_mod);
2516 ANSI(0x02b, 0, "u/mod", uslash_mod);
2517 ANSI(0x02c, 0, "negate", negate);
2518 ANSI(0x02d, 0, "abs", f_abs);
2519 ANSI(0x02e, 0, "min", f_min);
2520 ANSI(0x02f, 0, "max", f_max);
2521 ANSI(0x030, 0, ">r", to_r);
2522 ANSI(0x031, 0, "r>", from_r);
2523 ANSI(0x032, 0, "r@", rfetch);
2524 ANSI(0x033, 0, "exit", f_exit);
2525 ANSI(0x034, 0, "0=", zero_equals);
2526 ANSI(0x035, 0, "0<>", zero_not_equals);
2527 ANSI(0x036, 0, "0<", zero_less);
2528 ANSI(0x037, 0, "0<=", zero_less_equals);
2529 ANSI(0x038, 0, "0>", zero_greater);
2530 ANSI(0x039, 0, "0>=", zero_greater_equals);
2531 ANSI(0x03a, 0, "<", less);
2532 ANSI(0x03b, 0, ">", greater);
2533 ANSI(0x03c, 0, "=", equals);
2534 ANSI(0x03d, 0, "<>", not_equals);
2535 ANSI(0x03e, 0, "u>", unsign_greater);
2536 ANSI(0x03f, 0, "u<=", unsign_less_equals);
2537 ANSI(0x040, 0, "u<", unsign_less);
2538 ANSI(0x041, 0, "u>=", unsign_greater_equals);
2539 ANSI(0x042, 0, ">=", greater_equals);
2540 ANSI(0x043, 0, "<=", less_equals);
2541 ANSI(0x044, 0, "between", between);
2542 ANSI(0x045, 0, "within", within);
2543 ANSI(0x046, 0, "drop", drop);
2544 ANSI(0x047, 0, "dup", f_dup);
2545 ANSI(0x048, 0, "over", over);
2546 ANSI(0x049, 0, "swap", swap);
2547 ANSI(0x04a, 0, "rot", rot);
2548 ANSI(0x04b, 0, "-rot", minus_rot);
2549 ANSI(0x04c, 0, "tuck", tuck);
2550 ANSI(0x04d, 0, "nip", nip);
2551 ANSI(0x04e, 0, "pick", pick);
2552 ANSI(0x04f, 0, "roll", roll);
2553 ANSI(0x050, 0, "?dup", qdup);
2554 ANSI(0x051, 0, "depth", depth);
2555 ANSI(0x052, 0, "2drop", two_drop);
2556 ANSI(0x053, 0, "2dup", two_dup);
2557 ANSI(0x054, 0, "2over", two_over);
2558 ANSI(0x055, 0, "2swap", two_swap);
2559 ANSI(0x056, 0, "2rot", two_rot);
2560 ANSI(0x057, 0, "2/", two_slash);
2561 ANSI(0x058, 0, "u2/", utwo_slash);
2562 ANSI(0x059, 0, "2*", two_times);
2563 ANSI(0x05a, 0, "/c", slash_c);
2564 ANSI(0x05b, 0, "/w", slash_w);
2565 ANSI(0x05c, 0, "/l", slash_l);
2566 ANSI(0x05d, 0, "/n", slash_n);
2567 ANSI(0x05e, 0, "ca+", ca_plus);
2568 ANSI(0x05f, 0, "wa+", wa_plus);
2569 ANSI(0x060, 0, "la+", la_plus);
2570 ANSI(0x061, 0, "na+", na_plus);
2571 ANSI(0x062, 0, "char+", char_plus);
2572 ANSI(0x063, 0, "wa1+", wa1_plus);
2573 ANSI(0x064, 0, "la1+", la1_plus);
2574 ANSI(0x065, 0, "cell+", cell_plus);
2575 ANSI(0x066, 0, "chars", do_chars);
2576 ANSI(0x067, 0, "/w*", slash_w_times);
2577 ANSI(0x068, 0, "/l*", slash_l_times);
2578 ANSI(0x069, 0, "cells", cells);
2579 ANSI(0x06a, 0, "on", do_on);
2580 ANSI(0x06b, 0, "off", do_off);
2581 ANSI(0x06c, 0, "+!", addstore);
2582 ANSI(0x06d, 0, "@", fetch);
2583 ANSI(0x06e, 0, "l@", lfetch);
2584 ANSI(0x06f, 0, "w@", wfetch);
2585 ANSI(0x070, 0, "<w@", swfetch);
2586 ANSI(0x071, 0, "c@", cfetch);
2587 ANSI(0x072, 0, "!", store);
2588 ANSI(0x073, 0, "l!", lstore);
2589 ANSI(0x074, 0, "w!", wstore);
2590 ANSI(0x075, 0, "c!", cstore);
2591 ANSI(0x076, 0, "2@", two_fetch);
2592 ANSI(0x077, 0, "2!", two_store);
2593 ANSI(0x078, 0, "move", fc_move);
2594 ANSI(0x079, 0, "fill", fc_fill);
2595 ANSI(0x07a, 0, "comp", fc_comp);
2596 ANSI(0x07b, 0, "noop", noop);
2597 ANSI(0x07c, 0, "lwsplit", lwsplit);
2598 ANSI(0x07d, 0, "wljoin", wljoin);
2599 ANSI(0x07e, 0, "lbsplit", lbsplit);
2600 ANSI(0x07f, 0, "bljoin", bljoin);
2601 ANSI(0x080, 0, "wbflip", wbflip);
2602 ANSI(0x081, 0, "upc", upper_case);
2603 ANSI(0x082, 0, "lcc", lower_case);
2604 ANSI(0x083, 0, "pack", pack_str);
2605 ANSI(0x084, 0, "count", count_str);
2606 ANSI(0x085, 0, "body>", to_acf);
2607 ANSI(0x086, 0, ">body", to_body);
2609 ANSI(0x089, 0, "unloop", unloop);
2611 ANSI(0x09f, 0, ".s", dot_s);
2612 ANSI(0x0a0, 0, "base", base);
2613 FCODE(0x0a1, 0, "convert", fc_historical);
2614 ANSI(0x0a2, 0, "$number", dollar_number);
2615 ANSI(0x0a3, 0, "digit", digit);
2617 ANSI(0x0a9, 0, "bl", space);
2618 ANSI(0x0aa, 0, "bs", backspace);
2619 ANSI(0x0ab, 0, "bell", bell);
2620 ANSI(0x0ac, 0, "bounds", fc_bounds);
2621 ANSI(0x0ad, 0, "here", here);
2623 ANSI(0x0af, 0, "wbsplit", wbsplit);
2624 ANSI(0x0b0, 0, "bwjoin", bwjoin);
2626 P1275(0x0cb, 0, "$find", dollar_find);
2628 ANSI(0x0d0, 0, "c,", ccomma);
2629 ANSI(0x0d1, 0, "w,", wcomma);
2630 ANSI(0x0d2, 0, "l,", lcomma);
2631 ANSI(0x0d3, 0, ",", comma);
2632 ANSI(0x0d4, 0, "um*", um_multiply);
2633 ANSI(0x0d5, 0, "um/mod", um_slash_mod);
2635 ANSI(0x0d8, 0, "d+", d_plus);
2636 ANSI(0x0d9, 0, "d-", d_minus);
2638 ANSI(0x0dc, 0, "state", state);
2639 ANSI(0x0de, 0, "behavior", behavior);
2640 ANSI(0x0dd, 0, "compile,", compile_comma);
2642 ANSI(0x216, 0, "abort", f_abort);
2643 ANSI(0x217, 0, "catch", catch);
2644 ANSI(0x218, 0, "throw", throw);
2646 ANSI(0x226, 0, "lwflip", lwflip);
2647 ANSI(0x227, 0, "lbflip", lbflip);
2648 ANSI(0x228, 0, "lbflips", lbflips);
2650 ANSI(0x236, 0, "wbflips", wbflips);
2651 ANSI(0x237, 0, "lwflips", lwflips);
2653 FORTH(0, "forth", do_forth);
2654 FORTH(0, "current", do_current);
2655 FORTH(0, "context", do_context);
2656 FORTH(0, "definitions", do_definitions);
2657 FORTH(0, "vocabulary", do_vocab);
2658 FORTH(IMMEDIATE, ":", colon);
2659 FORTH(IMMEDIATE, ";", semi);
2660 FORTH(IMMEDIATE, "create", create);
2661 FORTH(IMMEDIATE, "does>", does);
2662 FORTH(IMMEDIATE, "recursive", recursive);
2663 FORTH(0, "parse-word", parse_word);
2664 FORTH(IMMEDIATE, "\"", run_quote);
2665 FORTH(IMMEDIATE, "order", do_order);
2666 FORTH(IMMEDIATE, "also", do_also);
2667 FORTH(IMMEDIATE, "previous", do_previous);
2668 FORTH(IMMEDIATE, "'", do_tick);
2669 FORTH(IMMEDIATE, "[']", bracket_tick);
2670 FORTH(0, "unaligned-l@", unaligned_lfetch);
2671 FORTH(0, "unaligned-l!", unaligned_lstore);
2672 FORTH(0, "unaligned-w@", unaligned_wfetch);
2673 FORTH(0, "unaligned-w!", unaligned_wstore);