aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPedro F. Giffuni <pfg@FreeBSD.org>2015-05-12 03:27:06 +0000
committerPedro F. Giffuni <pfg@FreeBSD.org>2015-05-12 03:27:06 +0000
commitf4e75c6395310fa4b119d3eaa9a4a9f8913df200 (patch)
tree2b015c205d81fa2431f0c36d7d9e903088a56d1c
parentbe98e1ae3decabdd852fbe6496166aaa9acfbf9e (diff)
downloadsrc-vendor/ficl.tar.gz
src-vendor/ficl.zip
Update to ficl 4.1.0 (latest release on sourceforge)vendor/ficl/4.1.0vendor/ficl
Notes
Notes: svn path=/vendor/ficl/dist/; revision=282803 svn path=/vendor/ficl/4.1.0/; revision=282804; tag=vendor/ficl/4.1.0
-rw-r--r--Makefile60
-rw-r--r--Makefile.ansi56
-rw-r--r--Makefile.linux30
-rw-r--r--ReadMe.txt20
-rw-r--r--bit.c49
-rw-r--r--callback.c76
-rw-r--r--compatibility.c284
-rw-r--r--contrib/xclasses/readme.txt111
-rw-r--r--contrib/xclasses/xclasses.py870
-rw-r--r--dict.c836
-rw-r--r--dictionary.c851
-rw-r--r--doc/Logo.jpgbin2349 -> 0 bytes
-rw-r--r--doc/api.html401
-rw-r--r--doc/articles/ficlddj.pdf (renamed from doc/ficlddj.PDF)bin34088 -> 34088 bytes
-rw-r--r--doc/articles/jwsforml.pdf (renamed from doc/jwsforml.PDF)bin140379 -> 140379 bytes
-rw-r--r--doc/articles/oo_in_c.html (renamed from doc/oo_in_c.html)0
-rw-r--r--doc/articles/sigplan9906.doc (renamed from doc/sigplan9906.doc)bin75776 -> 75776 bytes
-rw-r--r--doc/debugger.html259
-rw-r--r--doc/dpans.html1037
-rw-r--r--doc/favicon.icobin1078 -> 894 bytes
-rw-r--r--doc/ficl.html2754
-rw-r--r--doc/ficl1.icobin3310 -> 0 bytes
-rw-r--r--doc/ficl_debug.html111
-rw-r--r--doc/ficl_guts.htm69
-rw-r--r--doc/ficl_loc.html161
-rw-r--r--doc/ficl_logo.jpgbin2349 -> 0 bytes
-rw-r--r--doc/ficl_oop.html1387
-rw-r--r--doc/ficl_parse.html197
-rw-r--r--doc/ficlheader.js19
-rw-r--r--doc/graphics/4ring.gifbin0 -> 1247 bytes
-rw-r--r--doc/graphics/ficl.4.128.jpgbin0 -> 30958 bytes
-rw-r--r--doc/graphics/ficl.4.64.jpgbin0 -> 17200 bytes
-rw-r--r--doc/graphics/ficl.4.96.jpgbin0 -> 23710 bytes
-rw-r--r--doc/graphics/ficl_oop.jpg (renamed from doc/ficl_oop.jpg)bin63155 -> 63155 bytes
-rw-r--r--doc/graphics/ficl_top.jpg (renamed from doc/ficl_top.jpg)bin51512 -> 51512 bytes
-rw-r--r--doc/graphics/sourceforge.jpgbin0 -> 2615 bytes
-rw-r--r--doc/index.html492
-rw-r--r--doc/license.html103
-rw-r--r--doc/links.html318
-rw-r--r--doc/locals.html253
-rw-r--r--doc/oop.html1640
-rw-r--r--doc/parsesteps.html388
-rw-r--r--doc/primer.txt1164
-rw-r--r--doc/releases.html1267
-rw-r--r--doc/skey.gifbin4364 -> 0 bytes
-rw-r--r--doc/source/api.ht250
-rw-r--r--doc/source/debugger.ht157
-rw-r--r--doc/source/dpans.ht589
-rw-r--r--doc/source/ficl.ht1257
-rw-r--r--doc/source/generate.py244
-rw-r--r--doc/source/index.ht244
-rw-r--r--doc/source/license.ht47
-rw-r--r--doc/source/links.ht156
-rw-r--r--doc/source/locals.ht133
-rw-r--r--doc/source/oop.ht1224
-rw-r--r--doc/source/parsesteps.ht234
-rw-r--r--doc/source/releases.ht (renamed from doc/ficl_rel.html)729
-rw-r--r--doc/source/upgrading.ht349
-rw-r--r--doc/upgrading.html808
-rw-r--r--double.c479
-rw-r--r--extras.c267
-rw-r--r--ficl.c691
-rw-r--r--ficl.dsp301
-rw-r--r--ficl.dsw88
-rw-r--r--ficl.h1995
-rw-r--r--ficlcompatibility.h463
-rw-r--r--ficldll.def176
-rw-r--r--ficldll.dsp219
-rw-r--r--ficlexe.dsp206
-rw-r--r--ficllib.dsp296
-rw-r--r--ficllocal.h8
-rw-r--r--ficlplatform/alpha.h27
-rw-r--r--ficlplatform/ansi.c64
-rw-r--r--ficlplatform/ansi.h19
-rw-r--r--ficlplatform/ficlexports.txt168
-rw-r--r--ficlplatform/makedef.py33
-rw-r--r--ficlplatform/unix.c75
-rw-r--r--ficlplatform/unix.h46
-rw-r--r--ficlplatform/win32.c413
-rw-r--r--ficlplatform/win32.h64
-rw-r--r--ficltokens.h228
-rw-r--r--fileaccess.c364
-rw-r--r--float.c926
-rw-r--r--hash.c163
-rw-r--r--lzcompress.c202
-rw-r--r--lzuncompress.c94
-rw-r--r--main.c78
-rw-r--r--math64.c559
-rw-r--r--math64.h86
-rw-r--r--prefix.c131
-rw-r--r--primitives.c3513
-rw-r--r--search.c280
-rw-r--r--softcore.c3557
-rw-r--r--softcore/classes.fr (renamed from softwords/classes.fr)344
-rw-r--r--softcore/ficl.fr67
-rw-r--r--softcore/ficlclass.fr (renamed from softwords/ficlclass.fr)168
-rw-r--r--softcore/ficllocal.fr (renamed from softwords/ficllocal.fr)92
-rw-r--r--softcore/fileaccess.fr (renamed from softwords/fileaccess.fr)45
-rw-r--r--softcore/forml.fr (renamed from softwords/forml.fr)144
-rw-r--r--softcore/ifbrack.fr (renamed from softwords/ifbrack.fr)96
-rw-r--r--softcore/jhlocal.fr171
-rw-r--r--softcore/make.bat22
-rw-r--r--softcore/makefile11
-rw-r--r--softcore/makesoftcore.c244
-rw-r--r--softcore/marker.fr (renamed from softwords/marker.fr)50
-rw-r--r--softcore/oo.fr (renamed from softwords/oo.fr)1393
-rw-r--r--softcore/prefix.fr (renamed from softwords/prefix.fr)104
-rw-r--r--softcore/softcore.fr (renamed from softwords/softcore.fr)359
-rw-r--r--softcore/string.fr (renamed from softwords/string.fr)297
-rw-r--r--softcore/win32.fr211
-rw-r--r--softwords/jhlocal.fr103
-rw-r--r--softwords/makefile9
-rw-r--r--softwords/oo.fr.bak678
-rw-r--r--softwords/softcore.bat1
-rwxr-xr-xsoftwords/softcore.pl144
-rw-r--r--softwords/softcore.py152
-rw-r--r--softwords/softcore.py.bat1
-rw-r--r--softwords/win32.fr10
-rw-r--r--stack.c269
-rw-r--r--sysdep.c409
-rw-r--r--sysdep.h465
-rw-r--r--system.c466
-rw-r--r--test/asm68k.4th608
-rw-r--r--test/core.fr1994
-rw-r--r--test/fib.fr24
-rw-r--r--test/ficltest.fr212
-rw-r--r--test/ooptest.fr146
-rw-r--r--test/prefix.fr14
-rw-r--r--test/sarray.fr34
-rw-r--r--test/testcase.fr167
-rw-r--r--test/tester.fr118
-rw-r--r--test/vocab.fr64
-rw-r--r--testmain.c367
-rw-r--r--tools.c965
-rw-r--r--unix.c21
-rw-r--r--utility.c262
-rw-r--r--vm.c3097
-rw-r--r--win32.c406
-rw-r--r--word.c144
-rw-r--r--words.c5201
140 files changed, 35791 insertions, 22541 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000000..976d00a7fa12
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,60 @@
+OBJECTS= dictionary.o system.o fileaccess.o float.o double.o prefix.o search.o softcore.o stack.o tools.o vm.o primitives.o bit.o lzuncompress.o unix.o utility.o hash.o callback.o word.o extras.o
+HEADERS= ficl.h ficlplatform/unix.h
+#
+# Flags for shared library
+#TARGET= -Dlinux # riscos MOTO_CPU32
+SHFLAGS = -fPIC
+CFLAGS= -O $(SHFLAGS) -Wall
+CPPFLAGS= $(TARGET) -I.
+CC = cc
+LIB = ar cr
+RANLIB = ranlib
+
+MAJOR = 4
+MINOR = 1.0
+
+ficl: main.o $(HEADERS) libficl.a
+ $(CC) $(CFLAGS) $(LDFLAGS) main.o -o ficl -L. -lficl -lm
+
+lib: libficl.so.$(MAJOR).$(MINOR)
+
+# static library build
+libficl.a: $(OBJECTS)
+ $(LIB) libficl.a $(OBJECTS)
+ $(RANLIB) libficl.a
+
+# shared library build
+libficl.so.$(MAJOR).$(MINOR): $(OBJECTS)
+ $(CC) $(LDFLAGS) -shared -Wl,-soname,libficl.so.$(MAJOR).$(MINOR) \
+ -o libficl.so.$(MAJOR).$(MINOR) $(OBJECTS)
+ ln -sf libficl.so.$(MAJOR).$(MINOR) libficl.so
+
+main: main.o ficl.h sysdep.h libficl.so.$(MAJOR).$(MINOR)
+ $(CC) $(CFLAGS) $(LDFLAGS) main.o -o main -L. -lficl -lm
+ ln -sf libficl.so.$(MAJOR).$(MINOR) libficl.so.$(MAJOR)
+
+# depend explicitly to help finding source files in another subdirectory,
+# and repeat commands since gmake doesn't understand otherwise
+ansi.o: ficlplatform/ansi.c $(HEADERS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+unix.o: ficlplatform/unix.c $(HEADERS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+#
+# generic object code
+#
+.SUFFIXES: .cxx .cc .c .o
+
+.c.o:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+.cxx.o:
+ $(CPP) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+.cc.o:
+ $(CPP) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+#
+# generic cleanup code
+#
+clean:
+ rm -f *.o *.a libficl.* ficl
diff --git a/Makefile.ansi b/Makefile.ansi
new file mode 100644
index 000000000000..e510fcda2ca8
--- /dev/null
+++ b/Makefile.ansi
@@ -0,0 +1,56 @@
+OBJECTS= dictionary.o system.o fileaccess.o float.o double.o prefix.o search.o softcore.o stack.o tools.o vm.o primitives.o bit.o lzuncompress.o ansi.o utility.o hash.o callback.o word.o extras.o
+HEADERS= ficl.h ficlplatform/ansi.h
+#
+# Flags for shared library
+TARGET= -ansi -DFICL_ANSI # riscos MOTO_CPU32
+SHFLAGS = -fPIC
+CFLAGS= -O $(SHFLAGS)
+CPPFLAGS= $(TARGET) -I.
+CC = cc
+LIB = ar cr
+RANLIB = ranlib
+
+MAJOR = 4
+MINOR = 1.0
+
+ficl: main.o $(HEADERS) libficl.a
+ $(CC) main.o -o ficl -L. -lficl -lm
+
+lib: libficl.so.$(MAJOR).$(MINOR)
+
+# static library build
+libficl.a: $(OBJECTS)
+ $(LIB) libficl.a $(OBJECTS)
+ $(RANLIB) libficl.a
+
+# shared library build
+libficl.so.$(MAJOR).$(MINOR): $(OBJECTS)
+ $(CC) -shared -Wl,-soname,libficl.so.$(MAJOR).$(MINOR) \
+ -o libficl.so.$(MAJOR).$(MINOR) $(OBJECTS)
+ ln -sf libficl.so.$(MAJOR).$(MINOR) libficl.so
+
+main: main.o ficl.h sysdep.h libficl.so.$(MAJOR).$(MINOR)
+ $(CC) main.o -o main -L. -lficl -lm
+ ln -sf libficl.so.$(MAJOR).$(MINOR) libficl.so.$(MAJOR)
+
+ansi.o: ficlplatform/ansi.c $(HEADERS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ ficlplatform/ansi.c
+
+#
+# generic object code
+#
+.SUFFIXES: .cxx .cc .c .o
+
+.c.o:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+.cxx.o:
+ $(CPP) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+.cc.o:
+ $(CPP) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
+#
+# generic cleanup code
+#
+clean:
+ rm -f *.o *.a libficl.*
diff --git a/Makefile.linux b/Makefile.linux
index 5dbca1012744..d447e7e88178 100644
--- a/Makefile.linux
+++ b/Makefile.linux
@@ -1,19 +1,20 @@
-OBJECTS= dict.o ficl.o fileaccess.o float.o math64.o prefix.o search.o softcore.o stack.o sysdep.o tools.o unix.o vm.o words.o
-HEADERS= ficl.h math64.h sysdep.h
+OBJECTS= dictionary.o system.o fileaccess.o float.o double.o prefix.o search.o softcore.o stack.o tools.o vm.o primitives.o bit.o lzuncompress.o unix.o utility.o hash.o callback.o word.o extras.o
+HEADERS= ficl.h ficlplatform/unix.h
#
# Flags for shared library
TARGET= -Dlinux # riscos MOTO_CPU32
SHFLAGS = -fPIC
-CFLAGS= -O -c $(SHFLAGS) $(TARGET)
-CC=gcc
+CFLAGS= -O $(SHFLAGS)
+CPPFLAGS= $(TARGET) -I.
+CC = cc
LIB = ar cr
RANLIB = ranlib
-MAJOR = 3
-MINOR = 0.1
+MAJOR = 4
+MINOR = 1.0
-ficl: testmain.o ficl.h sysdep.h libficl.a
- $(CC) testmain.o -o ficl -L. -lficl -lm
+ficl: main.o $(HEADERS) libficl.a
+ $(CC) main.o -o ficl -L. -lficl -lm
lib: libficl.so.$(MAJOR).$(MINOR)
@@ -28,23 +29,26 @@ libficl.so.$(MAJOR).$(MINOR): $(OBJECTS)
-o libficl.so.$(MAJOR).$(MINOR) $(OBJECTS)
ln -sf libficl.so.$(MAJOR).$(MINOR) libficl.so
-testmain: testmain.o ficl.h sysdep.h libficl.so.$(MAJOR).$(MINOR)
- $(CC) testmain.o -o testmain -L. -lficl -lm
+main: main.o ficl.h sysdep.h libficl.so.$(MAJOR).$(MINOR)
+ $(CC) main.o -o main -L. -lficl -lm
ln -sf libficl.so.$(MAJOR).$(MINOR) libficl.so.$(MAJOR)
+unix.o: ficlplatform/unix.c $(HEADERS)
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ ficlplatform/unix.c
+
#
# generic object code
#
.SUFFIXES: .cxx .cc .c .o
.c.o:
- $(CC) $(CFLAGS) -c $*.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
.cxx.o:
- $(CPP) $(CPFLAGS) -c $*.cxx
+ $(CPP) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
.cc.o:
- $(CPP) $(CPFLAGS) -c $*.cc
+ $(CPP) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
#
# generic cleanup code
#
diff --git a/ReadMe.txt b/ReadMe.txt
index 6985b807d248..4ea553d0217e 100644
--- a/ReadMe.txt
+++ b/ReadMe.txt
@@ -1,5 +1,5 @@
-FICL 3.03
-April 2002
+FICL 4.1.0
+October 2010
________
OVERVIEW
@@ -10,18 +10,22 @@ and development prototype language. Ficl stands for "Forth Inspired
Command Language".
For more information, please see the "doc" directory.
-For release notes, please see "doc/ficl_rel.html".
+For release notes, please see "doc/releases.html".
____________
INSTALLATION
Ficl builds out-of-the-box on the following platforms:
- * Linux: use "Makefile.linux".
- * RiscOS: use "Makefile.riscos".
+ * NetBSD, FreeBSD: use "Makefile".
+ * Linux: use "Makefile.linux", but it should work with
+ "Makefile" as well.
* Win32: use "ficl.dsw" / "ficl.dsp".
-To port to other platforms, be sure to examine "sysdep.h", and
-we suggest you start with the Linux makefile. (And please--feel
-free to submit your portability changes!)
+To port to other platforms, we suggest you start with the generic
+"Makefile" and the "unix.c" / "unix.h" platform-specific implementation
+files. (And please--feel free to submit your portability changes!)
+
+(Note: Ficl used to build under RiscOS, but we broke everything
+for the 4.0 release. Please fix it and send us the diffs!)
____________
FICL LICENSE
diff --git a/bit.c b/bit.c
new file mode 100644
index 000000000000..68907c0ed06e
--- /dev/null
+++ b/bit.c
@@ -0,0 +1,49 @@
+#include "ficl.h"
+
+int ficlBitGet(const unsigned char *bits, size_t index)
+ {
+ int byteIndex = index >> 3;
+ int bitIndex = index & 7;
+ unsigned char mask = (unsigned char)(128 >> bitIndex);
+
+ return ((mask & bits[byteIndex]) ? 1 : 0);
+ }
+
+
+
+void ficlBitSet(unsigned char *bits, size_t index, int value)
+ {
+ int byteIndex = index >> 3;
+ int bitIndex = index & 7;
+ unsigned char mask = (unsigned char)(128 >> bitIndex);
+
+ if (value)
+ bits[byteIndex] |= mask;
+ else
+ bits[byteIndex] &= ~mask;
+ }
+
+
+void ficlBitGetString(unsigned char *destination, const unsigned char *source, int offset, int count, int destAlignment)
+ {
+ int bit = destAlignment - count;
+ while (count--)
+ ficlBitSet(destination, bit++, ficlBitGet(source, offset++));
+ }
+
+
+/*
+** This will actually work correctly *regardless* of the local architecture.
+** --lch
+**/
+ficlUnsigned16 ficlNetworkUnsigned16(ficlUnsigned16 number)
+{
+ ficlUnsigned8 *pointer = (ficlUnsigned8 *)&number;
+ return (ficlUnsigned16)(((ficlUnsigned16)(pointer[0] << 8)) | (pointer[1]));
+}
+
+ficlUnsigned32 ficlNetworkUnsigned32(ficlUnsigned32 number)
+{
+ ficlUnsigned16 *pointer = (ficlUnsigned16 *)&number;
+ return ((ficlUnsigned32)(ficlNetworkUnsigned16(pointer[0]) << 16)) | ficlNetworkUnsigned16(pointer[1]);
+}
diff --git a/callback.c b/callback.c
new file mode 100644
index 000000000000..6d6d65c54904
--- /dev/null
+++ b/callback.c
@@ -0,0 +1,76 @@
+#include "ficl.h"
+
+
+extern ficlSystem *ficlSystemGlobal;
+
+/**************************************************************************
+ f i c l C a l l b a c k T e x t O u t
+** Feeds text to the vm's output callback
+**************************************************************************/
+void ficlCallbackTextOut(ficlCallback *callback, char *text)
+{
+ ficlOutputFunction textOut = NULL;
+
+ if (callback != NULL)
+ {
+ if (callback->textOut != NULL)
+ textOut = callback->textOut;
+ else if ((callback->system != NULL) && (callback != &(callback->system->callback)))
+ {
+ ficlCallbackTextOut(&(callback->system->callback), text);
+ return;
+ }
+ }
+
+ if ((textOut == NULL) && (ficlSystemGlobal != NULL))
+ {
+ callback = &(ficlSystemGlobal->callback);
+ textOut = callback->textOut;
+ }
+
+ if (textOut == NULL)
+ textOut = ficlCallbackDefaultTextOut;
+
+ (textOut)(callback, text);
+
+ return;
+}
+
+
+/**************************************************************************
+ f i c l C a l l b a c k E r r o r O u t
+** Feeds text to the vm's error output callback
+**************************************************************************/
+void ficlCallbackErrorOut(ficlCallback *callback, char *text)
+{
+ ficlOutputFunction errorOut = NULL;
+
+ if (callback != NULL)
+ {
+ if (callback->errorOut != NULL)
+ errorOut = callback->errorOut;
+ else if ((callback->system != NULL) && (callback != &(callback->system->callback)))
+ {
+ ficlCallbackErrorOut(&(callback->system->callback), text);
+ return;
+ }
+ }
+
+ if ((errorOut == NULL) && (ficlSystemGlobal != NULL))
+ {
+ callback = &(ficlSystemGlobal->callback);
+ errorOut = callback->errorOut;
+ }
+
+ if (errorOut == NULL)
+ {
+ ficlCallbackTextOut(callback, text);
+ return;
+ }
+
+ (errorOut)(callback, text);
+
+ return;
+}
+
+
diff --git a/compatibility.c b/compatibility.c
new file mode 100644
index 000000000000..6970e4a422af
--- /dev/null
+++ b/compatibility.c
@@ -0,0 +1,284 @@
+#define FICL_FORCE_COMPATIBILITY 1
+#include "ficl.h"
+
+
+FICL_PLATFORM_EXTERN ficlStack *stackCreate (unsigned cells) { return ficlStackCreate(NULL, "unknown", cells); }
+FICL_PLATFORM_EXTERN void stackDelete (ficlStack *stack) { ficlStackDestroy(stack); }
+FICL_PLATFORM_EXTERN int stackDepth (ficlStack *stack) { return ficlStackDepth(stack); }
+FICL_PLATFORM_EXTERN void stackDrop (ficlStack *stack, int n) { ficlStackDrop(stack, n); }
+FICL_PLATFORM_EXTERN ficlCell stackFetch (ficlStack *stack, int n) { return ficlStackFetch(stack, n); }
+FICL_PLATFORM_EXTERN ficlCell stackGetTop (ficlStack *stack) { return ficlStackFetch(stack, 0); }
+#if FICL_WANT_LOCALS
+FICL_PLATFORM_EXTERN void stackLink (ficlStack *stack, int cells) { ficlStackLink(stack, cells); }
+FICL_PLATFORM_EXTERN void stackUnlink (ficlStack *stack) { ficlStackUnlink(stack); }
+#endif /* FICL_WANT_LOCALS */
+FICL_PLATFORM_EXTERN void stackPick (ficlStack *stack, int n) { ficlStackPick(stack, n); }
+FICL_PLATFORM_EXTERN ficlCell stackPop (ficlStack *stack) { return ficlStackPop(stack); }
+FICL_PLATFORM_EXTERN void *stackPopPtr (ficlStack *stack) { return ficlStackPopPointer(stack); }
+FICL_PLATFORM_EXTERN ficlUnsigned stackPopUNS (ficlStack *stack) { return ficlStackPopUnsigned(stack); }
+FICL_PLATFORM_EXTERN ficlInteger stackPopINT (ficlStack *stack) { return ficlStackPopInteger(stack); }
+FICL_PLATFORM_EXTERN void stackPush (ficlStack *stack, ficlCell cell) { ficlStackPush(stack, cell); }
+FICL_PLATFORM_EXTERN void stackPushPtr (ficlStack *stack, void *pointer) { ficlStackPushPointer(stack, pointer); }
+FICL_PLATFORM_EXTERN void stackPushUNS (ficlStack *stack, ficlUnsigned u) { ficlStackPushUnsigned(stack, u); }
+FICL_PLATFORM_EXTERN void stackPushINT (ficlStack *stack, ficlInteger i) { ficlStackPushInteger(stack, i); }
+FICL_PLATFORM_EXTERN void stackReset (ficlStack *stack) { ficlStackReset(stack); }
+FICL_PLATFORM_EXTERN void stackRoll (ficlStack *stack, int n) { ficlStackRoll(stack, n); }
+FICL_PLATFORM_EXTERN void stackSetTop (ficlStack *stack, ficlCell cell) { ficlStackSetTop(stack, cell); }
+FICL_PLATFORM_EXTERN void stackStore (ficlStack *stack, int n, ficlCell cell) { ficlStackStore(stack, n, cell); }
+
+#if (FICL_WANT_FLOAT)
+FICL_PLATFORM_EXTERN ficlFloat stackPopFloat (ficlStack *stack) { return ficlStackPopFloat(stack); }
+FICL_PLATFORM_EXTERN void stackPushFloat(ficlStack *stack, ficlFloat f) { ficlStackPushFloat(stack, f); }
+#endif
+
+FICL_PLATFORM_EXTERN int wordIsImmediate(ficlWord *word) { return ficlWordIsImmediate(word); }
+FICL_PLATFORM_EXTERN int wordIsCompileOnly(ficlWord *word) { return ficlWordIsCompileOnly(word); }
+
+
+FICL_PLATFORM_EXTERN void vmBranchRelative(ficlVm *vm, int offset) { ficlVmBranchRelative(vm, offset); }
+FICL_PLATFORM_EXTERN ficlVm *vmCreate (ficlVm *vm, unsigned nPStack, unsigned nRStack) { return ficlVmCreate(vm, nPStack, nRStack); }
+FICL_PLATFORM_EXTERN void vmDelete (ficlVm *vm) { ficlVmDestroy(vm); }
+FICL_PLATFORM_EXTERN void vmExecute (ficlVm *vm, ficlWord *word) { ficlVmExecuteWord(vm, word); }
+FICL_PLATFORM_EXTERN ficlDictionary *vmGetDict (ficlVm *vm) { return ficlVmGetDictionary(vm); }
+FICL_PLATFORM_EXTERN char * vmGetString (ficlVm *vm, ficlCountedString *spDest, char delimiter) { return ficlVmGetString(vm, spDest, delimiter); }
+FICL_PLATFORM_EXTERN ficlString vmGetWord (ficlVm *vm) { return ficlVmGetWord(vm); }
+FICL_PLATFORM_EXTERN ficlString vmGetWord0 (ficlVm *vm) { return ficlVmGetWord0(vm); }
+FICL_PLATFORM_EXTERN int vmGetWordToPad (ficlVm *vm) { return ficlVmGetWordToPad(vm); }
+FICL_PLATFORM_EXTERN ficlString vmParseString (ficlVm *vm, char delimiter) { return ficlVmParseString(vm, delimiter); }
+FICL_PLATFORM_EXTERN ficlString vmParseStringEx(ficlVm *vm, char delimiter, char skipLeading) { return ficlVmParseStringEx(vm, delimiter, skipLeading); }
+FICL_PLATFORM_EXTERN ficlCell vmPop (ficlVm *vm) { return ficlVmPop(vm); }
+FICL_PLATFORM_EXTERN void vmPush (ficlVm *vm, ficlCell cell) { ficlVmPush(vm, cell); }
+FICL_PLATFORM_EXTERN void vmPopIP (ficlVm *vm) { ficlVmPopIP(vm); }
+FICL_PLATFORM_EXTERN void vmPushIP (ficlVm *vm, ficlIp newIP) { ficlVmPushIP(vm, newIP); }
+FICL_PLATFORM_EXTERN void vmQuit (ficlVm *vm) { ficlVmQuit(vm); }
+FICL_PLATFORM_EXTERN void vmReset (ficlVm *vm) { ficlVmReset(vm); }
+FICL_PLATFORM_EXTERN void vmThrow (ficlVm *vm, int except) { ficlVmThrow(vm, except); }
+FICL_PLATFORM_EXTERN void vmThrowErr (ficlVm *vm, char *fmt, ...) { va_list list; va_start(list, fmt); ficlVmThrowErrorVararg(vm, fmt, list); va_end(list); }
+
+FICL_PLATFORM_EXTERN void vmCheckStack(ficlVm *vm, int popCells, int pushCells) { FICL_IGNORE(vm); FICL_IGNORE(popCells); FICL_IGNORE(pushCells); FICL_STACK_CHECK(vm->dataStack, popCells, pushCells); }
+#if FICL_WANT_FLOAT
+FICL_PLATFORM_EXTERN void vmCheckFStack(ficlVm *vm, int popCells, int pushCells) { FICL_IGNORE(vm); FICL_IGNORE(popCells); FICL_IGNORE(pushCells); FICL_STACK_CHECK(vm->floatStack, popCells, pushCells); }
+#endif
+
+FICL_PLATFORM_EXTERN void vmPushTib (ficlVm *vm, char *text, ficlInteger nChars, ficlTIB *pSaveTib) { ficlVmPushTib(vm, text, nChars, pSaveTib); }
+FICL_PLATFORM_EXTERN void vmPopTib (ficlVm *vm, ficlTIB *pTib) { ficlVmPopTib(vm, pTib); }
+
+FICL_PLATFORM_EXTERN int isPowerOfTwo(ficlUnsigned u) { return ficlIsPowerOfTwo(u); }
+
+#if defined(_WIN32)
+/* #SHEESH
+** Why do Microsoft Meatballs insist on contaminating
+** my namespace with their string functions???
+*/
+#pragma warning(disable: 4273)
+#endif
+char *ltoa(ficlInteger value, char *string, int radix ) { return ficlLtoa(value, string, radix); }
+char *ultoa(ficlUnsigned value, char *string, int radix ) { return ficlUltoa(value, string, radix); }
+char *strrev( char *string ) { return ficlStringReverse(string); }
+#if defined(_WIN32)
+#pragma warning(default: 4273)
+#endif
+FICL_PLATFORM_EXTERN char digit_to_char(int value) { return ficlDigitToCharacter(value); }
+FICL_PLATFORM_EXTERN char *skipSpace(char *cp, char *end) { return ficlStringSkipSpace(cp, end); }
+FICL_PLATFORM_EXTERN char *caseFold(char *cp) { return ficlStringCaseFold(cp); }
+FICL_PLATFORM_EXTERN int strincmp(char *cp1, char *cp2, ficlUnsigned count) { return ficlStrincmp(cp1, cp2, count); }
+
+FICL_PLATFORM_EXTERN void hashForget (ficlHash *hash, void *where) { ficlHashForget(hash, where); }
+FICL_PLATFORM_EXTERN ficlUnsigned16 hashHashCode (ficlString string) { return ficlHashCode(string); }
+FICL_PLATFORM_EXTERN void hashInsertWord(ficlHash *hash, ficlWord *word) { ficlHashInsertWord(hash, word); }
+FICL_PLATFORM_EXTERN ficlWord *hashLookup (ficlHash *hash, ficlString string, ficlUnsigned16 hashCode) { return ficlHashLookup(hash, string, hashCode); }
+FICL_PLATFORM_EXTERN void hashReset (ficlHash *hash) { ficlHashReset(hash); }
+
+
+FICL_PLATFORM_EXTERN void *alignPtr(void *ptr) { return ficlAlignPointer(ptr); }
+FICL_PLATFORM_EXTERN void dictAbortDefinition(ficlDictionary *dictionary) { ficlDictionaryAbortDefinition(dictionary); }
+FICL_PLATFORM_EXTERN void dictAlign (ficlDictionary *dictionary) { ficlDictionaryAlign(dictionary); }
+FICL_PLATFORM_EXTERN int dictAllot (ficlDictionary *dictionary, int n) { ficlDictionaryAllot(dictionary, n); return 0; }
+FICL_PLATFORM_EXTERN int dictAllotCells (ficlDictionary *dictionary, int cells) { ficlDictionaryAllotCells(dictionary, cells); return 0; }
+FICL_PLATFORM_EXTERN void dictAppendCell (ficlDictionary *dictionary, ficlCell cell) { ficlDictionaryAppendCell(dictionary, cell); }
+FICL_PLATFORM_EXTERN void dictAppendChar (ficlDictionary *dictionary, char c) { ficlDictionaryAppendCharacter(dictionary, c); }
+FICL_PLATFORM_EXTERN ficlWord *dictAppendWord (ficlDictionary *dictionary,
+ char *name,
+ ficlPrimitive code,
+ ficlUnsigned8 flags)
+ { return ficlDictionaryAppendPrimitive(dictionary, name, code, flags); }
+FICL_PLATFORM_EXTERN ficlWord *dictAppendWord2(ficlDictionary *dictionary,
+ ficlString name,
+ ficlPrimitive code,
+ ficlUnsigned8 flags)
+ { return ficlDictionaryAppendWord(dictionary, name, code, flags); }
+FICL_PLATFORM_EXTERN void dictAppendUNS (ficlDictionary *dictionary, ficlUnsigned u) { ficlDictionaryAppendUnsigned(dictionary, u); }
+FICL_PLATFORM_EXTERN int dictCellsAvail (ficlDictionary *dictionary) { return ficlDictionaryCellsAvailable(dictionary); }
+FICL_PLATFORM_EXTERN int dictCellsUsed (ficlDictionary *dictionary) { return ficlDictionaryCellsUsed(dictionary); }
+FICL_PLATFORM_EXTERN void dictCheck (ficlDictionary *dictionary, ficlVm *vm, int n) { FICL_IGNORE(dictionary); FICL_IGNORE(vm); FICL_IGNORE(n); FICL_VM_DICTIONARY_CHECK(vm, dictionary, n); }
+FICL_PLATFORM_EXTERN ficlDictionary *dictCreate(unsigned cells) { return ficlDictionaryCreate(NULL, cells); }
+FICL_PLATFORM_EXTERN ficlDictionary *dictCreateHashed(unsigned cells, unsigned hash) { return ficlDictionaryCreateHashed(NULL, cells, hash); }
+FICL_PLATFORM_EXTERN ficlHash *dictCreateWordlist(ficlDictionary *dictionary, int nBuckets) { return ficlDictionaryCreateWordlist(dictionary, nBuckets); }
+FICL_PLATFORM_EXTERN void dictDelete (ficlDictionary *dictionary) { ficlDictionaryDestroy(dictionary); }
+FICL_PLATFORM_EXTERN void dictEmpty (ficlDictionary *dictionary, unsigned nHash) { ficlDictionaryEmpty(dictionary, nHash); }
+#if FICL_WANT_FLOAT
+FICL_PLATFORM_EXTERN void ficlPrimitiveHashSummary(ficlVm *vm);
+FICL_PLATFORM_EXTERN void dictHashSummary(ficlVm *vm) { ficlPrimitiveHashSummary(vm); }
+#endif
+FICL_PLATFORM_EXTERN int dictIncludes (ficlDictionary *dictionary, void *p) { return ficlDictionaryIncludes(dictionary, p); }
+FICL_PLATFORM_EXTERN ficlWord *dictLookup (ficlDictionary *dictionary, ficlString name) { return ficlDictionaryLookup(dictionary, name); }
+#if FICL_WANT_LOCALS
+FICL_PLATFORM_EXTERN ficlWord *ficlLookupLoc (ficlSystem *system, ficlString name) { return ficlDictionaryLookup(ficlSystemGetLocals(system), name); }
+#endif
+FICL_PLATFORM_EXTERN void dictResetSearchOrder(ficlDictionary *dictionary) { ficlDictionaryResetSearchOrder(dictionary); }
+FICL_PLATFORM_EXTERN void dictSetFlags (ficlDictionary *dictionary, ficlUnsigned8 set, ficlUnsigned8 clear) { ficlDictionarySetFlags(dictionary, set); ficlDictionaryClearFlags(dictionary, clear); }
+FICL_PLATFORM_EXTERN void dictSetImmediate(ficlDictionary *dictionary) { ficlDictionarySetImmediate(dictionary); }
+FICL_PLATFORM_EXTERN void dictUnsmudge (ficlDictionary *dictionary) { ficlDictionaryUnsmudge(dictionary); }
+FICL_PLATFORM_EXTERN ficlCell *dictWhere (ficlDictionary *dictionary) { return ficlDictionaryWhere(dictionary); }
+
+FICL_PLATFORM_EXTERN int ficlAddParseStep(ficlSystem *system, ficlWord *word) { return ficlSystemAddParseStep(system, word); }
+FICL_PLATFORM_EXTERN void ficlAddPrecompiledParseStep(ficlSystem *system, char *name, ficlParseStep pStep) { ficlSystemAddPrimitiveParseStep(system, name, pStep); }
+FICL_PLATFORM_EXTERN void ficlPrimitiveParseStepList(ficlVm *vm);
+FICL_PLATFORM_EXTERN void ficlListParseSteps(ficlVm *vm) { ficlPrimitiveParseStepList(vm); }
+
+FICL_PLATFORM_EXTERN void ficlTermSystem(ficlSystem *system) { ficlSystemDestroy(system); }
+FICL_PLATFORM_EXTERN int ficlEvaluate(ficlVm *vm, char *pText) { return ficlVmEvaluate(vm, pText); }
+FICL_PLATFORM_EXTERN int ficlExec (ficlVm *vm, char *pText) { ficlString s; FICL_STRING_SET_FROM_CSTRING(s, pText); return ficlVmExecuteString(vm, s); }
+FICL_PLATFORM_EXTERN int ficlExecC(ficlVm *vm, char *pText, ficlInteger nChars) { ficlString s; FICL_STRING_SET_POINTER(s, pText); FICL_STRING_SET_LENGTH(s, nChars); return ficlVmExecuteString(vm, s); }
+FICL_PLATFORM_EXTERN int ficlExecXT(ficlVm *vm, ficlWord *word) { return ficlVmExecuteXT(vm, word); }
+FICL_PLATFORM_EXTERN void ficlFreeVM(ficlVm *vm) { ficlVmDestroy(vm); }
+
+
+
+
+
+static void thunkTextOut(ficlCallback *callback, char *text)
+ {
+ ficlCompatibilityOutputFunction outputFunction;
+ if ((callback->vm != NULL) && (callback->vm->thunkedTextout != NULL))
+ outputFunction = callback->system->thunkedTextout;
+ else if (callback->system->thunkedTextout != NULL)
+ outputFunction = callback->system->thunkedTextout;
+ else
+ {
+ ficlCallbackDefaultTextOut(callback, text);
+ return;
+ }
+ ficlCompatibilityTextOutCallback(callback, text, outputFunction);
+ }
+
+
+FICL_PLATFORM_EXTERN void vmSetTextOut(ficlVm *vm, ficlCompatibilityOutputFunction textOut)
+ {
+ vm->thunkedTextout = textOut;
+ ficlVmSetTextOut(vm, thunkTextOut);
+ }
+
+FICL_PLATFORM_EXTERN void vmTextOut (ficlVm *vm, char *text, int fNewline)
+ {
+ ficlVmTextOut(vm, text);
+ if (fNewline)
+ ficlVmTextOut(vm, "\n");
+ }
+
+
+FICL_PLATFORM_EXTERN void ficlTextOut (ficlVm *vm, char *text, int fNewline)
+ {
+ vmTextOut(vm, text, fNewline);
+ }
+
+extern ficlSystem *ficlSystemGlobal;
+static defaultStackSize = FICL_DEFAULT_STACK_SIZE;
+FICL_PLATFORM_EXTERN int ficlSetStackSize(int nStackCells)
+{
+ if (defaultStackSize < nStackCells)
+ defaultStackSize = nStackCells;
+ if ((ficlSystemGlobal != NULL) && (ficlSystemGlobal->stackSize < nStackCells))
+ ficlSystemGlobal->stackSize = nStackCells;
+ return defaultStackSize;
+}
+
+
+FICL_PLATFORM_EXTERN ficlSystem *ficlInitSystemEx(ficlSystemInformation *fsi)
+{
+ ficlSystem *returnValue;
+ ficlCompatibilityOutputFunction thunkedTextout;
+ ficlSystemInformation clone;
+
+ memcpy(&clone, fsi, sizeof(clone));
+ thunkedTextout = (ficlCompatibilityOutputFunction)clone.textOut;
+ clone.textOut = clone.errorOut = thunkTextOut;
+
+ returnValue = ficlSystemCreate(&clone);
+ if (returnValue != NULL)
+ {
+ returnValue->thunkedTextout = thunkedTextout;
+ }
+ return returnValue;
+}
+
+
+FICL_PLATFORM_EXTERN ficlSystem *ficlInitSystem(int nDictCells)
+{
+ ficlSystemInformation fsi;
+ ficlSystemInformationInitialize(&fsi);
+ fsi.dictionarySize = nDictCells;
+ if (fsi.stackSize < defaultStackSize)
+ fsi.stackSize = defaultStackSize;
+ return ficlSystemCreate(&fsi);
+}
+
+
+
+
+FICL_PLATFORM_EXTERN ficlVm *ficlNewVM(ficlSystem *system)
+{
+ ficlVm *returnValue = ficlSystemCreateVm(system);
+ if (returnValue != NULL)
+ {
+ if ((returnValue->callback.textOut != NULL) && (returnValue->callback.textOut != thunkTextOut))
+ {
+ returnValue->thunkedTextout = (ficlCompatibilityOutputFunction)returnValue->callback.textOut;
+ returnValue->callback.textOut = thunkTextOut;
+ }
+ if ((returnValue->callback.errorOut != NULL) && (returnValue->callback.errorOut != thunkTextOut))
+ {
+ if (returnValue->thunkedTextout == NULL)
+ returnValue->thunkedTextout = (ficlCompatibilityOutputFunction)returnValue->callback.errorOut;
+ returnValue->callback.errorOut = thunkTextOut;
+ }
+ }
+ return returnValue;
+}
+
+
+
+FICL_PLATFORM_EXTERN ficlWord *ficlLookup(ficlSystem *system, char *name) { return ficlSystemLookup(system, name); }
+FICL_PLATFORM_EXTERN ficlDictionary *ficlGetDict(ficlSystem *system) { return ficlSystemGetDictionary(system); }
+FICL_PLATFORM_EXTERN ficlDictionary *ficlGetEnv (ficlSystem *system) { return ficlSystemGetEnvironment(system); }
+FICL_PLATFORM_EXTERN void ficlSetEnv (ficlSystem *system, char *name, ficlInteger value) { ficlDictionarySetConstant(ficlSystemGetDictionary(system), name, value); }
+FICL_PLATFORM_EXTERN void ficlSetEnvD(ficlSystem *system, char *name, ficlInteger high, ficlInteger low) { ficl2Unsigned value; FICL_2UNSIGNED_SET(low, high, value); ficlDictionarySet2Constant(ficlSystemGetDictionary(system), name, FICL_2UNSIGNED_TO_2INTEGER(value)); }
+#if FICL_WANT_LOCALS
+FICL_PLATFORM_EXTERN ficlDictionary *ficlGetLoc (ficlSystem *system) { return ficlSystemGetLocals(system); }
+#endif
+FICL_PLATFORM_EXTERN int ficlBuild(ficlSystem *system, char *name, ficlPrimitive code, char flags) { ficlDictionary *dictionary = ficlSystemGetDictionary(system); ficlDictionaryLock(dictionary, FICL_TRUE); ficlDictionaryAppendPrimitive(dictionary, name, code, flags); ficlDictionaryLock(dictionary, FICL_FALSE); return 0; }
+FICL_PLATFORM_EXTERN void ficlCompileCore(ficlSystem *system) { ficlSystemCompileCore(system); }
+FICL_PLATFORM_EXTERN void ficlCompilePrefix(ficlSystem *system) { ficlSystemCompilePrefix(system); }
+FICL_PLATFORM_EXTERN void ficlCompileSearch(ficlSystem *system) { ficlSystemCompileSearch(system); }
+FICL_PLATFORM_EXTERN void ficlCompileSoftCore(ficlSystem *system) { ficlSystemCompileSoftCore(system); }
+FICL_PLATFORM_EXTERN void ficlCompileTools(ficlSystem *system) { ficlSystemCompileTools(system); }
+FICL_PLATFORM_EXTERN void ficlCompileFile(ficlSystem *system) { ficlSystemCompileFile(system); }
+#if FICL_WANT_FLOAT
+FICL_PLATFORM_EXTERN void ficlCompileFloat(ficlSystem *system) { ficlSystemCompileFloat(system); }
+FICL_PLATFORM_EXTERN int ficlParseFloatNumber( ficlVm *vm, ficlString string) { return ficlVmParseFloatNumber(vm, string); }
+#endif
+#if FICL_WANT_PLATFORM
+FICL_PLATFORM_EXTERN void ficlCompilePlatform(ficlSystem *system) { ficlSystemCompilePlatform(system); }
+#endif
+FICL_PLATFORM_EXTERN int ficlParsePrefix(ficlVm *vm, ficlString string) { return ficlVmParsePrefix(vm, string); }
+
+FICL_PLATFORM_EXTERN int ficlParseNumber(ficlVm *vm, ficlString string) { return ficlVmParseNumber(vm, string); }
+FICL_PLATFORM_EXTERN void ficlTick(ficlVm *vm) { ficlPrimitiveTick(vm); }
+FICL_PLATFORM_EXTERN void parseStepParen(ficlVm *vm) { ficlPrimitiveParseStepParen(vm); }
+
+FICL_PLATFORM_EXTERN int isAFiclWord(ficlDictionary *dictionary, ficlWord *word) { return ficlDictionaryIsAWord(dictionary, word); }
+
+
+FICL_PLATFORM_EXTERN void buildTestInterface(ficlSystem *system) { ficlSystemCompileExtras(system); }
+
+
diff --git a/contrib/xclasses/readme.txt b/contrib/xclasses/readme.txt
new file mode 100644
index 000000000000..1bd49d689a98
--- /dev/null
+++ b/contrib/xclasses/readme.txt
@@ -0,0 +1,111 @@
+XClasses is a simple IDL written in Python.
+You declare your classes, methods, and members as Python objects,
+and XClasses will generate the .c, .h, and .f files for you.
+Not only do the Forth classes line up with their C counterparts
+exactly, but all non-static methods (virtual and non-virtual)
+are *automatically* thunked. In other words, any method
+declared in XClasses and implemented in C can be called from
+the matching Ficl class, and the C method will be automatically
+called with the correct arguments. XClasses handles floating-point
+arguments too!
+
+Known limitations:
+ * All arguments must be one cell wide. (That means
+ only single-precision floats, too.)
+
+
+
+To use:
+ * Declare all your classes in a .py script
+ * Include "xclasses.h" everywhere you need your classes
+ * Include xclasses.cpp in your project somewhere
+ * Call
+ "xclasses.f" included
+ from your Ficl initialization script
+
+And you're mostly done!
+
+Simply including xclasses.f is not enough, though. You must
+explicitly instantiate your classes. This is to allow you a
+chance to add your own methods to the class. For a class
+named "myCallback", it would look like this:
+
+ declare-myCallback
+ end-myCallback
+
+You also have to define the "init" function for the class.
+Most of the time this will work fine:
+
+ declare-myCallback
+ use-default-init
+ end-myCallback
+
+
+The "default" init function calls the super class's init
+function, then sets all data members to 0. If this isn't
+what you want, roll your own. The init function takes
+the usual 2-cell "this" pointer as its argument:
+
+ declare-myCallback
+ : init ( 2:this ) ...
+ ;
+ end-myCallback
+
+For a do-nothing init function, you'll want this:
+
+ declare-myCallback
+ : init 2drop ;
+ end-myCallback
+
+
+Here's a random example from the simple game I'm working on:
+
+-----------------------------------------------------------------
+skinStream = xMethod("stream", "void").setVirtual(1)
+gjeSkin.addMethod(skinStream)
+
+##
+## gjeTexture
+##
+##
+gjeTexture = xClass("gjeTexture")
+gjeTexture.setParent(gjeSkin)
+gjeTexture.addMethod(skinStream)
+gjeTexture.addMethod(xMethod("clear", "void"))
+gjeTexture.addMember(xVariable("texture", "LPDIRECT3DTEXTURE8"))
+gjeTexture.addMember(xVariable("name", "char *"))
+gjeTexture.addMember(xVariable("variation", "int"))
+gjeTexture.addMember(xVariable("material", "D3DMATERIAL8 *"))
+
+-----------------------------------------------------------------
+
+I sure hope that's enough to get you started.
+
+
+
+Random notes:
+* XClasses doesn't deal well with struct-packing issues. It assumes
+ pretty much everything will be 4-byte aligned. This can bite you
+ if you add a 64-bit int... the C compiler may align it for you,
+ and XClasses won't know about it. (This could be fixed in a future
+ release... are you volunteering?) For now, it's best to declare
+ your classes such that 64-bit ints are naturally 8-byte aligned.
+
+* If you don't want to have to declare each class in turn,
+ you can add something like this to the end of your Python script:
+-----
+def declare(name):
+ xAddFiclFooter("\t\"" + name + ".constant\" \" sfind swap drop 0= [if] declare-" + name + " use-default-init end-" + name + " [endif] \" evaluate")
+
+
+xAddFiclFooter(": xclassesDeclare")
+for c in classes:
+ declare(c.name)
+xAddFiclFooter("\t;")
+-----
+ and then call "xclassesDeclare" from your Ficl script just after
+ including "xclasses.f".
+
+
+--lch
+larry@hastings.org
diff --git a/contrib/xclasses/xclasses.py b/contrib/xclasses/xclasses.py
new file mode 100644
index 000000000000..eaf449b19a27
--- /dev/null
+++ b/contrib/xclasses/xclasses.py
@@ -0,0 +1,870 @@
+import copy
+import string
+import sys
+import time
+import types
+
+
+def capitalize(s):
+ return string.upper(s[0]) + s[1:]
+
+def fprint(f, s):
+ print >> f, s
+
+
+def fprintHeader(f, comment = "//"):
+ fprint(f, comment)
+ fprint(f, comment + " Generated by xclasses.py at " + time.strftime("%Y/%m/%d %H:%M:%S"))
+ fprint(f, comment)
+ fprint(f, comment)
+ fprint(f, "")
+
+def fprintFooter(f, comment = "//"):
+ fprint(f, "")
+ fprint(f, "")
+ fprint(f, comment + " end of file")
+ fprint(f, "")
+
+multicallCallTypeFunction = 0
+multicallCallTypeMethod = 1
+multicallCallTypeVirtualMethod = 2
+
+multicallReturnTypeVoid = 0
+multicallReturnTypeInteger = 16
+multicallReturnTypeCstring = 32
+multicallReturnTypeFloat = 48
+
+multicallExplicitVtable = 512
+
+
+ficlVmName = "ficlVm"
+
+h_headers = []
+def xAddHHeader(line):
+ h_headers.append(line)
+
+h_footers = []
+def xAddHFooter(line):
+ h_footers.append(line)
+
+ficl_headers = []
+def xAddFiclHeader(line):
+ ficl_headers.append(line)
+
+ficl_footers = []
+def xAddFiclFooter(line):
+ ficl_footers.append(line)
+
+c_headers = []
+def xAddCHeader(line):
+ c_headers.append(line)
+
+c_footers = []
+def xAddCFooter(line):
+ c_footers.append(line)
+
+
+classes = []
+
+class xVariable:
+ def __init__(self, name, typeCPP = None, cells = None, count = None, defaultValue = None, cstring = None):
+ self.comments = []
+ self.setName(name)
+ self.setCells(cells)
+ self.setCount(count)
+ self.setDefaultValue(defaultValue)
+ self.setCString(cstring)
+ self.setTypeCPP(typeCPP)
+
+ def setName(self, name):
+ self.name = name
+ return self
+
+ def setTypeCPP(self, typeCPP):
+ self.typeCPP = typeCPP
+ if (typeCPP == "char *"):
+ self.setCString(1)
+ return self
+
+ def setCells(self, cells):
+ if cells == None:
+ self.cells = 1
+ else:
+ self.cells = cells
+ return self
+
+ def setCString(self, cstring):
+ self.cstring = cstring
+ return self
+
+ def isCString(self):
+ return self.cstring
+
+ def getTotalSize(self):
+ return self.cells * self.count
+
+ def setCount(self, count):
+ if type(count) != types.IntType:
+ count = 1
+ self.count = count
+ return self
+
+ def setDefaultValue(self, defaultValue):
+ if (defaultValue != None) and (type(defaultValue) != types.StringType):
+ defaultValue = str(defaultValue)
+ self.defaultValue = defaultValue
+ return self
+
+ def addComment(self, c):
+ self.comments.append(c)
+ return self
+
+ def isFloat(self):
+ return self.typeCPP == "float"
+
+ def stringCPP(self, wantDefaultValues=1):
+ if (type(self.typeCPP) != types.StringType):
+ sys.exit("didn't set a CPP type on variable " + self.name + "!")
+ output = self.typeCPP
+ if (self.typeCPP[-1] != "*") and (self.typeCPP[-1] != "&"):
+ output += " "
+ output += self.name
+ if self.count > 1:
+ output += "[" + str(self.count) + "]"
+ if self.count == 0:
+ output += "[]"
+ if wantDefaultValues and (self.defaultValue != None):
+ output += " = " + self.defaultValue
+ return output
+
+ def printH(self, f):
+ if len(self.comments):
+ for comment in self.comments:
+ fprint(f, "\t" + "// " + comment)
+ fprint(f, "\t" + self.stringCPP() + ";")
+
+ def printF(self, f):
+ totalCells = self.count * self.cells
+ if (totalCells <= 1):
+ typeF = "cell:"
+ else:
+ typeF = str(totalCells) + " cells:"
+ if len(self.comments):
+ for comment in self.comments:
+ fprint(f, "\t" + "// " + comment)
+ fprint(f, "\t" + "S\" " + typeF + " ." + self.name + " \" evaluate")
+
+
+class xMethod:
+ def __init__(self, name, returnType = None, virtual = None, static = None, body = None):
+ self.arguments = []
+ self.comments = []
+
+ self.setName(name)
+ self.setReturnType(returnType)
+ self.setVirtual(virtual)
+ self.setStatic(static)
+ self.setBody(body)
+ self.setThunkVariable(None)
+ self.vtableOffset = 0
+
+ def copy():
+ clone = xMethod(self.name, self.returnType, self.virtual, self.static)
+ clone.arguments = self.arguments
+ clone.comments = self.comments
+
+ def setName(self, name):
+ self.name = name
+ return self
+
+ def setReturnType(self, returnType):
+ if returnType.__class__ == xVariable:
+ self.returnType = returnType
+ elif type(returnType) == types.StringType:
+ self.returnType = xVariable("ignored", returnType)
+ else:
+ self.returnType = None
+ return self
+
+ def returnTypeIsVoid(self):
+ return(self.returnType == None) or (self.returnType.typeCPP == None) or (self.returnType.typeCPP == "") or (self.returnType.typeCPP == "void")
+
+ def setVirtual(self, virtual):
+ self.virtual = virtual
+ return self
+
+ def isVirtual(self):
+ return self.virtual > 0
+
+ def isPureVirtual(self):
+ return self.virtual > 1
+
+ def setStatic(self, static):
+ self.static = static
+ return self
+
+ def setThunkVariable(self, thunkVariable):
+ self.thunkVariable = thunkVariable
+ return self
+
+ def isStatic(self):
+ return self.static
+
+ # a constructor or a destructor
+ def isClassSpecial(self):
+ return (self.returnType == None) or (self.returnType.typeCPP == None) or (self.returnType.typeCPP == "")
+
+ def setBody(self, body):
+ self.body = body
+ return self
+
+ def addArgument(self, argument):
+ self.arguments.append(argument)
+ return self
+
+ def addComment(self, c):
+ self.comments.append(c)
+ return self
+
+ def prototype(self, isDefinition=None):
+ arguments = ""
+ for a in self.arguments:
+ if len(arguments):
+ arguments += ", "
+ arguments += a.stringCPP(not isDefinition)
+
+ if len(arguments) == 0:
+ arguments = "void"
+ className = ""
+ if (isDefinition):
+ className = self.memberOf.name + "::"
+ modifiers = ""
+ if self.virtual and (not isDefinition):
+ modifiers += "virtual "
+ if self.static and (not isDefinition):
+ modifiers += "static "
+ returnType = ""
+ name = self.name
+ if (name == "") or (name == "~"):
+ name += self.memberOf.name
+ if (self.returnType != None) and (len(self.returnType.typeCPP) > 0):
+ returnType = self.returnType.typeCPP + " "
+ return modifiers + returnType + className + name + "(" + arguments + ")"
+
+ def printH(self, f):
+ pureVirtual = ""
+ if (self.virtual > 1):
+ pureVirtual = " = 0"
+ suffix = ";"
+ modifiers = ""
+ if self.body != None:
+ modifiers = "inline "
+ suffix = " " + self.body
+ fprint(f, "\t" + modifiers + self.prototype() + pureVirtual + suffix)
+
+ def printF(self, f):
+ if not self.isVirtual():
+ return
+
+ if len(self.comments):
+ for comment in self.comments:
+ fprint(f, "\t" + "// " + comment)
+
+ flags = multicallReturnTypeInteger
+ if self.returnTypeIsVoid():
+ flags = multicallReturnTypeVoid
+ elif (self.returnType.isCString()):
+ flags = multicallReturnTypeCString
+ elif (self.returnType.typeCPP == "float"):
+ flags = multicallReturnTypeFloat
+ flags |= multicallCallTypeVirtualMethod
+ # move floating-point arguments from float stack
+ floatArgumentsBitfield = 0
+ cstringArgumentsBitfield = 0
+ argumentNumber = 0
+ cstrings = 0
+ name = self.name
+ if (self.memberOf.pureVirtual):
+ vtable = ""
+ else:
+ vtable = " drop [ " + self.memberOf.name + "-vtable literal ] "
+ flags |= multicallExplicitVtable
+ if (name == "") or (name == "~"):
+ name += self.memberOf.name
+ for a in self.arguments:
+ if a.isFloat():
+ floatArgumentsBitfield |= (1 << argumentNumber)
+ elif a.isCString():
+ cstringArgumentsBitfield |= (1 << argumentNumber)
+ cstrings += 1
+ argumentNumber += 1
+ fprint(f, "\tS\" : " + name + vtable + str(len(self.arguments) + cstrings) + " " + str(floatArgumentsBitfield) + " " + str(cstringArgumentsBitfield) + " " + str(self.vtableOffset) + " " + str(flags) + " multicall ; \" evaluate ")
+
+ def printCPP(self, f):
+ if (self.thunkVariable != None):
+ if (self.returnType != None) and (self.returnType.isCString()):
+ sys.exit("Can't thunk char * return values, sorry.")
+ fprint(f, "")
+ fprint(f, self.prototype(1))
+ fprint(f, "\t{")
+ fprint(f, "\tif (" + self.thunkVariable.name + " == NULL)")
+ if self.isClassSpecial() or self.returnTypeIsVoid():
+ fprint(f, "\t\treturn;")
+ elif (self.returnType.isFloat()):
+ fprint(f, "\t\treturn 0.0f;")
+ else:
+ fprint(f, "\t\treturn (" + self.returnType.typeCPP + ")0;")
+ fprint(f, "")
+
+ ficlVmName = self.memberOf.getFiclVmName()
+
+ ## output stack-checking code! how cool is that? --lch
+ dataStackPush = 2 # why 2? we always push this and ficlClass.
+ dataStackPop = 0
+ floatStackPush = 0
+ floatStackPop = 0
+
+ for a in self.arguments:
+ if (a.isCString()):
+ dataStackPush = dataStackPush + 2
+ elif (a.isFloat()):
+ floatStackPush = floatStackPush + 1
+ else:
+ dataStackPush = dataStackPush + 1
+
+ if (not self.returnTypeIsVoid()):
+ if (self.returnType.isFloat()):
+ floatStackPop = 1
+ else:
+ dataStackPop = 1
+
+ if (dataStackPush or dataStackPop or floatStackPush or floatStackPop):
+ fprint(f, "#ifdef _DEBUG")
+ if (dataStackPush or dataStackPop):
+ fprint(f, "\tficlStackCheck(" + ficlVmName + "->dataStack, " + str(dataStackPush) + ", " + str(dataStackPop) + ");")
+ if (floatStackPush or floatStackPop):
+ fprint(f, "\tficlStackCheck(" + ficlVmName + "->floatStack, " + str(floatStackPush) + ", " + str(floatStackPop) + ");")
+ fprint(f, "#endif // _DEBUG")
+
+ reversedArguments = copy.copy(self.arguments)
+ reversedArguments.reverse()
+
+ for a in reversedArguments:
+ if (a.isCString()):
+ fprint(f, "\tficlStackPushPointer(" + ficlVmName + "->dataStack, " + a.name + ");")
+ fprint(f, "\tficlStackPushInteger(" + ficlVmName + "->dataStack, strlen(" + a.name + "));")
+ elif (a.isFloat()):
+ fprint(f, "\tficlStackPushFloat(" + ficlVmName + "->floatStack, " + a.name + ");")
+ else:
+ fprint(f, "\tficlStackPushInteger(" + ficlVmName + "->dataStack, (int)" + a.name + ");")
+ fprint(f, "\tficlStackPushPointer(" + ficlVmName + "->dataStack, this);")
+ fprint(f, "\tficlStackPushPointer(" + ficlVmName + "->dataStack, ficlClass);")
+ fprint(f, "\tficlVmExecuteXT(" + ficlVmName + ", " + self.thunkVariable.name + ");")
+ if (not self.returnTypeIsVoid()):
+ if (self.returnType.isFloat()):
+ fprint(f, "\treturn ficlStackPopFloat(" + ficlVmName + "->floatStack);")
+ else:
+ fprint(f, "\treturn (" + self.returnType.typeCPP + ")ficlStackPopInteger(" + ficlVmName + "->dataStack);")
+ fprint(f, "\t}")
+ fprint(f, "")
+
+ # don't do virtual functions
+ if self.isVirtual() or self.isClassSpecial():
+ return
+
+ name = self.name
+ if (name == "") or (name == "~"):
+ name += self.memberOf.name
+
+ fprint(f, "// " + self.memberOf.name + "::" + name)
+ if len(self.comments):
+ fprint(f, "\t" + "//")
+ for comment in self.comments:
+ fprint(f, "\t" + "// " + comment)
+
+ arguments = ""
+ for a in self.arguments:
+ if len(arguments):
+ arguments += ", "
+ arguments += a.stringCPP()
+
+ if len(arguments) == 0:
+ arguments = "void"
+ classModifier = self.memberOf.name + "::"
+ calltype = "FICL_MULTICALL_CALLTYPE_METHOD"
+ if self.isStatic():
+ classModifier = ""
+ calltype = "FICL_MULTICALL_CALLTYPE_FUNCTION"
+ returnString = "FICL_MULTICALL_RETURNTYPE_INTEGER"
+ if self.returnTypeIsVoid():
+ returnString = "FICL_MULTICALL_RETURNTYPE_VOID"
+ elif (self.returnType.typeCPP == "float"):
+ returnString = "FICL_MULTICALL_RETURNTYPE_FLOAT"
+ elif (self.returnType.isCString()):
+ returnString = "FICL_MULTICALL_RETURNTYPE_CSTRING"
+
+ # set bits in argumentFlags
+ floatArgumentsBitfield = 0
+ cstringArgumentsBitfield = 0
+ argumentNumber = 0
+ cstrings = 0
+ for a in self.arguments:
+ if a.isFloat():
+ floatArgumentsBitfield |= (1 << argumentNumber)
+ elif a.isCString():
+ cstringArgumentsBitfield |= (1 << argumentNumber)
+ cstrings += 1
+ argumentNumber += 1
+
+ uniqueSuffix = "_" + self.memberOf.name + "_" + name
+ # constructor is blank!
+ if (self.name == ""):
+ uniqueSuffix = "_" + self.memberOf.name + "_constructor"
+ # destructor is just a squiggle!
+ elif (self.name == "~"):
+ uniqueSuffix = "_" + self.memberOf.name + "_destructor"
+ printingHash = {}
+ printingHash["classname"] = "xMethod" + uniqueSuffix
+ printingHash["variablename"] = "instance" + uniqueSuffix
+ printingHash["address"] = self.returnType.typeCPP + " (" + classModifier + "*address)(" + arguments + ")"
+ printingHash["function"] = self.memberOf.name + "::" + name
+ printingHash["methodname"] = name
+ printingHash["argumentCount"] = str(len(self.arguments) + cstrings)
+ printingHash["floatArgumentsBitfield"] = str(floatArgumentsBitfield)
+ printingHash["cstringArgumentsBitfield"] = str(cstringArgumentsBitfield)
+ printingHash["flags"] = calltype + " | " + returnString
+ fprint(f, """
+struct %(classname)s
+ {
+ char *name;
+ int argumentCount;
+ int floatArgumentBitfield;
+ int cstringArgumentBitfield;
+ int flags;
+ %(address)s;
+ int zero;
+ };
+
+static %(classname)s %(variablename)s = { "%(methodname)s", %(argumentCount)s, %(floatArgumentsBitfield)s, %(cstringArgumentsBitfield)s, %(flags)s, %(function)s, 0 };
+""" % printingHash)
+
+
+
+
+
+class xClass:
+ def __init__(self, name):
+ self.members = []
+ self.methods = []
+ self.verbatim = []
+ self.name = name
+ self.superclass = None
+ self.superclassName = None
+ self.containsVtable = 0
+ self.vtableEntries = 0
+ self.firstMember = None
+ self.memberCellsTotal = 0
+ self.thunkedSubclass = None
+ self.pureVirtual = 0
+ self.setFiclVmName(None)
+ classes.append(self)
+
+
+ def subclassOf(self, superclass):
+ if type(superclass) == types.StringType:
+ self.superclassName = superclass
+ else:
+ self.superclass = superclass
+ self.superclassName = superclass.name
+ if superclass.containsVtable:
+ self.containsVtable = 2
+ self.pureVirtual = superclass.pureVirtual
+ self.vtableEntries = superclass.vtableEntries
+ else:
+ self.containsVtable = 0
+ return self
+
+ def thunkedSubclassOf(self, superclass):
+ self.subclassOf(superclass)
+ self.addMember(xVariable("ficlClass", "void *"))
+ for method in superclass.methods:
+ if not method.isClassSpecial() or method.isPureVirtual():
+ method = copy.deepcopy(method)
+ if method.isPureVirtual():
+ method.setVirtual(1)
+ self.addThunkedMethod(method)
+ self.constructor = xMethod("")
+ self.addMethod(self.constructor)
+ self.thunkedSubclass = 1
+ return self
+
+ def forwardDeclare(self):
+ xAddHHeader("class " + self.name + ";")
+
+
+ def addVerbatim(self, v):
+ self.verbatim.append(v)
+ return self
+
+ def addMember(self, variable):
+ self.members.append(variable)
+ self.memberCellsTotal += variable.getTotalSize()
+ if (self.firstMember == None):
+ self.firstMember = variable
+ return self
+
+ def removeMember(self, variable):
+ self.members.remove(variable)
+ self.memberCellsTotal -= variable.getTotalSize()
+ if (self.firstMember == variable):
+ self.firstMember = self.members[0]
+ return self
+
+ def addMemberArray(self, array):
+ map(self.addMember, copy.deepcopy(array))
+
+
+ def findPreviousInstanceOfVirtualMethod(self, name):
+ for method in self.methods:
+ if method.name == name:
+ return method
+ if (self.superclass != None) and (type(self.superclass) != types.StringType):
+ return self.superclass.findPreviousInstanceOfVirtualMethod(name)
+ return None
+
+ def setFiclVmName(self, name):
+ self.ficlVmName = name
+ return self
+
+ def getFiclVmName(self):
+ if self.ficlVmName != None:
+ return self.ficlVmName
+
+ global ficlVmName
+ return ficlVmName
+
+ def addMethod(self, method):
+ method.memberOf = self
+ if method.virtual:
+ previousInstance = self.findPreviousInstanceOfVirtualMethod(method.name)
+ if (previousInstance != None):
+ method.vtableOffset = previousInstance.vtableOffset
+ if previousInstance.isPureVirtual() and (not method.isPureVirtual()):
+ self.pureVirtual -= 1
+ else:
+ method.vtableOffset = self.vtableEntries
+ self.vtableEntries = self.vtableEntries + 1
+ if (not self.containsVtable):
+ self.containsVtable = 1
+ if method.isPureVirtual():
+ self.pureVirtual += 1
+ self.methods.append(method)
+ return self
+
+ def lookupMethod(self, methodName):
+ for m in self.methods:
+ if (m.name == methodName):
+ return m
+ return None
+
+ def removeMethod(self, method):
+ if (type(method) == types.StringType):
+ method = self.lookupMethod(method)
+ if method == None:
+ return None
+ method.memberOf = None
+ self.methods.remove(method)
+ if method.virtual:
+ previousInstance = self.findPreviousInstanceOfVirtualMethod(method.name)
+ if (previousInstance == None):
+ for m in self.methods:
+ if (m.vtableOffset >= method.vtableOffset):
+ m.vtableOffset = m.vtableOffset - 1
+ self.vtableEntries = self.vtableEntries - 1
+ if (self.vtableEntries == 0):
+ self.containsVtable = 0
+ if previousInstance.isPureVirtual() and (not method.isPureVirtual()):
+ self.pureVirtual += 1
+ else:
+ if method.isPureVirtual():
+ self.pureVirtual -= 1
+
+ if method.thunkVariable != None:
+ self.removeMember(method.thunkVariable)
+
+ return self
+
+ def addThunkedMethod(self, method):
+ method = copy.deepcopy(method)
+ self.addMethod(method)
+ name = capitalize(method.name)
+ if (method.isClassSpecial()):
+ if (name == ""):
+ name = "Constructor"
+ else:
+ name = "Destructor"
+ thunkVariable = xVariable("xt" + name, "ficlWord *")
+ self.addMember(thunkVariable)
+ method.setThunkVariable(thunkVariable)
+ return self
+
+ def addNoopConstructor(self):
+ self.addVerbatim(self.name + "() { }")
+ return self
+
+ def addConstructor(self, virtual = 0):
+ method = xMethod("")
+ method.setVirtual(virtual)
+ self.addMethod(method)
+ return method
+
+ def addDestructor(self, virtual = 0):
+ method = xMethod("~")
+ method.setVirtual(virtual)
+ self.addMethod(method)
+ return method
+
+ def addMemberWithAccessors(self, variable, writeBodiesToo = 1):
+ self.addMember(variable)
+ capitalizedName = capitalize(variable.name)
+
+ m = xMethod("set" + capitalizedName, "void").addArgument(variable)
+ if writeBodiesToo:
+ m.setBody("\t{ this->" + variable.name + " = " + variable.name + "; }")
+ self.addMethod(m)
+
+ m = xMethod("get" + capitalizedName, variable.typeCPP)
+ if writeBodiesToo:
+ m.setBody("\t{ return this->" + variable.name + "; }")
+ self.addMethod(m)
+
+ def addMethodArray(self, array):
+ map(self.addMethod, copy.deepcopy(array))
+
+ def addThunkedMethodArray(self, array):
+ map(self.addThunkedMethod, copy.deepcopy(array))
+
+ def printHforward(self, f):
+ fprint(f, "class " + self.name + ";")
+
+ def printH(self, f):
+ if (self.thunkedSubclass):
+ body = "\n\t\t{\n"
+ for m in self.methods:
+ if m.thunkVariable != None:
+ body += "\t\t" + m.thunkVariable.name + " = NULL;\n"
+ body += "\t\t}\n"
+ self.constructor.setBody(body)
+ s = ""
+ if self.superclassName != None:
+ s = " : public " + self.superclassName
+ fprint(f, "class " + self.name + s)
+ fprint(f, "\t" + "{")
+ fprint(f, "\t" + "public:")
+ fprint(f, "")
+ for member in self.members:
+ member.printH(f)
+ fprint(f, "")
+ for method in self.methods:
+ method.printH(f)
+ for v in self.verbatim:
+ fprint(f, "\t" + v + "\n")
+ fprint(f, "\t" + "};\n\n")
+
+ def printF(self, f):
+ s = self.superclassName
+ if s == None:
+ s = "object"
+
+ fprint(f, "")
+ fprint(f, "//")
+ fprint(f, "// " + self.name)
+ fprint(f, "//")
+ fprint(f, ": declare-" + self.name)
+ fprint(f, "\t" + "S\" " + s + " subclass " + self.name + " \" evaluate")
+ fprint(f, "")
+ if self.containsVtable == 1:
+ fprint(f, "\t" + "S\" cell: .vtable\" evaluate")
+ for member in self.members:
+ member.printF(f)
+ fprint(f, "")
+ if (self.firstMember == None):
+ fprint(f, "\t" + "S\" : default-init 2drop ; \" evaluate // no members!")
+ else:
+ storeFiclClass = ""
+ if (self.thunkedSubclass != None):
+ storeFiclClass = "this this my=> .ficlClass ! drop "
+ setVtable = ""
+ if self.containsVtable and (not self.pureVirtual):
+ setVtable = self.name + "-vtable this my=> .vtable ! "
+ fprint(f, "\t" + "S\" : default-init { 2:this -- } this my=> super my=> init this my=> ." + self.firstMember.name + " " + str(self.memberCellsTotal) + " cells 0 fill " + setVtable + storeFiclClass + "; \" evaluate")
+ fprint(f, "\t// " + self.name + " methods:")
+ fprint(f, "\t" + self.name + "-declare-methods")
+ for method in self.methods:
+ method.printF(f)
+ fprint(f, "\t;")
+ fprint(f, "")
+ fprint(f, ": end-" + self.name)
+ fprint(f, "\t" + "S\" end-class \" evaluate")
+ fprint(f, "\t" + "S\" " + self.name + " 2constant " + self.name + ".constant \" evaluate")
+ fprint(f, "\t;")
+ fprint(f, "")
+
+ def printCPP(self, f):
+ fprint(f, "//")
+ fprint(f, "// " + self.name)
+ fprint(f, "//")
+ for method in self.methods:
+ method.printCPP(f)
+ fprint(f, "")
+ fprint(f, "// " + self.name + " final structure")
+ fprint(f, "static xMethod *" + self.name + "_methods[] =")
+ fprint(f, "\t" + "{")
+ for method in self.methods:
+ if (method.isVirtual() or method.isClassSpecial()):
+ continue
+ fprint(f, "\t" + "(xMethod *)(&instance_" + self.name + "_" + method.name + "),")
+ fprint(f, "\t" + "NULL")
+ fprint(f, "\t" + "};")
+ if self.containsVtable and (not self.pureVirtual):
+ fprint(f, "")
+ fprint(f, "// " + self.name + " instance, so we can get the vtable")
+ fprint(f, "static " + self.name + " " + self.name + "_instance;" )
+ fprint(f, "")
+
+
+
+def xclassesFooter():
+ f = open("xclasses.h", "wt")
+
+ fprintHeader(f)
+ fprint(f, "#ifndef __XCLASSES_H")
+ fprint(f, "#define __XCLASSES_H")
+ fprint(f, "")
+ fprint(f, "extern void xclassesDefineMethods(ficlVm *vm);")
+ fprint(f, "")
+ fprint(f, "enum xtype");
+ fprint(f, "\t{");
+ fprint(f, "\txtypeInvalid = 0,");
+ for c in classes:
+ fprint(f, "\txtype_" + c.name + ",");
+ fprint(f, "\txtypeLast,");
+ fprint(f, "\t};");
+ fprint(f, "");
+ for line in h_headers:
+ fprint(f, line)
+ fprint(f, "")
+ fprint(f, "")
+ for c in classes:
+ c.printH(f)
+ for line in h_footers:
+ fprint(f, line)
+ fprint(f, "")
+ fprint(f, "#endif // __XCLASSES_H")
+ fprintFooter(f)
+ f.close()
+
+
+ f = open("xclasses.f", "wt")
+ fprintHeader(f)
+ fprint(f, ": use-default-init S\" : init { 2:this } this my=> super my=> init this my=> default-init ; \" evaluate ;");
+ for line in ficl_headers:
+ fprint(f, line)
+ fprint(f, "")
+ for c in classes:
+ c.printF(f)
+ for line in ficl_footers:
+ fprint(f, line)
+ fprint(f, "")
+ fprintFooter(f)
+ f.close()
+
+
+ f = open("xclasses.cpp", "wt")
+ fprintHeader(f)
+
+ for line in c_headers:
+ fprint(f, line)
+ fprint(f, "")
+
+ fprint(f, "#include \"xclasses.h\"")
+ fprint(f, """
+
+struct xMethod
+ {
+ char *name;
+ int argumentCount;
+ int floatArgumentBitfield;
+ int cstringArgumentBitfield;
+ int flags;
+ void *address;
+ int zero;
+ };
+
+struct xClass
+ {
+ char *name;
+ xMethod **methods;
+ void **instance;
+ };
+
+""")
+
+ for c in classes:
+ c.printCPP(f)
+ fprint(f, """
+static xClass classes[] =
+ {
+""")
+ for c in classes:
+ vtableVariable = "NULL"
+ if c.containsVtable and (not c.pureVirtual):
+ vtableVariable = "(void **)&" + c.name + "_instance"
+ fprint(f, "\t" + "{ \"" + c.name + "\", " + c.name + "_methods, " + vtableVariable + " },")
+ fprint(f, """
+ { NULL, NULL }
+ };
+
+void xclassesDefineMethods(ficlVm *vm)
+ {
+ char buffer[1024];
+ xClass *c;
+ xMethod **m;
+
+ for (c = classes; c->name != NULL; c++)
+ {
+ sprintf(buffer, " : %s-declare-methods ", c->name);
+ ficlVmEvaluate(vm, buffer);
+ for (m = c->methods; *m != NULL; m++)
+ {
+ xMethod *method = *m;
+ /* why is this here? I dunno, but MSVC seems to be packing my struct. So if address is zero, the next dword has the address. --lch */
+ if (method->address == NULL)
+ method->address = (void *)method->zero;
+ sprintf(buffer, " S\\" : %s drop %d %d %d %d %d multicall ; \\" evaluate ",
+ method->name,
+ method->argumentCount,
+ method->floatArgumentBitfield,
+ method->cstringArgumentBitfield,
+ method->address,
+ method->flags
+ );
+ ficlVmEvaluate(vm, buffer);
+ }
+ ficlVmEvaluate(vm, " ; ");
+ if (c->instance != NULL)
+ {
+ sprintf(buffer, "%s-vtable", c->name);
+ ficlDictionarySetConstantPointer(ficlVmGetDictionary(vm), buffer, *(c->instance));
+ }
+ }
+ }
+""")
+ for line in c_footers:
+ fprint(f, line)
+ fprint(f, "")
+ fprintFooter(f)
+ f.close()
+
+
+
diff --git a/dict.c b/dict.c
deleted file mode 100644
index 5f61c301555b..000000000000
--- a/dict.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/*******************************************************************
-** d i c t . c
-** Forth Inspired Command Language - dictionary methods
-** Author: John Sadler (john_sadler@alum.mit.edu)
-** Created: 19 July 1997
-** $Id: dict.c,v 1.12 2001-10-28 10:59:22-08 jsadler Exp jsadler $
-*******************************************************************/
-/*
-** This file implements the dictionary -- FICL's model of
-** memory management. All FICL words are stored in the
-** dictionary. A word is a named chunk of data with its
-** associated code. FICL treats all words the same, even
-** precompiled ones, so your words become first-class
-** extensions of the language. You can even define new
-** control structures.
-**
-** 29 jun 1998 (sadler) added variable sized hash table support
-*/
-/*
-** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
-** All rights reserved.
-**
-** Get the latest Ficl release at http://ficl.sourceforge.net
-**
-** I am interested in hearing from anyone who uses ficl. If you have
-** a problem, a success story, a defect, an enhancement request, or
-** if you would like to contribute to the ficl release, please
-** contact me by email at the address above.
-**
-** L I C E N S E and D I S C L A I M E R
-**
-** Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions
-** are met:
-** 1. Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** 2. Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in the
-** documentation and/or other materials provided with the distribution.
-**
-** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-** SUCH DAMAGE.
-*/
-
-#include <stdlib.h>
-#include <stdio.h> /* sprintf */
-#include <string.h>
-#include <ctype.h>
-#include "ficl.h"
-
-static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si);
-
-/**************************************************************************
- d i c t A b o r t D e f i n i t i o n
-** Abort a definition in process: reclaim its memory and unlink it
-** from the dictionary list. Assumes that there is a smudged
-** definition in process...otherwise does nothing.
-** NOTE: this function is not smart enough to unlink a word that
-** has been successfully defined (ie linked into a hash). It
-** only works for defs in process. If the def has been unsmudged,
-** nothing happens.
-**************************************************************************/
-void dictAbortDefinition(FICL_DICT *pDict)
-{
- FICL_WORD *pFW;
- ficlLockDictionary(TRUE);
- pFW = pDict->smudge;
-
- if (pFW->flags & FW_SMUDGE)
- pDict->here = (CELL *)pFW->name;
-
- ficlLockDictionary(FALSE);
- return;
-}
-
-
-/**************************************************************************
- a l i g n P t r
-** Aligns the given pointer to FICL_ALIGN address units.
-** Returns the aligned pointer value.
-**************************************************************************/
-void *alignPtr(void *ptr)
-{
-#if FICL_ALIGN > 0
- char *cp;
- CELL c;
- cp = (char *)ptr + FICL_ALIGN_ADD;
- c.p = (void *)cp;
- c.u = c.u & (~FICL_ALIGN_ADD);
- ptr = (CELL *)c.p;
-#endif
- return ptr;
-}
-
-
-/**************************************************************************
- d i c t A l i g n
-** Align the dictionary's free space pointer
-**************************************************************************/
-void dictAlign(FICL_DICT *pDict)
-{
- pDict->here = alignPtr(pDict->here);
-}
-
-
-/**************************************************************************
- d i c t A l l o t
-** Allocate or remove n chars of dictionary space, with
-** checks for underrun and overrun
-**************************************************************************/
-int dictAllot(FICL_DICT *pDict, int n)
-{
- char *cp = (char *)pDict->here;
-#if FICL_ROBUST
- if (n > 0)
- {
- if ((unsigned)n <= dictCellsAvail(pDict) * sizeof (CELL))
- cp += n;
- else
- return 1; /* dict is full */
- }
- else
- {
- n = -n;
- if ((unsigned)n <= dictCellsUsed(pDict) * sizeof (CELL))
- cp -= n;
- else /* prevent underflow */
- cp -= dictCellsUsed(pDict) * sizeof (CELL);
- }
-#else
- cp += n;
-#endif
- pDict->here = PTRtoCELL cp;
- return 0;
-}
-
-
-/**************************************************************************
- d i c t A l l o t C e l l s
-** Reserve space for the requested number of cells in the
-** dictionary. If nCells < 0 , removes space from the dictionary.
-**************************************************************************/
-int dictAllotCells(FICL_DICT *pDict, int nCells)
-{
-#if FICL_ROBUST
- if (nCells > 0)
- {
- if (nCells <= dictCellsAvail(pDict))
- pDict->here += nCells;
- else
- return 1; /* dict is full */
- }
- else
- {
- nCells = -nCells;
- if (nCells <= dictCellsUsed(pDict))
- pDict->here -= nCells;
- else /* prevent underflow */
- pDict->here -= dictCellsUsed(pDict);
- }
-#else
- pDict->here += nCells;
-#endif
- return 0;
-}
-
-
-/**************************************************************************
- d i c t A p p e n d C e l l
-** Append the specified cell to the dictionary
-**************************************************************************/
-void dictAppendCell(FICL_DICT *pDict, CELL c)
-{
- *pDict->here++ = c;
- return;
-}
-
-
-/**************************************************************************
- d i c t A p p e n d C h a r
-** Append the specified char to the dictionary
-**************************************************************************/
-void dictAppendChar(FICL_DICT *pDict, char c)
-{
- char *cp = (char *)pDict->here;
- *cp++ = c;
- pDict->here = PTRtoCELL cp;
- return;
-}
-
-
-/**************************************************************************
- d i c t A p p e n d W o r d
-** Create a new word in the dictionary with the specified
-** name, code, and flags. Name must be NULL-terminated.
-**************************************************************************/
-FICL_WORD *dictAppendWord(FICL_DICT *pDict,
- char *name,
- FICL_CODE pCode,
- UNS8 flags)
-{
- STRINGINFO si;
- SI_SETLEN(si, strlen(name));
- SI_SETPTR(si, name);
- return dictAppendWord2(pDict, si, pCode, flags);
-}
-
-
-/**************************************************************************
- d i c t A p p e n d W o r d 2
-** Create a new word in the dictionary with the specified
-** STRINGINFO, code, and flags. Does not require a NULL-terminated
-** name.
-**************************************************************************/
-FICL_WORD *dictAppendWord2(FICL_DICT *pDict,
- STRINGINFO si,
- FICL_CODE pCode,
- UNS8 flags)
-{
- FICL_COUNT len = (FICL_COUNT)SI_COUNT(si);
- char *pName;
- FICL_WORD *pFW;
-
- ficlLockDictionary(TRUE);
-
- /*
- ** NOTE: dictCopyName advances "here" as a side-effect.
- ** It must execute before pFW is initialized.
- */
- pName = dictCopyName(pDict, si);
- pFW = (FICL_WORD *)pDict->here;
- pDict->smudge = pFW;
- pFW->hash = hashHashCode(si);
- pFW->code = pCode;
- pFW->flags = (UNS8)(flags | FW_SMUDGE);
- pFW->nName = (char)len;
- pFW->name = pName;
- /*
- ** Point "here" to first cell of new word's param area...
- */
- pDict->here = pFW->param;
-
- if (!(flags & FW_SMUDGE))
- dictUnsmudge(pDict);
-
- ficlLockDictionary(FALSE);
- return pFW;
-}
-
-
-/**************************************************************************
- d i c t A p p e n d U N S
-** Append the specified FICL_UNS to the dictionary
-**************************************************************************/
-void dictAppendUNS(FICL_DICT *pDict, FICL_UNS u)
-{
- *pDict->here++ = LVALUEtoCELL(u);
- return;
-}
-
-
-/**************************************************************************
- d i c t C e l l s A v a i l
-** Returns the number of empty cells left in the dictionary
-**************************************************************************/
-int dictCellsAvail(FICL_DICT *pDict)
-{
- return pDict->size - dictCellsUsed(pDict);
-}
-
-
-/**************************************************************************
- d i c t C e l l s U s e d
-** Returns the number of cells consumed in the dicionary
-**************************************************************************/
-int dictCellsUsed(FICL_DICT *pDict)
-{
- return pDict->here - pDict->dict;
-}
-
-
-/**************************************************************************
- d i c t C h e c k
-** Checks the dictionary for corruption and throws appropriate
-** errors.
-** Input: +n number of ADDRESS UNITS (not Cells) proposed to allot
-** -n number of ADDRESS UNITS proposed to de-allot
-** 0 just do a consistency check
-**************************************************************************/
-void dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int n)
-{
- if ((n >= 0) && (dictCellsAvail(pDict) * (int)sizeof(CELL) < n))
- {
- vmThrowErr(pVM, "Error: dictionary full");
- }
-
- if ((n <= 0) && (dictCellsUsed(pDict) * (int)sizeof(CELL) < -n))
- {
- vmThrowErr(pVM, "Error: dictionary underflow");
- }
-
- if (pDict->nLists > FICL_DEFAULT_VOCS)
- {
- dictResetSearchOrder(pDict);
- vmThrowErr(pVM, "Error: search order overflow");
- }
- else if (pDict->nLists < 0)
- {
- dictResetSearchOrder(pDict);
- vmThrowErr(pVM, "Error: search order underflow");
- }
-
- return;
-}
-
-
-/**************************************************************************
- d i c t C o p y N a m e
-** Copy up to nFICLNAME characters of the name specified by si into
-** the dictionary starting at "here", then NULL-terminate the name,
-** point "here" to the next available byte, and return the address of
-** the beginning of the name. Used by dictAppendWord.
-** N O T E S :
-** 1. "here" is guaranteed to be aligned after this operation.
-** 2. If the string has zero length, align and return "here"
-**************************************************************************/
-static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si)
-{
- char *oldCP = (char *)pDict->here;
- char *cp = oldCP;
- char *name = SI_PTR(si);
- int i = SI_COUNT(si);
-
- if (i == 0)
- {
- dictAlign(pDict);
- return (char *)pDict->here;
- }
-
- if (i > nFICLNAME)
- i = nFICLNAME;
-
- for (; i > 0; --i)
- {
- *cp++ = *name++;
- }
-
- *cp++ = '\0';
-
- pDict->here = PTRtoCELL cp;
- dictAlign(pDict);
- return oldCP;
-}
-
-
-/**************************************************************************
- d i c t C r e a t e
-** Create and initialize a dictionary with the specified number
-** of cells capacity, and no hashing (hash size == 1).
-**************************************************************************/
-FICL_DICT *dictCreate(unsigned nCells)
-{
- return dictCreateHashed(nCells, 1);
-}
-
-
-FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash)
-{
- FICL_DICT *pDict;
- size_t nAlloc;
-
- nAlloc = sizeof (FICL_DICT) + nCells * sizeof (CELL)
- + sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *);
-
- pDict = ficlMalloc(nAlloc);
- assert(pDict);
-
- pDict->size = nCells;
- dictEmpty(pDict, nHash);
- return pDict;
-}
-
-
-/**************************************************************************
- d i c t C r e a t e W o r d l i s t
-** Create and initialize an anonymous wordlist
-**************************************************************************/
-FICL_HASH *dictCreateWordlist(FICL_DICT *dp, int nBuckets)
-{
- FICL_HASH *pHash;
-
- dictAlign(dp);
- pHash = (FICL_HASH *)dp->here;
- dictAllot(dp, sizeof (FICL_HASH)
- + (nBuckets-1) * sizeof (FICL_WORD *));
-
- pHash->size = nBuckets;
- hashReset(pHash);
- return pHash;
-}
-
-
-/**************************************************************************
- d i c t D e l e t e
-** Free all memory allocated for the given dictionary
-**************************************************************************/
-void dictDelete(FICL_DICT *pDict)
-{
- assert(pDict);
- ficlFree(pDict);
- return;
-}
-
-
-/**************************************************************************
- d i c t E m p t y
-** Empty the dictionary, reset its hash table, and reset its search order.
-** Clears and (re-)creates the hash table with the size specified by nHash.
-**************************************************************************/
-void dictEmpty(FICL_DICT *pDict, unsigned nHash)
-{
- FICL_HASH *pHash;
-
- pDict->here = pDict->dict;
-
- dictAlign(pDict);
- pHash = (FICL_HASH *)pDict->here;
- dictAllot(pDict,
- sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *));
-
- pHash->size = nHash;
- hashReset(pHash);
-
- pDict->pForthWords = pHash;
- pDict->smudge = NULL;
- dictResetSearchOrder(pDict);
- return;
-}
-
-
-/**************************************************************************
- d i c t H a s h S u m m a r y
-** Calculate a figure of merit for the dictionary hash table based
-** on the average search depth for all the words in the dictionary,
-** assuming uniform distribution of target keys. The figure of merit
-** is the ratio of the total search depth for all keys in the table
-** versus a theoretical optimum that would be achieved if the keys
-** were distributed into the table as evenly as possible.
-** The figure would be worse if the hash table used an open
-** addressing scheme (i.e. collisions resolved by searching the
-** table for an empty slot) for a given size table.
-**************************************************************************/
-#if FICL_WANT_FLOAT
-void dictHashSummary(FICL_VM *pVM)
-{
- FICL_DICT *dp = vmGetDict(pVM);
- FICL_HASH *pFHash;
- FICL_WORD **pHash;
- unsigned size;
- FICL_WORD *pFW;
- unsigned i;
- int nMax = 0;
- int nWords = 0;
- int nFilled;
- double avg = 0.0;
- double best;
- int nAvg, nRem, nDepth;
-
- dictCheck(dp, pVM, 0);
-
- pFHash = dp->pSearch[dp->nLists - 1];
- pHash = pFHash->table;
- size = pFHash->size;
- nFilled = size;
-
- for (i = 0; i < size; i++)
- {
- int n = 0;
- pFW = pHash[i];
-
- while (pFW)
- {
- ++n;
- ++nWords;
- pFW = pFW->link;
- }
-
- avg += (double)(n * (n+1)) / 2.0;
-
- if (n > nMax)
- nMax = n;
- if (n == 0)
- --nFilled;
- }
-
- /* Calc actual avg search depth for this hash */
- avg = avg / nWords;
-
- /* Calc best possible performance with this size hash */
- nAvg = nWords / size;
- nRem = nWords % size;
- nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem;
- best = (double)nDepth/nWords;
-
- sprintf(pVM->pad,
- "%d bins, %2.0f%% filled, Depth: Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%",
- size,
- (double)nFilled * 100.0 / size, nMax,
- avg,
- best,
- 100.0 * best / avg);
-
- ficlTextOut(pVM, pVM->pad, 1);
-
- return;
-}
-#endif
-
-/**************************************************************************
- d i c t I n c l u d e s
-** Returns TRUE iff the given pointer is within the address range of
-** the dictionary.
-**************************************************************************/
-int dictIncludes(FICL_DICT *pDict, void *p)
-{
- return ((p >= (void *) &pDict->dict)
- && (p < (void *)(&pDict->dict + pDict->size))
- );
-}
-
-
-/**************************************************************************
- d i c t L o o k u p
-** Find the FICL_WORD that matches the given name and length.
-** If found, returns the word's address. Otherwise returns NULL.
-** Uses the search order list to search multiple wordlists.
-**************************************************************************/
-FICL_WORD *dictLookup(FICL_DICT *pDict, STRINGINFO si)
-{
- FICL_WORD *pFW = NULL;
- FICL_HASH *pHash;
- int i;
- UNS16 hashCode = hashHashCode(si);
-
- assert(pDict);
-
- ficlLockDictionary(1);
-
- for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i)
- {
- pHash = pDict->pSearch[i];
- pFW = hashLookup(pHash, si, hashCode);
- }
-
- ficlLockDictionary(0);
- return pFW;
-}
-
-
-/**************************************************************************
- f i c l L o o k u p L o c
-** Same as dictLookup, but looks in system locals dictionary first...
-** Assumes locals dictionary has only one wordlist...
-**************************************************************************/
-#if FICL_WANT_LOCALS
-FICL_WORD *ficlLookupLoc(FICL_SYSTEM *pSys, STRINGINFO si)
-{
- FICL_WORD *pFW = NULL;
- FICL_DICT *pDict = pSys->dp;
- FICL_HASH *pHash = ficlGetLoc(pSys)->pForthWords;
- int i;
- UNS16 hashCode = hashHashCode(si);
-
- assert(pHash);
- assert(pDict);
-
- ficlLockDictionary(1);
- /*
- ** check the locals dict first...
- */
- pFW = hashLookup(pHash, si, hashCode);
-
- /*
- ** If no joy, (!pFW) --------------------------v
- ** iterate over the search list in the main dict
- */
- for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i)
- {
- pHash = pDict->pSearch[i];
- pFW = hashLookup(pHash, si, hashCode);
- }
-
- ficlLockDictionary(0);
- return pFW;
-}
-#endif
-
-
-/**************************************************************************
- d i c t R e s e t S e a r c h O r d e r
-** Initialize the dictionary search order list to sane state
-**************************************************************************/
-void dictResetSearchOrder(FICL_DICT *pDict)
-{
- assert(pDict);
- pDict->pCompile = pDict->pForthWords;
- pDict->nLists = 1;
- pDict->pSearch[0] = pDict->pForthWords;
- return;
-}
-
-
-/**************************************************************************
- d i c t S e t F l a g s
-** Changes the flags field of the most recently defined word:
-** Set all bits that are ones in the set parameter, clear all bits
-** that are ones in the clr parameter. Clear wins in case the same bit
-** is set in both parameters.
-**************************************************************************/
-void dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr)
-{
- assert(pDict->smudge);
- pDict->smudge->flags |= set;
- pDict->smudge->flags &= ~clr;
- return;
-}
-
-
-/**************************************************************************
- d i c t S e t I m m e d i a t e
-** Set the most recently defined word as IMMEDIATE
-**************************************************************************/
-void dictSetImmediate(FICL_DICT *pDict)
-{
- assert(pDict->smudge);
- pDict->smudge->flags |= FW_IMMEDIATE;
- return;
-}
-
-
-/**************************************************************************
- d i c t U n s m u d g e
-** Completes the definition of a word by linking it
-** into the main list
-**************************************************************************/
-void dictUnsmudge(FICL_DICT *pDict)
-{
- FICL_WORD *pFW = pDict->smudge;
- FICL_HASH *pHash = pDict->pCompile;
-
- assert(pHash);
- assert(pFW);
- /*
- ** :noname words never get linked into the list...
- */
- if (pFW->nName > 0)
- hashInsertWord(pHash, pFW);
- pFW->flags &= ~(FW_SMUDGE);
- return;
-}
-
-
-/**************************************************************************
- d i c t W h e r e
-** Returns the value of the HERE pointer -- the address
-** of the next free cell in the dictionary
-**************************************************************************/
-CELL *dictWhere(FICL_DICT *pDict)
-{
- return pDict->here;
-}
-
-
-/**************************************************************************
- h a s h F o r g e t
-** Unlink all words in the hash that have addresses greater than or
-** equal to the address supplied. Implementation factor for FORGET
-** and MARKER.
-**************************************************************************/
-void hashForget(FICL_HASH *pHash, void *where)
-{
- FICL_WORD *pWord;
- unsigned i;
-
- assert(pHash);
- assert(where);
-
- for (i = 0; i < pHash->size; i++)
- {
- pWord = pHash->table[i];
-
- while ((void *)pWord >= where)
- {
- pWord = pWord->link;
- }
-
- pHash->table[i] = pWord;
- }
-
- return;
-}
-
-
-/**************************************************************************
- h a s h H a s h C o d e
-**
-** Generate a 16 bit hashcode from a character string using a rolling
-** shift and add stolen from PJ Weinberger of Bell Labs fame. Case folds
-** the name before hashing it...
-** N O T E : If string has zero length, returns zero.
-**************************************************************************/
-UNS16 hashHashCode(STRINGINFO si)
-{
- /* hashPJW */
- UNS8 *cp;
- UNS16 code = (UNS16)si.count;
- UNS16 shift = 0;
-
- if (si.count == 0)
- return 0;
-
- /* changed to run without errors under Purify -- lch */
- for (cp = (UNS8 *)si.cp; si.count && *cp; cp++, si.count--)
- {
- code = (UNS16)((code << 4) + tolower(*cp));
- shift = (UNS16)(code & 0xf000);
- if (shift)
- {
- code ^= (UNS16)(shift >> 8);
- code ^= (UNS16)shift;
- }
- }
-
- return (UNS16)code;
-}
-
-
-
-
-/**************************************************************************
- h a s h I n s e r t W o r d
-** Put a word into the hash table using the word's hashcode as
-** an index (modulo the table size).
-**************************************************************************/
-void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW)
-{
- FICL_WORD **pList;
-
- assert(pHash);
- assert(pFW);
-
- if (pHash->size == 1)
- {
- pList = pHash->table;
- }
- else
- {
- pList = pHash->table + (pFW->hash % pHash->size);
- }
-
- pFW->link = *pList;
- *pList = pFW;
- return;
-}
-
-
-/**************************************************************************
- h a s h L o o k u p
-** Find a name in the hash table given the hashcode and text of the name.
-** Returns the address of the corresponding FICL_WORD if found,
-** otherwise NULL.
-** Note: outer loop on link field supports inheritance in wordlists.
-** It's not part of ANS Forth - ficl only. hashReset creates wordlists
-** with NULL link fields.
-**************************************************************************/
-FICL_WORD *hashLookup(FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode)
-{
- FICL_UNS nCmp = si.count;
- FICL_WORD *pFW;
- UNS16 hashIdx;
-
- if (nCmp > nFICLNAME)
- nCmp = nFICLNAME;
-
- for (; pHash != NULL; pHash = pHash->link)
- {
- if (pHash->size > 1)
- hashIdx = (UNS16)(hashCode % pHash->size);
- else /* avoid the modulo op for single threaded lists */
- hashIdx = 0;
-
- for (pFW = pHash->table[hashIdx]; pFW; pFW = pFW->link)
- {
- if ( (pFW->nName == si.count)
- && (!strincmp(si.cp, pFW->name, nCmp)) )
- return pFW;
-#if FICL_ROBUST
- assert(pFW != pFW->link);
-#endif
- }
- }
-
- return NULL;
-}
-
-
-/**************************************************************************
- h a s h R e s e t
-** Initialize a FICL_HASH to empty state.
-**************************************************************************/
-void hashReset(FICL_HASH *pHash)
-{
- unsigned i;
-
- assert(pHash);
-
- for (i = 0; i < pHash->size; i++)
- {
- pHash->table[i] = NULL;
- }
-
- pHash->link = NULL;
- pHash->name = NULL;
- return;
-}
-
-
diff --git a/dictionary.c b/dictionary.c
new file mode 100644
index 000000000000..9b4ddc3f3160
--- /dev/null
+++ b/dictionary.c
@@ -0,0 +1,851 @@
+/*******************************************************************
+** d i c t . c
+** Forth Inspired Command Language - dictionary methods
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 19 July 1997
+** $Id: dictionary.c,v 1.2 2010/09/12 15:14:52 asau Exp $
+*******************************************************************/
+/*
+** This file implements the dictionary -- Ficl's model of
+** memory management. All Ficl words are stored in the
+** dictionary. A word is a named chunk of data with its
+** associated code. Ficl treats all words the same, even
+** precompiled ones, so your words become first-class
+** extensions of the language. You can even define new
+** control structures.
+**
+** 29 jun 1998 (sadler) added variable sized hash table support
+*/
+/*
+** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+** All rights reserved.
+**
+** Get the latest Ficl release at http://ficl.sourceforge.net
+**
+** I am interested in hearing from anyone who uses Ficl. If you have
+** a problem, a success story, a defect, an enhancement request, or
+** if you would like to contribute to the Ficl release, please
+** contact me by email at the address above.
+**
+** L I C E N S E and D I S C L A I M E R
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+** 1. Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** 2. Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+** SUCH DAMAGE.
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ficl.h"
+
+#define FICL_SAFE_CALLBACK_FROM_SYSTEM(system) (((system) != NULL) ? &((system)->callback) : NULL)
+#define FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary) (((dictionary) != NULL) ? (dictionary)->system : NULL)
+#define FICL_DICTIONARY_ASSERT(dictionary, expression) FICL_SYSTEM_ASSERT(FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary), expression)
+
+/**************************************************************************
+ d i c t A b o r t D e f i n i t i o n
+** Abort a definition in process: reclaim its memory and unlink it
+** from the dictionary list. Assumes that there is a smudged
+** definition in process...otherwise does nothing.
+** NOTE: this function is not smart enough to unlink a word that
+** has been successfully defined (ie linked into a hash). It
+** only works for defs in process. If the def has been unsmudged,
+** nothing happens.
+**************************************************************************/
+void ficlDictionaryAbortDefinition(ficlDictionary *dictionary)
+{
+ ficlWord *word;
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+ word = dictionary->smudge;
+
+ if (word->flags & FICL_WORD_SMUDGED)
+ dictionary->here = (ficlCell *)word->name;
+
+ ficlDictionaryLock(dictionary, FICL_FALSE);
+ return;
+}
+
+
+/**************************************************************************
+ d i c t A l i g n
+** Align the dictionary's free space pointer
+**************************************************************************/
+void ficlDictionaryAlign(ficlDictionary *dictionary)
+{
+ dictionary->here = ficlAlignPointer(dictionary->here);
+}
+
+
+/**************************************************************************
+ d i c t A l l o t
+** Allocate or remove n chars of dictionary space, with
+** checks for underrun and overrun
+**************************************************************************/
+void ficlDictionaryAllot(ficlDictionary *dictionary, int n)
+{
+ char *here = (char *)dictionary->here;
+ here += n;
+ dictionary->here = FICL_POINTER_TO_CELL(here);
+}
+
+
+/**************************************************************************
+ d i c t A l l o t C e l l s
+** Reserve space for the requested number of ficlCells in the
+** dictionary. If nficlCells < 0 , removes space from the dictionary.
+**************************************************************************/
+void ficlDictionaryAllotCells(ficlDictionary *dictionary, int nficlCells)
+{
+ dictionary->here += nficlCells;
+}
+
+
+/**************************************************************************
+ d i c t A p p e n d C e l l
+** Append the specified ficlCell to the dictionary
+**************************************************************************/
+void ficlDictionaryAppendCell(ficlDictionary *dictionary, ficlCell c)
+{
+ *dictionary->here++ = c;
+ return;
+}
+
+
+/**************************************************************************
+ d i c t A p p e n d C h a r
+** Append the specified char to the dictionary
+**************************************************************************/
+void ficlDictionaryAppendCharacter(ficlDictionary *dictionary, char c)
+{
+ char *here = (char *)dictionary->here;
+ *here++ = c;
+ dictionary->here = FICL_POINTER_TO_CELL(here);
+ return;
+}
+
+
+/**************************************************************************
+ d i c t A p p e n d U N S
+** Append the specified ficlUnsigned to the dictionary
+**************************************************************************/
+void ficlDictionaryAppendUnsigned(ficlDictionary *dictionary, ficlUnsigned u)
+{
+ *dictionary->here++ = FICL_LVALUE_TO_CELL(u);
+ return;
+}
+
+
+void *ficlDictionaryAppendData(ficlDictionary *dictionary, void *data, ficlInteger length)
+{
+ char *here = (char *)dictionary->here;
+ char *oldHere = here;
+ char *from = (char *)data;
+
+ if (length == 0)
+ {
+ ficlDictionaryAlign(dictionary);
+ return (char *)dictionary->here;
+ }
+
+ while (length)
+ {
+ *here++ = *from++;
+ length--;
+ }
+
+ *here++ = '\0';
+
+ dictionary->here = FICL_POINTER_TO_CELL(here);
+ ficlDictionaryAlign(dictionary);
+ return oldHere;
+}
+
+
+/**************************************************************************
+ d i c t C o p y N a m e
+** Copy up to FICL_NAME_LENGTH characters of the name specified by s into
+** the dictionary starting at "here", then NULL-terminate the name,
+** point "here" to the next available byte, and return the address of
+** the beginning of the name. Used by dictAppendWord.
+** N O T E S :
+** 1. "here" is guaranteed to be aligned after this operation.
+** 2. If the string has zero length, align and return "here"
+**************************************************************************/
+char *ficlDictionaryAppendString(ficlDictionary *dictionary, ficlString s)
+{
+ void *data = FICL_STRING_GET_POINTER(s);
+ ficlInteger length = FICL_STRING_GET_LENGTH(s);
+
+ if (length > FICL_NAME_LENGTH)
+ length = FICL_NAME_LENGTH;
+
+ return ficlDictionaryAppendData(dictionary, data, length);
+}
+
+
+ficlWord *ficlDictionaryAppendConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficlInteger value)
+{
+ ficlWord *word = ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)instruction, FICL_WORD_DEFAULT);
+ if (word != NULL)
+ ficlDictionaryAppendUnsigned(dictionary, value);
+ return word;
+}
+
+
+ficlWord *ficlDictionaryAppend2ConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficl2Integer value)
+{
+ ficlWord *word = ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)instruction, FICL_WORD_DEFAULT);
+ if (word != NULL)
+ {
+ ficlDictionaryAppendUnsigned(dictionary, FICL_2UNSIGNED_GET_HIGH(value));
+ ficlDictionaryAppendUnsigned(dictionary, FICL_2UNSIGNED_GET_LOW(value));
+ }
+ return word;
+}
+
+
+
+ficlWord *ficlDictionaryAppendConstant(ficlDictionary *dictionary, char *name, ficlInteger value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return ficlDictionaryAppendConstantInstruction(dictionary, s, ficlInstructionConstantParen, value);
+}
+
+
+
+ficlWord *ficlDictionaryAppend2Constant(ficlDictionary *dictionary, char *name, ficl2Integer value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return ficlDictionaryAppend2ConstantInstruction(dictionary, s, ficlInstruction2ConstantParen, value);
+}
+
+
+
+ficlWord *ficlDictionarySetConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficlInteger value)
+{
+ ficlWord *word = ficlDictionaryLookup(dictionary, name);
+
+ if (word == NULL)
+ {
+ word = ficlDictionaryAppendConstantInstruction(dictionary, name, instruction, value);
+ }
+ else
+ {
+ word->code = (ficlPrimitive)instruction;
+ word->param[0] = FICL_LVALUE_TO_CELL(value);
+ }
+ return word;
+}
+
+ficlWord *ficlDictionarySetConstant(ficlDictionary *dictionary, char *name, ficlInteger value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return ficlDictionarySetConstantInstruction(dictionary, s, ficlInstructionConstantParen, value);
+}
+
+ficlWord *ficlDictionarySet2ConstantInstruction(ficlDictionary *dictionary, ficlString s, ficlInstruction instruction, ficl2Integer value)
+{
+ ficlWord *word;
+ word = ficlDictionaryLookup(dictionary, s);
+
+ /* only reuse the existing word if we're sure it has space for a 2constant */
+ if ((word != NULL) &&
+ ((((ficlInstruction)word->code) == ficlInstruction2ConstantParen)
+#if FICL_WANT_FLOAT
+ ||
+ (((ficlInstruction)word->code) == ficlInstructionF2ConstantParen)
+#endif /* FICL_WANT_FLOAT */
+ )
+ )
+ {
+ word->code = (ficlPrimitive)instruction;
+ word->param[0].u = FICL_2UNSIGNED_GET_HIGH(value);
+ word->param[1].u = FICL_2UNSIGNED_GET_LOW(value);
+ }
+ else
+ {
+ word = ficlDictionaryAppend2ConstantInstruction(dictionary, s, instruction, value);
+ }
+
+ return word;
+}
+
+
+ficlWord *ficlDictionarySet2Constant(ficlDictionary *dictionary, char *name, ficl2Integer value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return ficlDictionarySet2ConstantInstruction(dictionary, s, ficlInstruction2ConstantParen, value);
+}
+
+
+ficlWord *ficlDictionarySetConstantString(ficlDictionary *dictionary, char *name, char *value)
+{
+ ficlString s;
+ ficl2Integer valueAs2Integer;
+ FICL_2INTEGER_SET(strlen(value), (intptr_t)value, valueAs2Integer);
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+
+ return ficlDictionarySet2ConstantInstruction(dictionary, s, ficlInstruction2ConstantParen, valueAs2Integer);
+}
+
+
+
+/**************************************************************************
+ d i c t A p p e n d W o r d
+** Create a new word in the dictionary with the specified
+** ficlString, code, and flags. Does not require a NULL-terminated
+** name.
+**************************************************************************/
+ficlWord *ficlDictionaryAppendWord(ficlDictionary *dictionary,
+ ficlString name,
+ ficlPrimitive code,
+ ficlUnsigned8 flags)
+{
+ ficlUnsigned8 length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(name);
+ char *nameCopy;
+ ficlWord *word;
+
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+
+ /*
+ ** NOTE: ficlDictionaryAppendString advances "here" as a side-effect.
+ ** It must execute before word is initialized.
+ */
+ nameCopy = ficlDictionaryAppendString(dictionary, name);
+ word = (ficlWord *)dictionary->here;
+ dictionary->smudge = word;
+ word->hash = ficlHashCode(name);
+ word->code = code;
+ word->semiParen = ficlInstructionSemiParen;
+ word->flags = (ficlUnsigned8)(flags | FICL_WORD_SMUDGED);
+ word->length = length;
+ word->name = nameCopy;
+ /*
+ ** Point "here" to first ficlCell of new word's param area...
+ */
+ dictionary->here = word->param;
+
+ if (!(flags & FICL_WORD_SMUDGED))
+ ficlDictionaryUnsmudge(dictionary);
+
+ ficlDictionaryLock(dictionary, FICL_FALSE);
+ return word;
+}
+
+
+/**************************************************************************
+ d i c t A p p e n d W o r d
+** Create a new word in the dictionary with the specified
+** name, code, and flags. Name must be NULL-terminated.
+**************************************************************************/
+ficlWord *ficlDictionaryAppendPrimitive(ficlDictionary *dictionary,
+ char *name,
+ ficlPrimitive code,
+ ficlUnsigned8 flags)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return ficlDictionaryAppendWord(dictionary, s, code, flags);
+}
+
+
+ficlWord *ficlDictionarySetPrimitive(ficlDictionary *dictionary,
+ char *name,
+ ficlPrimitive code,
+ ficlUnsigned8 flags)
+{
+ ficlString s;
+ ficlWord *word;
+
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ word = ficlDictionaryLookup(dictionary, s);
+
+ if (word == NULL)
+ {
+ word = ficlDictionaryAppendPrimitive(dictionary, name, code, flags);
+ }
+ else
+ {
+ word->code = (ficlPrimitive)code;
+ word->flags = flags;
+ }
+ return word;
+}
+
+
+ficlWord *ficlDictionaryAppendInstruction(ficlDictionary *dictionary,
+ char *name,
+ ficlInstruction i,
+ ficlUnsigned8 flags)
+{
+ return ficlDictionaryAppendPrimitive(dictionary, name, (ficlPrimitive)i, (ficlUnsigned8)(FICL_WORD_INSTRUCTION | flags));
+}
+
+ficlWord *ficlDictionarySetInstruction(ficlDictionary *dictionary,
+ char *name,
+ ficlInstruction i,
+ ficlUnsigned8 flags)
+{
+ return ficlDictionarySetPrimitive(dictionary, name, (ficlPrimitive)i, (ficlUnsigned8)(FICL_WORD_INSTRUCTION | flags));
+}
+
+
+/**************************************************************************
+ d i c t C e l l s A v a i l
+** Returns the number of empty ficlCells left in the dictionary
+**************************************************************************/
+int ficlDictionaryCellsAvailable(ficlDictionary *dictionary)
+{
+ return dictionary->size - ficlDictionaryCellsUsed(dictionary);
+}
+
+
+/**************************************************************************
+ d i c t C e l l s U s e d
+** Returns the number of ficlCells consumed in the dicionary
+**************************************************************************/
+int ficlDictionaryCellsUsed(ficlDictionary *dictionary)
+{
+ return dictionary->here - dictionary->base;
+}
+
+
+
+/**************************************************************************
+ d i c t C r e a t e
+** Create and initialize a dictionary with the specified number
+** of ficlCells capacity, and no hashing (hash size == 1).
+**************************************************************************/
+ficlDictionary *ficlDictionaryCreate(ficlSystem *system, unsigned size)
+{
+ return ficlDictionaryCreateHashed(system, size, 1);
+}
+
+
+ficlDictionary *ficlDictionaryCreateHashed(ficlSystem *system, unsigned size, unsigned bucketCount)
+{
+ ficlDictionary *dictionary;
+ size_t nAlloc;
+
+ nAlloc = sizeof(ficlDictionary) + (size * sizeof (ficlCell))
+ + sizeof(ficlHash) + (bucketCount - 1) * sizeof (ficlWord *);
+
+ dictionary = ficlMalloc(nAlloc);
+ FICL_SYSTEM_ASSERT(system, dictionary != NULL);
+
+ dictionary->size = size;
+ dictionary->system = system;
+
+ ficlDictionaryEmpty(dictionary, bucketCount);
+ return dictionary;
+}
+
+
+/**************************************************************************
+ d i c t C r e a t e W o r d l i s t
+** Create and initialize an anonymous wordlist
+**************************************************************************/
+ficlHash *ficlDictionaryCreateWordlist(ficlDictionary *dictionary, int bucketCount)
+{
+ ficlHash *hash;
+
+ ficlDictionaryAlign(dictionary);
+ hash = (ficlHash *)dictionary->here;
+ ficlDictionaryAllot(dictionary, sizeof (ficlHash)
+ + (bucketCount - 1) * sizeof (ficlWord *));
+
+ hash->size = bucketCount;
+ ficlHashReset(hash);
+ return hash;
+}
+
+
+/**************************************************************************
+ d i c t D e l e t e
+** Free all memory allocated for the given dictionary
+**************************************************************************/
+void ficlDictionaryDestroy(ficlDictionary *dictionary)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary != NULL);
+ ficlFree(dictionary);
+ return;
+}
+
+
+/**************************************************************************
+ d i c t E m p t y
+** Empty the dictionary, reset its hash table, and reset its search order.
+** Clears and (re-)creates the hash table with the size specified by nHash.
+**************************************************************************/
+void ficlDictionaryEmpty(ficlDictionary *dictionary, unsigned bucketCount)
+{
+ ficlHash *hash;
+
+ dictionary->here = dictionary->base;
+
+ ficlDictionaryAlign(dictionary);
+ hash = (ficlHash *)dictionary->here;
+ ficlDictionaryAllot(dictionary,
+ sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *));
+
+ hash->size = bucketCount;
+ ficlHashReset(hash);
+
+ dictionary->forthWordlist = hash;
+ dictionary->smudge = NULL;
+ ficlDictionaryResetSearchOrder(dictionary);
+ return;
+}
+
+
+/**************************************************************************
+** i s A F i c l W o r d
+** Vet a candidate pointer carefully to make sure
+** it's not some chunk o' inline data...
+** It has to have a name, and it has to look
+** like it's in the dictionary address range.
+** NOTE: this excludes :noname words!
+**************************************************************************/
+int ficlDictionaryIsAWord(ficlDictionary *dictionary, ficlWord *word)
+{
+ if ( (((ficlInstruction)word) > ficlInstructionInvalid)
+ && (((ficlInstruction)word) < ficlInstructionLast) )
+ return 1;
+
+ if (!ficlDictionaryIncludes(dictionary, word))
+ return 0;
+
+ if (!ficlDictionaryIncludes(dictionary, word->name))
+ return 0;
+
+ if ((word->link != NULL) && !ficlDictionaryIncludes(dictionary, word->link))
+ return 0;
+
+ if ((word->length <= 0) || (word->name[word->length] != '\0'))
+ return 0;
+
+ if (strlen(word->name) != word->length)
+ return 0;
+
+ return 1;
+}
+
+
+/**************************************************************************
+ f i n d E n c l o s i n g W o r d
+** Given a pointer to something, check to make sure it's an address in the
+** dictionary. If so, search backwards until we find something that looks
+** like a dictionary header. If successful, return the address of the
+** ficlWord found. Otherwise return NULL.
+** nSEARCH_CELLS sets the maximum neighborhood this func will search before giving up
+**************************************************************************/
+#define nSEARCH_CELLS 100
+
+ficlWord *ficlDictionaryFindEnclosingWord(ficlDictionary *dictionary, ficlCell *cell)
+{
+ ficlWord *word;
+ int i;
+
+ if (!ficlDictionaryIncludes(dictionary, (void *)cell))
+ return NULL;
+
+ for (i = nSEARCH_CELLS; i > 0; --i, --cell)
+ {
+ word = (ficlWord *)(cell + 1 - (sizeof(ficlWord) / sizeof(ficlCell)));
+ if (ficlDictionaryIsAWord(dictionary, word))
+ return word;
+ }
+
+ return NULL;
+}
+
+
+/**************************************************************************
+ d i c t I n c l u d e s
+** Returns FICL_TRUE iff the given pointer is within the address range of
+** the dictionary.
+**************************************************************************/
+int ficlDictionaryIncludes(ficlDictionary *dictionary, void *p)
+{
+ return ((p >= (void *) &dictionary->base)
+ && (p < (void *)(&dictionary->base + dictionary->size)));
+}
+
+
+/**************************************************************************
+ d i c t L o o k u p
+** Find the ficlWord that matches the given name and length.
+** If found, returns the word's address. Otherwise returns NULL.
+** Uses the search order list to search multiple wordlists.
+**************************************************************************/
+ficlWord *ficlDictionaryLookup(ficlDictionary *dictionary, ficlString name)
+{
+ ficlWord *word = NULL;
+ ficlHash *hash;
+ int i;
+ ficlUnsigned16 hashCode = ficlHashCode(name);
+
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary != NULL);
+
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+
+ for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i)
+ {
+ hash = dictionary->wordlists[i];
+ word = ficlHashLookup(hash, name, hashCode);
+ }
+
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+ return word;
+}
+
+
+/**************************************************************************
+ s e e
+** TOOLS ( "<spaces>name" -- )
+** Display a human-readable representation of the named word's definition.
+** The source of the representation (object-code decompilation, source
+** block, etc.) and the particular form of the display is implementation
+** defined.
+**************************************************************************/
+/*
+** ficlSeeColon (for proctologists only)
+** Walks a colon definition, decompiling
+** on the fly. Knows about primitive control structures.
+*/
+char *ficlDictionaryInstructionNames[] =
+{
+#define FICL_TOKEN(token, description) description,
+#define FICL_INSTRUCTION_TOKEN(token, description, flags) description,
+#include "ficltokens.h"
+#undef FICL_TOKEN
+#undef FICL_INSTRUCTION_TOKEN
+};
+
+void ficlDictionarySee(ficlDictionary *dictionary, ficlWord *word, ficlCallback *callback)
+{
+ char *trace;
+ ficlCell *cell = word->param;
+ ficlCell *param0 = cell;
+ char buffer[128];
+
+ for (; cell->i != ficlInstructionSemiParen; cell++)
+ {
+ ficlWord *word = (ficlWord *)(cell->p);
+
+ trace = buffer;
+ if ((void *)cell == (void *)buffer)
+ *trace++ = '>';
+ else
+ *trace++ = ' ';
+ trace += sprintf(trace, "%3d ", cell - param0);
+
+ if (ficlDictionaryIsAWord(dictionary, word))
+ {
+ ficlWordKind kind = ficlWordClassify(word);
+ ficlCell c, c2;
+
+ switch (kind)
+ {
+ case FICL_WORDKIND_INSTRUCTION:
+ sprintf(trace, "%s (instruction %ld)", ficlDictionaryInstructionNames[(long)word], (long)word);
+ break;
+ case FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT:
+ c = *++cell;
+ sprintf(trace, "%s (instruction %ld), with argument %ld (%#lx)", ficlDictionaryInstructionNames[(long)word], (long)word, c.i, c.u);
+ break;
+ case FICL_WORDKIND_INSTRUCTION_WORD:
+ sprintf(trace, "%s :: executes %s (instruction word %ld)", word->name, ficlDictionaryInstructionNames[(long)word->code], (long)word->code);
+ break;
+ case FICL_WORDKIND_LITERAL:
+ c = *++cell;
+ if (ficlDictionaryIsAWord(dictionary, c.p) && (c.i >= ficlInstructionLast))
+ {
+ ficlWord *word = (ficlWord *)c.p;
+ sprintf(trace, "%.*s ( %#lx literal )",
+ word->length, word->name, c.u);
+ }
+ else
+ sprintf(trace, "literal %ld (%#lx)", c.i, c.u);
+ break;
+ case FICL_WORDKIND_2LITERAL:
+ c = *++cell;
+ c2 = *++cell;
+ sprintf(trace, "2literal %d %d (%#lx %#lx)", c2.i, c.i, c2.u, c.u);
+ break;
+#if FICL_WANT_FLOAT
+ case FICL_WORDKIND_FLITERAL:
+ c = *++cell;
+ sprintf(trace, "fliteral %f (%#lx)", c.f, c.u);
+ break;
+#endif /* FICL_WANT_FLOAT */
+ case FICL_WORDKIND_STRING_LITERAL:
+ {
+ ficlCountedString *counted = (ficlCountedString *)(void *)++cell;
+ cell = (ficlCell *)ficlAlignPointer(counted->text + counted->length + 1) - 1;
+ sprintf(trace, "s\" %.*s\"", counted->length, counted->text);
+ }
+ break;
+ case FICL_WORDKIND_CSTRING_LITERAL:
+ {
+ ficlCountedString *counted = (ficlCountedString *)(void *)++cell;
+ cell = (ficlCell *)ficlAlignPointer(counted->text + counted->length + 1) - 1;
+ sprintf(trace, "c\" %.*s\"", counted->length, counted->text);
+ }
+ break;
+ case FICL_WORDKIND_BRANCH0:
+ c = *++cell;
+ sprintf(trace, "branch0 %d", cell + c.i - param0);
+ break;
+ case FICL_WORDKIND_BRANCH:
+ c = *++cell;
+ sprintf(trace, "branch %d", cell + c.i - param0);
+ break;
+
+ case FICL_WORDKIND_QDO:
+ c = *++cell;
+ sprintf(trace, "?do (leave %d)", (ficlCell *)c.p - param0);
+ break;
+ case FICL_WORDKIND_DO:
+ c = *++cell;
+ sprintf(trace, "do (leave %d)", (ficlCell *)c.p - param0);
+ break;
+ case FICL_WORDKIND_LOOP:
+ c = *++cell;
+ sprintf(trace, "loop (branch %d)", cell + c.i - param0);
+ break;
+ case FICL_WORDKIND_OF:
+ c = *++cell;
+ sprintf(trace, "of (branch %d)", cell + c.i - param0);
+ break;
+ case FICL_WORDKIND_PLOOP:
+ c = *++cell;
+ sprintf(trace, "+loop (branch %d)", cell + c.i - param0);
+ break;
+ default:
+ sprintf(trace, "%.*s", word->length, word->name);
+ break;
+ }
+
+ }
+ else /* probably not a word - punt and print value */
+ {
+ sprintf(trace, "%ld ( %#lx )", cell->i, cell->u);
+ }
+
+ ficlCallbackTextOut(callback, buffer);
+ ficlCallbackTextOut(callback, "\n");
+ }
+
+ ficlCallbackTextOut(callback, ";\n");
+}
+
+/**************************************************************************
+ d i c t R e s e t S e a r c h O r d e r
+** Initialize the dictionary search order list to sane state
+**************************************************************************/
+void ficlDictionaryResetSearchOrder(ficlDictionary *dictionary)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary);
+ dictionary->compilationWordlist = dictionary->forthWordlist;
+ dictionary->wordlistCount = 1;
+ dictionary->wordlists[0] = dictionary->forthWordlist;
+ return;
+}
+
+
+/**************************************************************************
+ d i c t S e t F l a g s
+** Changes the flags field of the most recently defined word:
+** Set all bits that are ones in the set parameter.
+**************************************************************************/
+void ficlDictionarySetFlags(ficlDictionary *dictionary, ficlUnsigned8 set)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
+ dictionary->smudge->flags |= set;
+ return;
+}
+
+
+/**************************************************************************
+ d i c t C l e a r F l a g s
+** Changes the flags field of the most recently defined word:
+** Clear all bits that are ones in the clear parameter.
+**************************************************************************/
+void ficlDictionaryClearFlags(ficlDictionary *dictionary, ficlUnsigned8 clear)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
+ dictionary->smudge->flags &= ~clear;
+ return;
+}
+
+
+/**************************************************************************
+ d i c t S e t I m m e d i a t e
+** Set the most recently defined word as IMMEDIATE
+**************************************************************************/
+void ficlDictionarySetImmediate(ficlDictionary *dictionary)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
+ dictionary->smudge->flags |= FICL_WORD_IMMEDIATE;
+ return;
+}
+
+
+/**************************************************************************
+ d i c t U n s m u d g e
+** Completes the definition of a word by linking it
+** into the main list
+**************************************************************************/
+void ficlDictionaryUnsmudge(ficlDictionary *dictionary)
+{
+ ficlWord *word = dictionary->smudge;
+ ficlHash *hash = dictionary->compilationWordlist;
+
+ FICL_DICTIONARY_ASSERT(dictionary, hash);
+ FICL_DICTIONARY_ASSERT(dictionary, word);
+ /*
+ ** :noname words never get linked into the list...
+ */
+ if (word->length > 0)
+ ficlHashInsertWord(hash, word);
+ word->flags &= ~(FICL_WORD_SMUDGED);
+ return;
+}
+
+
+/**************************************************************************
+ d i c t W h e r e
+** Returns the value of the HERE pointer -- the address
+** of the next free ficlCell in the dictionary
+**************************************************************************/
+ficlCell *ficlDictionaryWhere(ficlDictionary *dictionary)
+{
+ return dictionary->here;
+}
+
+
diff --git a/doc/Logo.jpg b/doc/Logo.jpg
deleted file mode 100644
index c3332dbf65a1..000000000000
--- a/doc/Logo.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/api.html b/doc/api.html
new file mode 100644
index 000000000000..379f0d33eca7
--- /dev/null
+++ b/doc/api.html
@@ -0,0 +1,401 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl api</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl api
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='QuickFiclProgrammingConceptsOverview'>
+Quick Ficl Programming Concepts Overview
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+A Ficl <i>dictionary</i> is equivalent to the FORTH "dictionary"; it is where words are stored.
+A single dictionary has a single <code>HERE</code> pointer.
+<p>
+
+A Ficl <i>system information</i> structure is used to change default values used
+in initializing a Ficl <i>system</i>.
+<p>
+
+A Ficl <i>system</i> contains a single <i>dictionary</i>, and one or more <i>virtual machines</i>.
+<p>
+
+A Ficl <i>stack</i> is equivalent to a FORTH "stack". Ficl has three stacks:
+<ul>
+
+<li>
+The <i>data</i> stack, where integer arguments are stored.
+
+<li>
+The <i>return</i> stack, where locals and return addresses for subroutine returns are stored.
+
+<li>
+The <i>float</i> stack, where floating-point arguments are stored. (This stack
+is only enabled when <code>FICL_WANT_FLOAT</code> is nonzero.)
+</ul>
+
+<p>
+
+A Ficl <i>virtual machine</i> (or <i>vm</i>) represents a single running instance of the Ficl interpreter.
+All virtual machines in a single Ficl system see the same dictionary.
+<p>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='QuickFiclProgrammingTutorial'>
+Quick Ficl Programming Tutorial
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Though Ficl's API offers a great deal of flexibility, most programs
+incorporating Ficl simply use it as follows:
+
+<ol>
+
+<li>
+Create a single <code>ficlSystem</code> using <code>ficlSystemCreate(NULL)</code>.
+
+<li>
+Add native functions as necessary with <code>ficlDictionarySetPrimitive()</code>.
+
+<li>
+Add constants as necessary with <code>ficlDictionarySetConstant()</code>.
+
+<li>
+Create one (or more) virtual machine(s) with <code>ficlSystemCreateVm()</code>.
+
+<li>
+Add one or more scripted functions with <code>ficlVmEvaluate()</code>.
+
+<li>
+Execute code in a Ficl virtual machine, usually with <code>ficlVmEvaluate()</code>,
+but perhaps with <code>ficlVmExecuteXT()</code>.
+
+<li>
+At shutdown, call <code>ficlSystemDestroy()</code> on the single Ficl system.
+
+</ol>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FiclApplicationProgrammingInterface'>
+Ficl Application Programming Interface
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+The following is a partial listing of functions that interface your
+system or program to Ficl. For a complete listing, see <code>ficl.h</code>
+(which is heavily commented). For a simple example, see <code>main.c</code>.
+<p>
+
+Note that as of Ficl 4, the API is internally consistent.
+<i>Every</i> external entry point starts with the word
+<code>ficl</code>, and the word after that also corresponds
+with the first argument. For instance, a word that operates
+on a <code>ficlSystem *</code> will be called <code>ficlSystem<i>Something</i>()</code>.
+
+
+
+
+<dl>
+
+<p><dt>
+<code>void ficlSystemInformationInitialize(ficlSystemInformation *fsi)</code>
+<dd>
+
+
+
+Resets a <code>ficlSystemInformation</code> structure to all zeros.
+(Actually implemented as a macro.) Use this to initialize a <code>ficlSystemInformation</code>
+structure before initializing its members and passing it
+into <code>ficlSystemCreate()</code> (below).
+
+<p><dt>
+<code>ficlSystem *ficlSystemCreate(ficlSystemInformation *fsi)</code>
+<dd>
+
+
+
+Initializes Ficl's shared system data structures, and creates the
+dictionary allocating the specified number of cells from the heap
+(by a call to <code>ficlMalloc()</code>). If you pass in a <code>NULL</code>
+pointer, you will recieve a <code>ficlSystem</code> using the default
+sizes for the dictionary and stacks.
+
+
+<p><dt>
+<code>void ficlSystemDestroy(ficlSystem *system)</code>
+<dd>
+
+
+
+Reclaims memory allocated for the Ficl system including all
+dictionaries and all virtual machines created by
+<code>ficlSystemCreateVm()</code>. Note that this will <i>not</i>
+automatically free memory allocated by the FORTH memory allocation
+words (<code>ALLOCATE</code> and <code>RESIZE</code>).
+
+<p><dt>
+<code>ficlWord *ficlDictionarySetPrimitive(ficlDictionary *dictionary, char *name, ficlCode code, ficlUnsigned8 flags)</code>
+<dd>
+
+
+
+Adds a new word to the dictionary with the given
+name, code pointer, and flags. To add
+<p>
+
+The <code>flags</code> parameter is a bitfield. The valid
+flags are:<ul>
+
+<li>
+FICL_WORD_IMMEDIATE
+<li>
+FICL_WORD_COMPILE_ONLY
+<li>
+FICL_WORD_SMUDGED
+<li>
+FICL_WORD_OBJECT
+<li>
+FICL_WORD_INSTRUCTION
+
+</ul>
+
+For more information on these flags, see <code>ficl.h</code>.
+
+
+<p><dt>
+<code>ficlVm *ficlSystemCreateVm(ficlSystem *system)</code>
+<dd>
+
+
+
+Creates a new virtual machine in the specified system.
+
+
+<p><dt>
+<code>int ficlVmEvaluate(ficlVm *vm, char *text)</code>
+<dd>
+
+
+
+ the specified C string (zero-terminated) to the given
+virtual machine for evaluation. Returns various exception codes (VM_XXXX
+in ficl.h) to indicate the reason for returning. Normal exit
+condition is VM_OUTOFTEXT, indicating that the VM consumed the string
+successfully and is back for more. Calls to <code>ficlVmEvaluate()</code>
+can be nested, and
+the function itself is re-entrant, but note that a VM is
+static, so you have to take reasonable precautions (for example, use one
+VM per thread in a multithreaded system if you want multiple threads to
+be able to execute commands).
+
+
+<p><dt>
+<code>int ficlVmExecuteXT(ficlVm *vm, ficlWord *pFW)</code>
+<dd>
+
+
+
+Same as ficlExec, but takes a pointer to a ficlWord instead of a
+string. Executes the word and returns after it has finished. If
+executing the word results in an exception, this function will
+re-throw the same code if it is nested under another ficlExec family
+function, or return the exception code directly if not. This function
+is useful if you need to execute the same word repeatedly&mdash;you
+save the dictionary search and outer interpreter overhead.
+
+<p><dt>
+<code>void ficlFreeVM(ficlVm *vm)</code>
+<dd>
+
+
+
+Removes the VM in question from the system VM list and deletes
+the memory allocated to it. This is an optional call, since
+ficlTermSystem will do this cleanup for you. This function is
+handy if you're going to do a lot of dynamic creation of VMs.
+
+<p><dt>
+<code>ficlVm *ficlNewVM(ficlSystem *system)</code>
+<dd>
+
+
+
+Create, initialize, and return a VM from the heap using
+ficlMalloc. Links the VM into the system VM list for later reclamation
+by ficlTermSystem.
+
+<p><dt>
+<code>ficlWord *ficlSystemLookup(ficlSystem *system, char *name)</code>
+<dd>
+
+
+
+Returns the address of the specified word in the main dictionary.
+If no such word is found, it returns <code>NULL</code>.
+The address is also a valid execution token, and can be used in a call to <code>ficlVmExecuteXT()</code>.
+
+<p><dt>
+<code>ficlDictionary *ficlSystemGetDictionary(ficlSystem *system)<br>ficlDictionary *ficlVmGetDictionary(ficlVm *system)</code>
+<dd>
+
+
+
+Returns a pointer to the main system dictionary.
+
+
+<p><dt>
+<code>ficlDictionary *ficlSystemGetEnvironment(ficlSystem *system)</code>
+<dd>
+
+
+
+Returns a pointer to the environment dictionary. This dictionary
+stores information that describes this implementation as required by the
+Standard.
+
+
+
+
+<p><dt>
+<code>ficlDictionary *ficlSystemGetLocals(ficlSystem *system)</code>
+<dd>
+
+
+
+Returns a pointer to the locals dictionary. This function is
+defined only if <code>FICL_WANT_LOCALS</code> is non-zero (see <code>ficl.h</code>).
+The locals dictionary is the symbol table for
+<a href="locals.html">local variables</a>.
+
+
+</dl>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FiclCompile-TimeConstants'>
+Ficl Compile-Time Constants
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+There are a lot of preprocessor constants you can set at compile-time
+to modify Ficl's runtime behavior. Some are required, such as telling
+Ficl whether or not the local platform supports double-width integers
+(<code>FICL_PLATFORM_HAS_2INTEGER</code>);
+some are optional, such as telling Ficl whether or not to use the
+extended set of "prefixes" (<code>FICL_WANT_EXTENDED_PREFIXES</code>).
+<p>
+
+The best way to find out more about these constants is to read <code>ficl.h</code>
+yourself. The settings that turn on or off Ficl modules all start with
+<code>FICL_WANT</code>. The settings relating to functionality available
+on the current platform all start with <code>FICL_PLATFORM</code>.
+<p>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='codeficllocalh/code'>
+<code>ficllocal.h</code>
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+One more note about constants. Ficl now ships with a standard place for
+you to tweak the Ficl compile-time preprocessor constants.
+It's a file called <code>ficllocal.h</code>, and we guarantee that it
+will always ship empty (or with only comments). We suggest that you
+put all your local changes there, rather than editing <code>ficl.h</code>
+or editing the makefile. That should make it much easier to integrate
+future Ficl releases into your product&mdash;all you need do is preserve
+your tweaked copy of <code>ficllocal.h</code> and replace the rest.
+
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/ficlddj.PDF b/doc/articles/ficlddj.pdf
index f058dbe4166a..f058dbe4166a 100644
--- a/doc/ficlddj.PDF
+++ b/doc/articles/ficlddj.pdf
Binary files differ
diff --git a/doc/jwsforml.PDF b/doc/articles/jwsforml.pdf
index b7c8a3d11250..b7c8a3d11250 100644
--- a/doc/jwsforml.PDF
+++ b/doc/articles/jwsforml.pdf
Binary files differ
diff --git a/doc/oo_in_c.html b/doc/articles/oo_in_c.html
index b483eb37b369..b483eb37b369 100644
--- a/doc/oo_in_c.html
+++ b/doc/articles/oo_in_c.html
diff --git a/doc/sigplan9906.doc b/doc/articles/sigplan9906.doc
index 1f4cea092e58..1f4cea092e58 100644
--- a/doc/sigplan9906.doc
+++ b/doc/articles/sigplan9906.doc
Binary files differ
diff --git a/doc/debugger.html b/doc/debugger.html
new file mode 100644
index 000000000000..31e948dd7686
--- /dev/null
+++ b/doc/debugger.html
@@ -0,0 +1,259 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl debugger</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl debugger
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+<p>Ficl includes a simple step debugger for colon definitions
+and <code>DOES></code> words.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='UsingTheFiclDebugger'>
+Using The Ficl Debugger
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+To debug a word, set up the stack with any parameters the word requires,
+then execute:
+<pre><b>DEBUG <i>your-word-name-here</i></b></pre>
+<p>
+
+If the word is unnamed, or all you have is an execution token,
+you can instead use <code>DEBUG-XT</code></b>
+<p>
+
+The debugger invokes <tt>SEE</tt> on the word which prints a crude source
+listing. It then stops at the first instruction of the definition. There are
+six (case insensitive) commands you can use from here onwards:
+
+<dl>
+
+<dt>
+<b>I</b> (step <b>I</b>n)
+<dd>If the next instruction is a colon defintion or does> word, steps into
+that word's code. If the word is a primitive, simply executes the word.
+
+<dt>
+<b>O</b> (step <b>O</b>ver)
+<dd>
+Executes the next instruction in its entirety.
+
+<dt>
+<b>G</b> (<b>G</b>o)
+<dd>
+Run the word to completion and exit the debugger.
+
+<dt>
+<b>L</b> (<b>L</b>ist)
+<dd>
+Lists the source code of the word presently being stepped.
+
+<dt>
+<b>Q</b> (<b>Q</b>uit)
+<dd>
+Abort the word and exit the debugger, clearing the stacks.
+
+<dt>
+<b>X</b> (e<b>X</b>ecute)
+<dd>
+Interpret the remainder of the line as Ficl words. Any change
+they make to the stacks will be preserved when the debugged word
+continues execution.
+Any errors will abort the debug session and reset the VM. Usage example:
+<pre>
+X DROP 3 \ change top argument on stack to 3
+</pre>
+
+</dl>
+
+
+Any other character will prints a list of available debugger commands.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='ThecodeON-STEP/codeEvent'>
+The <code>ON-STEP</code> Event
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+If there is a defined word named <code>ON-STEP</code> when the debugger starts, that
+word will be executed before every step. Its intended use is to display the stacks
+and any other VM state you find interesting. The default <code>ON-STEP</code> is:
+<p>
+
+<pre>
+: ON-STEP ." S: " .S-SIMPLE CR ;
+</pre>
+
+If you redefine <code>ON-STEP</code>, we recommend you ensure the word has no
+side-effects (for instance, adding or removing values from any stack).
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#d0d0d0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=3><b><i>
+<a name='OtherUsefulWordsForDebuggingAndcodeON-STEP/code'>
+Other Useful Words For Debugging And <code>ON-STEP</code>
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<dt>
+<code>.ENV ( -- )</code>
+<dd>
+Prints all environment settings non-destructively.
+
+<dt>
+<code>.S ( -- )</code>
+<dd>
+Prints the parameter stack non-destructively in a verbose format.
+
+<dt>
+<code>.S-SIMPLE ( -- )</code>
+<dd>
+Prints the parameter stack non-destructively in a simple single-line format.
+
+<dt>
+<code>F.S ( -- )</code>
+<dd>
+Prints the float stack non-destructively (only available if <code>FICL_WANT_FLOAT</code> is enabled).
+
+<dt>
+<code>R.S ( -- )</code>
+<dd>
+Prints a represention of the state of the return stack non-destructively.
+
+
+
+</dl>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='DebuggerInternals'>
+Debugger Internals
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<p>
+The debugger words are mostly located in source file <code>tools.c</code>. There are
+supporting words (<code>DEBUG</code> and <code>ON-STEP</code>) in <code>softcore.fr</code> as well.
+There are two main words that make the debugger go: <code>debug-xt</code> and <code>step-break</code>.
+<code>debug-xt</code> takes the execution token of a word to debug (as returned by <code>'</code> for example) ,
+checks to see if it is debuggable (not a primitive), sets a breakpoint at its
+first instruction, and runs <code>see</code> on it. To set a breakpoint,
+<code>debug-xt</code>
+replaces the instruction at the breakpoint with the execution token of <code>step-break</code>, and
+stores the original instruction and its address in a static breakpoint
+record. To clear the breakpoint, <code>step-break</code> simply replaces the original
+instruction and adjusts the target virtual machine's instruction pointer
+to run it.
+
+<p>
+
+<code>step-break</code> is responsible for processing debugger commands and setting
+breakpoints at subsequent instructions.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FutureEnhancements'>
+Future Enhancements
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<li>
+The debugger needs to exit automatically when it encounters the end of the word
+it was asked to debug. (Perhaps this could be a special kind of breakpoint?)
+
+<li>Add user-set breakpoints.
+
+<li>Add "step out" command.
+</dl>
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/dpans.html b/doc/dpans.html
new file mode 100644
index 000000000000..d6bc87acb8e3
--- /dev/null
+++ b/doc/dpans.html
@@ -0,0 +1,1037 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl standards compliance</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl standards compliance
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='ANSRequiredInformation'>
+ANS Required Information
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+The following documentation is necessary to comply for Ficl
+to comply with the DPANS94 standard. It describes what areas
+of the standard Ficl implements, what areas it does not, and
+how it behaves in areas undefined by the standard.
+
+<blockquote>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='ANSForthSystem'>
+ANS Forth System
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<b>
+
+Providing names from the Core Extensions word set
+<br>
+
+Providing names from the Double-Number word set
+<br>
+
+Providing the Exception word set
+<br>
+
+Providing the Exception Extensions word set
+<br>
+
+Providing the File-Access word set
+<br>
+
+Providing the File-Access Extensions word set
+<br>
+
+Providing names from the Floating-Point word set
+<br>
+
+Providing the Locals word set
+<br>
+
+Providing the Locals Extensions word set
+<br>
+
+Providing the Memory Allocation word set
+<br>
+
+Providing the Programming-Tools word set
+<br>
+
+Providing names from the Programming-Tools Extensions word set
+<br>
+
+Providing the Search-Order word set
+<br>
+
+Providing the Search-Order Extensions word set
+<br>
+
+Providing names from the String Extensions word set
+<br>
+
+</b>
+
+
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='Implementation-definedOptions'>
+Implementation-defined Options
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+The implementation-defined items in the following list represent
+characteristics and choices left to the discretion of the implementor,
+provided that the requirements of the Standard are met. A system shall
+document the values for, or behaviors of, each item.
+
+<dl>
+
+<dt><b>
+aligned address requirements (3.1.3.3 Addresses)
+</b><dd>
+
+
+
+System dependent. You can change the default address alignment by
+defining <code>FICL_ALIGN</code> on your compiler's command line,
+or in <code>platform.h</code>.
+The default value is set to 2 in <code>ficl.h</code>.
+This causes dictionary entries and <code>ALIGN</code> and
+<code>ALIGNED</code> to align on 4 byte
+boundaries. To align on 2<b><sup>n</sup></b> byte boundaries,
+set <code>FICL_ALIGN</code> to <b>n</b>.
+
+
+<dt><b>
+behavior of 6.1.1320 EMIT for non-graphic characters
+</b><dd>
+
+
+
+Depends on target system, C runtime library, and your
+implementation of <code>ficlTextOut()</code>.
+
+
+<dt><b>
+character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT
+</b><dd>
+
+
+
+None implemented in the versions supplied in <code>primitives.c</code>.
+Because <code>ficlEvaluate()</code> is supplied a text buffer
+externally, it's up to your system to define how that buffer will
+be obtained.
+
+
+<dt><b>
+character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750 KEY)
+</b><dd>
+
+
+
+Depends on target system and implementation of <code>ficlTextOut()</code>.
+
+
+<dt><b>
+character-aligned address requirements (3.1.3.3 Addresses)
+</b><dd>
+
+
+
+Ficl characters are one byte each. There are no alignment requirements.
+
+
+<dt><b>
+character-set-extensions matching characteristics (3.4.2 Finding definition names)
+</b><dd>
+
+
+
+No special processing is performed on characters beyond case-folding. Therefore,
+extended characters will not match their unaccented counterparts.
+
+
+<dt><b>
+conditions under which control characters match a space delimiter (3.4.1.1 Delimiters)
+</b><dd>
+
+
+
+Ficl uses the Standard C function <code>isspace()</code> to distinguish space characters.
+
+
+<dt><b>
+format of the control-flow stack (3.2.3.2 Control-flow stack)
+</b><dd>
+
+
+
+Uses the data stack.
+
+
+<dt><b>
+conversion of digits larger than thirty-five (3.2.1.2 Digit conversion)
+</b><dd>
+
+
+
+The maximum supported value of <code>BASE</code> is 36.
+Ficl will fail via assertion in function <code>ltoa()</code> of <code>utility.c</code>
+if the base is found to be larger than 36 or smaller than 2. There will be no effect
+if <code>NDEBUG</code> is defined, however, other than possibly unexpected behavior.
+
+
+<dt><b>
+display after input terminates in 6.1.0695 ACCEPT and 6.2.1390 EXPECT
+</b><dd>
+
+
+
+Target system dependent.
+
+
+<dt><b>
+exception abort sequence (as in 6.1.0680 ABORT")
+</b><dd>
+
+
+
+Calls <tt>ABORT</tt> to exit.
+
+
+<dt><b>
+input line terminator (3.2.4.1 User input device)
+</b><dd>
+
+
+
+Target system dependent (implementation of outer loop that calls <code>ficlEvaluate()</code>).
+
+
+<dt><b>
+maximum size of a counted string, in characters (3.1.3.4 Counted strings, 6.1.2450 WORD)
+</b><dd>
+
+
+
+Counted strings are limited to 255 characters.
+
+
+<dt><b>
+maximum size of a parsed string (3.4.1 Parsing)
+</b><dd>
+
+
+
+Limited by available memory and the maximum unsigned value that can fit in a cell (2<sup>32</sup>-1).
+
+
+<dt><b>
+maximum size of a definition name, in characters (3.3.1.2 Definition names)
+</b><dd>
+
+
+
+Ficl stores the first 31 characters of a definition name.
+
+
+<dt><b>
+maximum string length for 6.1.1345 ENVIRONMENT?, in characters
+</b><dd>
+
+
+
+Same as maximum definition name length.
+
+
+<dt><b>
+method of selecting 3.2.4.1 User input device
+</b><dd>
+
+
+
+None supported. This is up to the target system.
+
+
+<dt><b>
+method of selecting 3.2.4.2 User output device
+</b><dd>
+
+
+
+None supported. This is up to the target system.
+
+
+<dt><b>
+methods of dictionary compilation (3.3 The Forth dictionary)
+</b><dd>
+
+
+
+Okay, we don't know what this means. If you understand what they're asking for here,
+please call the home office.
+
+
+<dt><b>
+number of bits in one address unit (3.1.3.3 Addresses)
+</b><dd>
+
+
+
+Target system dependent, either 32 or 64 bits.
+
+
+<dt><b>
+number representation and arithmetic (3.2.1.1 Internal number representation)
+</b><dd>
+
+
+
+System dependent. Ficl represents a CELL internally as a union that can hold a <code>ficlInteger32</code>
+(a signed 32 bit scalar value), a <code>ficlUnsigned32</code> (32 bits unsigned),
+and an untyped pointer. No specific byte ordering is assumed.
+
+
+<dt><b>
+ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types, 3.1.4 Cell-pair types)
+</b><dd>
+
+
+
+System dependent.
+Assuming a 32 bit implementation, range for signed single-cell values is [-2<sup>31</sup>, 2<sup>31</sup>-1].
+Range for unsigned single cell values is [0, 2<sup>32</sup>-1].
+Range for signed double-cell values is [-2<sup>63</sup>, 2<sup>63</sup>-1].
+Range for unsigned double cell values is [0, 2<sup>64</sup>-1].
+
+
+<dt><b>
+read-only data-space regions (3.3.3 Data space)
+</b><dd>
+
+
+
+None.
+
+
+<dt><b>
+size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient regions)
+</b><dd>
+
+
+
+Default is 255. Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>.
+
+
+<dt><b>
+size of one cell in address units (3.1.3 Single-cell types)
+</b><dd>
+
+
+
+System dependent, generally 4.
+
+
+<dt><b>
+size of one character in address units (3.1.2 Character types)
+</b><dd>
+
+
+
+System dependent, generally 1.
+
+
+<dt><b>
+size of the keyboard terminal input buffer (3.3.3.5 Input buffers)
+</b><dd>
+
+
+
+This buffer is supplied by the host program. Ficl imposes no practical limit.
+
+
+<dt><b>
+size of the pictured numeric output string buffer (3.3.3.6 Other transient regions)
+</b><dd>
+
+
+
+Default is 255. Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>.
+
+
+<dt><b>
+size of the scratch area whose address is returned by 6.2.2000 PAD (3.3.3.6 Other transient regions)
+</b><dd>
+
+
+
+Default is 255. Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>.
+
+
+<dt><b>
+system case-sensitivity characteristics (3.4.2 Finding definition names)
+</b><dd>
+
+
+
+The Ficl dictionary is not case-sensitive.
+
+
+<dt><b>
+system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)
+</b><dd>
+
+
+
+<code>ok&gt;</code>
+
+
+<dt><b>
+type of division rounding (3.2.2.1 Integer division, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1890 MOD)
+</b><dd>
+
+
+
+Symmetric.
+
+
+<dt><b>
+values of 6.1.2250 STATE when true
+</b><dd>
+
+
+
+1.
+
+
+<dt><b>
+values returned after arithmetic overflow (3.2.2.2 Other integer operations)
+</b><dd>
+
+
+
+System dependent. Ficl makes no special checks for overflow.
+
+
+<dt><b>
+whether the current definition can be found after 6.1.1250 DOES&gt; (6.1.0450 :)
+</b><dd>
+
+
+No. Definitions are unsmudged after ; only, and only then if no control structure matching problems have been detected.
+
+</dl>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='AmbiguousConditions'>
+Ambiguous Conditions
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<dt><b>
+a name is neither a valid definition name nor a valid number during text interpretation (3.4 The Forth text interpreter)
+</b><dd>
+
+
+
+Ficl calls <code>ABORT</code> then prints the name followed by <code>not found</code>.
+
+
+<dt><b>
+a definition name exceeded the maximum length allowed (3.3.1.2 Definition names)
+</b><dd>
+
+
+
+Ficl stores the first 31 characters of the definition name, and uses all characters of the name
+in computing its hash code. The actual length of the name, up to 255 characters, is stored in
+the definition's length field.
+
+
+<dt><b>
+addressing a region not listed in 3.3.3 Data Space
+</b><dd>
+
+
+
+No problem: all addresses in Ficl are absolute. You can reach any 32 bit address in Ficl's address space.
+
+
+<dt><b>
+argument type incompatible with specified input parameter, e.g., passing a flag to a word expecting an n (3.1 Data types)
+</b><dd>
+
+
+
+Ficl makes no check for argument type compatibility. Effects of a mismatch vary widely depending on the specific problem and operands.
+
+
+<dt><b>
+attempting to obtain the execution token, (e.g., with 6.1.0070 ', 6.1.1550 FIND, etc.) of a definition with undefined interpretation semantics
+</b><dd>
+
+
+
+Ficl returns a valid token, but the result of executing that token while interpreting may be undesirable.
+
+
+<dt><b>
+dividing by zero (6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1561 FM/MOD, 6.1.1890 MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 8.6.1.1820 M*/)
+</b><dd>
+
+
+
+Results are target procesor dependent. Generally, Ficl makes no check for divide-by-zero. The target processor will probably throw an exception.
+
+
+<dt><b>
+insufficient data-stack space or return-stack space (stack overflow)
+</b><dd>
+
+
+
+With <code>FICL_ROBUST</code> (defined in <code>ficl.h</code>) set to a value of 2 or greater,
+most data, float, and return stack operations are checked for underflow and overflow.
+
+
+<dt><b>
+insufficient space for loop-control parameters
+</b><dd>
+
+
+
+This is not checked, and bad things will happen.
+
+
+<dt><b>
+insufficient space in the dictionary
+</b><dd>
+
+
+
+Ficl generates an error message if the dictionary is too full to create
+a definition header. It checks <code>ALLOT</code> as well, but it is possible
+to make an unchecked allocation request that will overflow the dictionary.
+
+
+<dt><b>
+interpreting a word with undefined interpretation semantics
+</b><dd>
+
+
+
+Ficl protects all ANS Forth words with undefined interpretation semantics from being executed while in interpret state.
+It is possible to defeat this protection using ' (tick) and <code>EXECUTE</code> though.
+
+
+<dt><b>
+modifying the contents of the input buffer or a string literal (3.3.3.4 Text-literal regions, 3.3.3.5 Input buffers)
+</b><dd>
+
+
+
+Varies depending on the nature of the buffer. The input buffer is supplied by ficl's host function, and may reside
+in read-only memory. If so, writing the input buffer can ganerate an exception.
+String literals are stored in the dictionary, and are writable.
+
+
+<dt><b>
+overflow of a pictured numeric output string
+</b><dd>
+
+
+
+In the unlikely event you are able to construct a pictured numeric string of more
+than <code>FICL_PAD_LENGTH</code> characters, the system will be corrupted unpredictably.
+The buffer area that holds pictured numeric output is at the end of the virtual machine.
+Whatever is mapped after the offending VM in memory will be trashed, along with the heap
+structures that contain it.
+
+
+<dt><b>
+parsed string overflow
+</b><dd>
+
+
+
+Ficl does not copy parsed strings unless asked to. Ordinarily, a string parsed from the input buffer during
+normal interpretation is left in-place, so there is no possibility of overflow.
+If you ask to parse a string into the dictionary, as in <code>SLITERAL</code>, you need to have enough
+room for the string, otherwise bad things may happen. This is usually not a problem.
+
+
+<dt><b>
+producing a result out of range, e.g., multiplication (using *) results in a value too big to be represented by a single-cell integer (6.1.0090 *, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0570, &gt;NUMBER, 6.1.1561 FM/MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 6.2.0970 CONVERT, 8.6.1.1820 M*/)
+</b><dd>
+
+
+
+Value will be truncated.
+
+
+<dt><b>
+reading from an empty data stack or return stack (stack underflow)
+</b><dd>
+
+
+
+Most stack underflows are detected and prevented if <code>FICL_ROBUST</code> (defined in <code>sysdep.h</code>) is set to 2 or greater.
+Otherwise, the stack pointer and size are likely to be trashed.
+
+
+<dt><b>
+unexpected end of input buffer, resulting in an attempt to use a zero-length string as a name
+</b><dd>
+
+
+
+Ficl returns for a new input buffer until a non-empty one is supplied.
+
+
+</dl>
+
+
+The following specific ambiguous conditions are noted in the glossary entries of the relevant words:
+
+<dl>
+
+<dt><b>
+&gt;IN greater than size of input buffer (3.4.1 Parsing)
+</b><dd>
+
+
+
+Memory corruption will occur&mdash;the exact behavior is unpredictable
+because the input buffer is supplied by the host program's outer loop.
+
+
+<dt><b>
+6.1.2120 RECURSE appears after 6.1.1250 DOES&gt;
+</b><dd>
+
+
+
+It finds the address of the definition before <code>DOES&gt;</code>
+
+
+<dt><b>
+argument input source different than current input source for 6.2.2148 RESTORE-INPUT
+</b><dd>
+
+
+
+Not implemented.
+
+
+<dt><b>
+data space containing definitions is de-allocated (3.3.3.2 Contiguous regions)
+</b><dd>
+
+
+
+This is okay until the cells are overwritten with something else.
+The dictionary maintains a hash table, and the table must be updated
+in order to de-allocate words without corruption.
+
+
+<dt><b>
+data space read/write with incorrect alignment (3.3.3.1 Address alignment)
+</b><dd>
+
+
+
+Target processor dependent. Consequences include: none (Intel), address error exception (68K).
+
+
+<dt><b>
+data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860 C,)
+</b><dd>
+
+
+
+See above on data space read/write alignment.
+
+<dt><b>
+less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)
+</b><dd>
+
+
+
+If <code>FICL_ROBUST</code> is two or larger, Ficl will detect a stack underflow, report it, and execute <code>ABORT</code> to
+exit execution. Otherwise the error will not be detected, and memory corruption will occur.
+
+
+<dt><b>
+loop-control parameters not available ( 6.1.0140 +LOOP, 6.1.1680 I, 6.1.1730 J, 6.1.1760 LEAVE, 6.1.1800 LOOP, 6.1.2380 UNLOOP)
+</b><dd>
+
+
+
+Loop initiation words are responsible for checking the stack and guaranteeing that the control parameters are pushed.
+Any underflows will be detected early if <code>FICL_ROBUST</code> is set to 2 or greater.
+Note however that Ficl only checks for return stack underflows at the end of each line of text.
+
+<dt><b>
+most recent definition does not have a name (6.1.1710 IMMEDIATE)
+</b><dd>
+
+
+
+No problem.
+
+
+<dt><b>
+name not defined by 6.2.2405 VALUE used by 6.2.2295 TO
+</b><dd>
+
+
+
+Ficl's version of <code>TO</code> works correctly with words defined with:
+<ul>
+
+<li> <code>VALUE</code>
+<li> <code>2VALUE</code>
+<li> <code>FVALUE</code>
+<li> <code>F2VALUE</code>
+<li> <code>CONSTANT</code>
+<li> <code>FCONSTANT</code>
+<li> <code>2CONSTANT</code>
+<li> <code>F2CONSTANT</code>
+<li> <code>VARIABLE</code>
+<li> <code>2VARIABLE</code>
+</ul>
+as well as with all "local" variables.
+
+<dt><b>
+name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['], 6.2.2530 [COMPILE])
+</b><dd>
+
+
+
+Ficl prints an error message and executes <code>ABORT</code>
+
+<dt><b>
+parameters are not of the same type (6.1.1240 DO, 6.2.0620 ?DO, 6.2.2440 WITHIN)
+</b><dd>
+
+
+
+Not detected. Results vary depending on the specific problem.
+
+
+<dt><b>
+6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO
+</b><dd>
+
+
+
+The word is postponed correctly.
+
+
+<dt><b>
+string longer than a counted string returned by 6.1.2450 WORD
+</b><dd>
+
+
+
+Ficl stores the first <code>FICL_COUNTED_STRING_MAX</code> - 1 characters in the
+destination buffer.
+(The extra character is the trailing space required by the standard. Yuck.)
+
+<dt><b>
+u greater than or equal to the number of bits in a cell (6.1.1805 LSHIFT, 6.1.2162 RSHIFT)
+</b><dd>
+
+
+
+Depends on target process or and C runtime library implementations of the &lt;&lt; and &gt;&gt; operators
+on unsigned values. For I386, the processor appears to shift modulo the number of bits in a cell.
+
+<dt><b>
+word not defined via 6.1.1000 CREATE (6.1.0550 &gt;BODY, 6.1.1250 DOES&gt;)
+</b><dd>
+
+
+
+<dt><b>
+words improperly used outside 6.1.0490 &lt;# and 6.1.0040 #&gt; (6.1.0030 #, 6.1.0050 #S, 6.1.1670 HOLD, 6.1.2210 SIGN)
+</b><dd>
+
+
+
+Undefined. <code>CREATE</code> reserves a field in words it builds for <code>DOES&gt;</code> to fill in.
+If you use <code>DOES&gt;</code> on a word not made by <code>CREATE</code> it will overwrite the first
+cell of its parameter area. That's probably not what you want. Likewise, pictured numeric words
+assume that there is a string under construction in the VM's scratch buffer. If that's not the case,
+results may be unpleasant.
+
+
+</dl>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='LocalsImplementation-DefinedOptions'>
+Locals Implementation-Defined Options
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<dt><b>
+maximum number of locals in a definition (13.3.3 Processing locals, 13.6.2.1795 LOCALS|)
+</b><dd>
+
+
+
+Default is 64&mdash;unused locals are cheap. Change by redefining <code>FICL_MAX_LOCALS</code> (defined in <code>ficl.h</code>).
+
+</dl>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='LocalsAmbiguousconditions'>
+Locals Ambiguous conditions
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<dt><b>
+executing a named local while in interpretation state (13.6.1.0086 (LOCAL))
+</b><dd>
+
+
+
+Locals can be found in interpretation state while in the context of a definition under
+construction. Under these circumstances, locals behave correctly. Locals are not visible
+at all outside the scope of a definition.
+
+<dt><b>
+name not defined by VALUE or LOCAL (13.6.1.2295 TO)
+</b><dd>
+
+
+
+See the CORE ambiguous conditions, above (no change).
+
+</dl>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='ProgrammingToolsImplementation-DefinedOptions'>
+Programming Tools Implementation-Defined Options
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+<dl>
+
+<dt><b>
+source and format of display by 15.6.1.2194 SEE
+</b><dd>
+
+
+
+<code>SEE</code> de-compiles definitions from the dictionary. Ficl words are stored as a combination
+of things:
+<ol>
+
+<li>bytecodes (identified as "instructions"),
+<li>addresses of native Ficl functions, and
+<li>arguments to both of the above.
+
+</ol>
+Colon definitions are decompiled. Branching instructions indicate their destination,
+but target labels are not reconstructed.
+Literals and string literals are so noted, and their contents displayed.
+
+</dl>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='SearchOrderImplementation-DefinedOptions'>
+Search Order Implementation-Defined Options
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+<dl>
+
+<dt><b>
+maximum number of word lists in the search order (16.3.3 Finding definition names, 16.6.1.2197 SET-ORDER)
+</b><dd>
+
+
+
+Defaults to 16. Can be changed by redefining <code>FICL_MAX_WORDLISTS</code> (declared in <code>ficl.h</code>).
+
+
+<dt><b>
+minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY)
+</b><dd>
+
+
+
+Equivalent to <code>FORTH-WORDLIST 1 SET-ORDER</code>
+
+</dl>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='SearchOrderAmbiguousConditions'>
+Search Order Ambiguous Conditions
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+<dl>
+<dt><b>
+changing the compilation word list (16.3.3 Finding definition names)
+</b><dd>
+
+
+
+Ficl stores a link to the current definition independently of the compile wordlist while
+it is being defined, and links it into the compile wordlist only after the definition completes
+successfully. Changing the compile wordlist mid-definition will cause the definition to link
+into the <i>new</i> compile wordlist.
+
+
+<dt><b>
+search order empty (16.6.2.2037 PREVIOUS)
+</b><dd>
+
+
+
+Ficl prints an error message if the search order underflows, and resets the order to its default state.
+
+
+<dt><b>
+too many word lists in search order (16.6.2.0715 ALSO)
+</b><dd>
+
+
+
+Ficl prints an error message if the search order overflows, and resets the order to its default state.
+
+</dl>
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/favicon.ico b/doc/favicon.ico
index 57b1c723f583..027a7bd6b072 100644
--- a/doc/favicon.ico
+++ b/doc/favicon.ico
Binary files differ
diff --git a/doc/ficl.html b/doc/ficl.html
index a3096a4e5d33..3c23c0dde130 100644
--- a/doc/ficl.html
+++ b/doc/ficl.html
@@ -1,185 +1,264 @@
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
<!DOCTYPE html PUBLIC "-//w3c//dtd html 4.0 transitional//en">
-<HTML>
- <HEAD>
- <META name="Author" content="john sadler">
- <META name="Description" content="Ficl - embedded scripting with object oriented programming">
- <META name="Keywords" content="scripting prototyping tcl OOP Forth interpreter C">
-<STYLE>
-
-</STYLE>
- <LINK rel="SHORTCUT ICON" href="ficl.ico">
- <TITLE>
- Ficl - Embedded Scripting
- </TITLE>
- </HEAD>
- <BODY>
- <H1>
- <B>Ficl Documentation</B>
- </H1>
-<SCRIPT language="javascript" src="ficlheader.js" type="text/javascript">
-</SCRIPT>
- <DIV style="width:675px">
- <BR>
-
- <H1>
- <A name="whatis"></A>What is ficl?
- </H1>
- Ficl is a complete programming language interpreter designed to be embedded into other systems (including firmware based ones) as a command, macro, and development prototype language. Unlike other scripting interpreters,
- Ficl:
- <UL>
- <LI>
- typically takes under 2 hours to port to a new system -- much less if the target operating system is one of several already supported (Win32, Linux, FreeBSD, RiscOS, and more)
- </LI>
- <LI>
- has a small memory footprint: a fully featured Win32 console version takes less than 100K of memory, and a minimal version is less than half that
- </LI>
- <LI>
- is relatively quick thanks to its threaded code virtual machine design and just in time compiling
- </LI>
- <LI>
- is a complete and powerful programming language
- </LI>
- <LI>
- is interactive
- </LI>
- <LI>
- has object oriented programming features that can be used to wrap data structures or classes of the host system without altering them - even if the host is mainly written in a non-OO
- language
- </LI>
- </UL>
- <P>
- Ficl syntax is based on ANS Forth and the code is Standard C. See below for examples of <A href="#includesficl">software and products that include ficl</A>. Ficl stands for "Forth inspired
- command language".&nbsp;
- </P>
- <H3>
- Ficl vs. other Forth interpreters
- </H3>
- Where Forths usually view themselves as the center of the system and expect the rest of the system to be coded in Forth, Ficl acts as a component of the system. It is easy to export code
- written in C or ASM to Ficl in the style of TCL, or to invoke Ficl code from a compiled module. This allows you to do incremental development in a way that combines the best features of
- threaded languages (rapid development, quick code/test/debug cycle, reasonably fast) with the best features of C (everyone knows it, easier to support large blocks of code, efficient, type
- checking). In addition, Ficl provides a simple and powerful object model that can act as an object oriented <I>adapter</I> for code written in C (or asm, Forth, C++...).&nbsp;
- <H3>
- Ficl Design goals
- </H3>
- <UL>
- <LI>
- Target 32 bit processors (<I>version 2.03 targets 64 bit processors too</I>)
- </LI>
- <LI>
- Scripting, prototyping, and extension language for systems written also in C
- </LI>
- <LI>
- Supportable - code is as transparent as I can make it
- </LI>
- <LI>
- Interface to functions written in C
- </LI>
- <LI>
- Conform to the Forth DPANS 94
- </LI>
- <LI>
- Minimize porting effort - require an ANSI C runtime environment and minimal glue code
- </LI>
- <LI>
- Provide object oriented extensions
- </LI>
- </UL>
- <HR>
- <H2>
- <A name="download"></A>Download
- </H2>
- <UL>
- <LI>
- <B><A href="http://sourceforge.net/project/showfiles.php?group_id=24441">Download ficl (latest release)</A></B>
- </LI>
- </UL>
- <H2>
- <A name="links"></A>More information on Ficl and Forth
- </H2>
- <UL>
- <LI>
- <A href="http://ficl.sourceforge.net">Web home of Ficl</A>
- </LI>
- <LI>
- <A href="http://ficl.sourceforge.net/pdf/Forth_Primer.pdf">An excellent Forth Primer by Hans Bezemer</A>
- </LI>
- <LI>
- <A href="ficlddj.pdf">Manuscript of Ficl article for January 1999 Dr. Dobb's Journal</A>
- </LI>
- <LI>
- <A href="jwsforml.pdf">1998 FORML Conference paper - OO Programming in Ficl</A>
- </LI>
- <LI>
- <A href="http://www.taygeta.com/forth_intro/stackflo.html">An Introduction to Forth using Stack Flow</A> (start here if you're new to Forth)
- </LI>
- <LI>
- <A href="http://www.softsynth.com/pforth/pf_tut.htm">Phil Burk's Forth Tutorial</A>
- </LI>
- <LI>
- <A href="http://www.complang.tuwien.ac.at/forth/threaded-code.html">Anton Ertl's description of Threaded Code</A>
- </LI>
- <LI>
- <A href="http://ficl.sourceforge.net/dpans/dpans.htm">Draft Proposed American National Standard for Forth</A> (quite readable, actually)
- </LI>
- <LI>
- <A href="http://www.taygeta.com/forthlit.html">Forth literature index on Taygeta</A>
- </LI>
- <LI>
- <A href="http://www.forth.org">Forth Interest Group</A>
- </LI>
- </UL>
- <H2>
- <A name="includesficl"></A>Some software that uses ficl
- </H2>
- <UL>
- <LI>
- <A href="http://www.freebsd.org/">FreeBSD</A> boot loader (Daniel Sobral, Jordan Hubbard)
- </LI>
- <LI>
- <A href="http://www.chipcenter.com/networking/images/prod/prod158a.pdf">SwitchCore</A> Gigabit Ethernet switches (&Ouml;rjan Gustavsson )
- </LI>
- <LI>
- <A href="http://debuffer.sourceforge.net/">Palm Pilot Debuffer</A> (Eric Sessoms) Also see ficlx, a C++ interface to ficl, on the same site
- </LI>
- <LI>
- <A href="http://www.swcp.com/~jchavez/osmond.html">Osmond PC Board Layout tool</A>
- </LI>
- <LI>
- <A href="http://www.netcomsystems.com">NetCom Systems</A> ML7710
- </LI>
- <LI>
- <A href="http://www.parview.com/ds/homepage.html">ParView</A> GPS system
- </LI>
- <LI>
- <A href="http://www.thekompany.com/products/powerplant/software/Languages/Embedded.php3">PowerPlant Software</A> Development Environment for Linux
- </LI>
- <LI>
- <A href="http://www.vyyo.com/products/architecture_v3000.html">Vyyo V3000 Broadband Wireless Hub</A>
- </LI>
- <LI>
- <A href="mailto:john_sadler@alum.mit.edu"><I>Your Product Name Here!!!</I></A>
- </LI>
- </UL>
- <HR>
- <H2>
- <A name="lawyerbait"></A>LICENSE and DISCLAIMER
- </H2>
- <P>
- Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) All rights reserved.
- </P>
- <P>
- I am interested in hearing from anyone who uses ficl. If you have a problem, a success story, a defect, an enhancement request, or if you would like to contribute to the ficl release, please
- <A href="mailto:john_sadler@alum.mit.edu">send me email</A>.&nbsp;
- </P>
-<PRE>
+
+<html>
+<head>
+ <meta name="Author" content="john sadler">
+ <meta name="Description" content="Ficl - embedded scripting with object oriented programming">
+ <meta name="Keywords" content="scripting prototyping tcl OOP Forth interpreter C">
+ <link rel="SHORTCUT ICON" href="favicon.ico">
+ <title>Ficl - Embedded Scripting</title>
+</head>
+
+<body>
+
+<h1>Ficl Documentation</h1>
+
+<script language="javascript" src="ficlheader.js" type="text/javascript">
+</script>
+
+<h1><a name="whatis">What is Ficl?</a></h1>
+Ficl is a complete programming language interpreter designed to be
+embedded into other systems (including firmware based ones) as a
+command, macro, and development prototype language. Unlike other
+scripting interpreters, Ficl:
+
+<ul>
+
+<li>
+typically takes under 2 hours to port to a new system&mdash;much
+less if the target operating system is one of several already supported
+(Win32, Linux, FreeBSD, RiscOS, and more)
+
+<li>
+has a small memory footprint: a fully featured Win32 console
+version takes less than 100K of memory, and a minimal version is less
+than half that
+
+<li>
+is relatively quick thanks to its "switch-threaded" virtual
+machine design and just in time compiling
+
+<li>
+is a complete and powerful programming language
+
+<li>
+is interactive
+
+<li>
+has object oriented programming features that can be used to wrap
+data structures or classes of the host system without altering them&#151;even
+if the host is mainly written in a non-OO language
+
+</ul>
+
+<p>
+
+Ficl syntax is based on ANS Forth and the code is ANSI C. See
+below for examples of <a href="#includesficl">software and products
+that include ficl</a>. Ficl stands for "Forth inspired command language".
+
+
+<h3>Ficl Versus Other Forth Interpreters</h3>
+
+Where most Forths view themselves as the center of the system and
+expect the rest of the system to be coded in Forth, Ficl acts as a
+component of the system. It is easy to export code written in C or
+ASM to Ficl in the style of TCL, or to invoke Ficl code from a compiled
+module. This allows you to do incremental development in a way that
+combines the best features of threaded languages (rapid
+development, quick code/test/debug cycle, reasonably fast) with the best
+features of C (everyone knows it, easier to support large blocks of
+code, efficient, type checking). In addition, Ficl provides a simple
+and powerful object model that can act as an object oriented <i>adapter</i>
+for code written in C (or asm, Forth, C++...).
+
+
+<h3>Ficl Design Goals</h3>
+<ul>
+
+<li>
+Target 32- and 64-bit processors
+
+<li>
+Scripting, prototyping, and extension language for systems
+written also in C
+
+<li>
+Supportable&mdash;code is as transparent as I can make it
+
+<li>
+Interface to functions written in C
+
+<li>
+Conformant to the 1994 ANSI Standard for Forth (DPANS94)
+
+<li>
+Minimize porting effort&mdash;require an ANSI C runtime environment
+and minimal glue code
+
+<li>
+Provide object oriented extensions
+
+</ul>
+
+<hr>
+
+<h2><a name="download">Download</a></h2>
+
+<ul>
+
+<li> <b><a href="http://sourceforge.net/project/showfiles.php?group_id=24441">Download Ficl (latest release)</a></b>
+
+</ul>
+
+<h2><a name="links">More information on Ficl and Forth</a></h2>
+
+<ul>
+
+<li>
+<a href="http://ficl.sourceforge.net">Web home of Ficl</a>
+
+<li>
+<a href="http://ficl.sourceforge.net/pdf/Forth_Primer.pdf">
+An excellent Forth Primer by Hans Bezemer
+</a>
+
+<li>
+<a href="ficlddj.pdf">
+Manuscript of Ficl article for January 1999 Dr. Dobb's Journal
+</a>
+
+<li>
+<a href="jwsforml.pdf">
+1998 FORML Conference paper&mdash;OO Programming in Ficl
+</a>
+
+<li>
+<a href="http://www.taygeta.com/forth_intro/stackflo.html">
+An Introduction to Forth using Stack Flow
+</a>
+(start here if you're new to Forth)
+
+<li>
+<a href="http://www.softsynth.com/pforth/pf_tut.htm">
+Phil Burk's Forth Tutorial
+</a>
+
+<li>
+<a href="http://www.complang.tuwien.ac.at/forth/threaded-code.html">
+Anton Ertl's description of Threaded Code
+</a>
+(Ficl now uses what he calls "switch threading")
+
+<li>
+<a href="http://ficl.sourceforge.net/dpans/dpans.htm">
+Draft Proposed American National Standard for Forth
+</a>
+(quite readable, actually)
+
+<li>
+<a href="http://www.taygeta.com/forthlit.html">
+Forth literature index on Taygeta
+</a>
+
+<li>
+<a href="http://www.forth.org">
+Forth Interest Group
+</a>
+
+</ul>
+
+<h2><a name="includesficl">Some software that uses Ficl</a></h2>
+
+<ul>
+<li>
+The <a href="http://www.freebsd.org/">FreeBSD</a> boot loader
+(Daniel Sobral, Jordan Hubbard)
+
+<li>
+<a href="http://www.chipcenter.com/networking/images/prod/prod158a.pdf">
+SwitchCore
+</a>
+Gigabit Ethernet switches (&Ouml;rjan Gustavsson )
+
+<li>
+<a href="http://debuffer.sourceforge.net/">
+Palm Pilot Debuffer
+</a>
+(Eric Sessoms) Also see ficlx, a C++ interface to ficl, on the same site
+
+<li>
+<a href="http://www.swcp.com/%7Ejchavez/osmond.html">
+Osmond PC Board Layout tool
+</a>
+
+<li>
+<a href="http://www.netcomsystems.com">
+NetCom Systems
+</a>
+ML7710
+
+<li>
+<a href="http://www.parview.com/ds/homepage.html">
+ParView
+</a>
+GPS system
+
+<li>
+<a href="http://www.thekompany.com/products/powerplant/software/Languages/Embedded.php3">
+PowerPlant Software
+</a>
+Development Environment for Linux
+
+<li>
+<a href="http://www.vyyo.com/products/architecture_v3000.html">
+Vyyo V3000 Broadband Wireless Hub
+</a>
+
+<li>
+<a href="mailto:john_sadler@alum.mit.edu">
+<i>Your Product Name Here!!!</i>
+</a>
+
+</ul>
+
+
+<hr>
+<h2><a name="lawyerbait">License And Disclaimer</a></h2>
+
+Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+<br>
+All rights reserved.
+<p>
+
+<b>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
+<ol>
+
+<li>
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+<li>
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+</ol>
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -192,1328 +271,999 @@ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-</PRE>
- &nbsp;
- <H2>
- <A name="features"></A>Ficl features
- </H2>
- <UL>
- <LI>
- Simple to integrate into existing systems: the sample implementation requires three Ficl function calls (see the example program in testmain.c).
- </LI>
- <LI>
- Written in ANSI C for portability.&nbsp;
- </LI>
- <LI>
- Standard: Implements the ANS Forth CORE word set, part of the CORE EXT word set, SEARCH and SEARCH EXT, TOOLS and part of TOOLS EXT, LOCAL and LOCAL EXT, EXCEPTION, MEMORY,&nbsp; and
- various extras.
- </LI>
- <LI>
- Extensible: you can export code written in Forth, C, or asm in a straightforward way. Ficl provides open facilities for extending the language in an application specific way. You can even
- add new control structures (not surprising if you're familiar with Forth)
- </LI>
- <LI>
- Ficl and C/C++ can interact in two ways: Ficl can wrap C code, and C functions can invoke ficl code.
- </LI>
- <LI>
- Ficl code is thread safe and re-entrant:&nbsp; All Ficl Virtual Machines share one system dictionary (version 3.0 will permit multiple dictionaries); each Ficl Virtual Machine has an
- otherwise complete state, and each can be bound to a separate I/O channel (or none at all). An optional function called ficlLockDictionary() can control exclusive dictionary access. This
- function is stubbed out by default (See FICL_MULTITHREAD in sysdep.h). As long as there is only one "session" that can compile words into the dictionary, you do not need exclusive
- dictionary access for multithreading. <B>Note</B>: while the code is re-entrant, there are still restrictions on how you can use it safely in a multithreaded system. Specifically, the VM
- itself maintains state, so you generally need a VM per thread in a multithreaded system. If interrupt service routines make calls into Ficl code that alters VM state, then these generally
- need their own VM as well. Alternatively, you could provide a mutual exclusion mechanism to serialize access to a VM from multiple threads.
- </LI>
- <LI>
- ROMable: Ficl is designed to work in RAM based and ROM code / RAM data environments. It does require somewhat more memory than a pure ROM implementation because it builds its system
- dictionary in RAM at startup time.
- </LI>
- <LI>
- Written in ANSI C to be as simple as I can make it to understand, support, debug, and port. Compiles without complaint at /Az /W4 (require ANSI C, max. warnings) under Microsoft VC++. Ports
- to several other toolchains and operating systems (notably FreeBSD and Linux flavors) exist.
- </LI>
- <LI>
- Does full 32 bit math (but you need to implement two mixed precision math primitives (see sysdep.c))
- </LI>
- </UL>
- <HR>
- <H2>
- <A name="porting"></A>Porting ficl
- </H2>
- To install ficl on your target system, you need an ANSI C compiler and its runtime library. Inspect the system dependent macros and functions in <TT>sysdep.h</TT> and <TT>sysdep.c</TT> and edit
- them to suit your system. For example, <TT>INT16</TT> is a <TT>short</TT> on some compilers and an <TT>int</TT> on others. Check the default <TT>CELL</TT> alignment controlled by <TT>
- FICL_ALIGN</TT>. If necessary, add new definitions of <TT>ficlMalloc, ficlFree, ficlRealloc</TT>, and <TT>ficlTextOut</TT> to work with your operating system. Finally, use <TT>testmain.c</TT>
- as a guide to installing the ficl system and one or more virtual machines into your code. You do not need to include <TT>testmain.c</TT> in your build.&nbsp;
- <P>
- Note: ficlLockDictionary can be left unimplemented in most multithreaded implementations - it's only necessary if you expect to have more than one thread modifying the dictionary at the same
- time. If you do decide to implement it, make sure calls to ficlLockDictionary can nest properly (see the comments in sysdep.h). You need to keep count of nested locks and unlocks and do the
- right thing.
- </P>
- <P>
- Feel free to stub out the double precision math functions (which are presently implemented as inline assembly because it's so easy on many 32 bit processors) with kludge code that only goes
- to 32 bit precision. In most applications, you won't notice the difference. If you're doing a lot of number crunching, consider implementing them correctly.&nbsp;
- </P>
- <H3>
- Build controls
- </H3>
- The file sysdep.h contains default values for build controls. Most of these are written such that if you define them on the compiler command line, the defaults are overridden. I suggest you
- take the defaults on everything below the "build controls" section until you're confident of your port. Beware of declaring too small a dictionary, for example. You need about 3200 cells for a
- full system, about 2000 if you strip out most of the "soft" words.&nbsp;
- <H3>
- Soft Words
- </H3>
- Many words from all the supported wordsets are written in Forth, and stored as a big string that Ficl compiles when it starts. The sources for all of these words are in directory
- ficl/softwords. There is a .bat file (softcore.bat) and a PERL 5 script (softcore.pl) that convert Forth files into the file softcore.c, so softcore.c is really dependent on the Forth sources.
- This is not reflected in the Visual C++ project database. For the time being, it's a manual step. You can edit softcore.bat to change the list of files that contribute to softcore.c.&nbsp;
- <H3>
- To-Do List (target system dependent words)
- </H3>
- <UL>
- <LI>
- Unimplemented system dependent <TT>CORE</TT> word: <TT>KEY</TT> (implement this yourself if you need it)
- </LI>
- <LI>
- Kludged <TT>CORE</TT> word: <TT>ACCEPT</TT> (implement this better if you need to)
- </LI>
- </UL>
- <BR>
- &nbsp;<BR>
- &nbsp;
- <H2>
- <A name="api"></A>Application Programming Interface
- </H2>
- The following is a partial listing of functions that interface your system or program to ficl. For a complete listing, see ficl.h (heavily commented). For examples, see testmain.c and the
- ficlwin sources (<A href="#download">below</A>). <I>See the comments in ficl.c and ficl.h for additional information, and the example in file testmain.c.</I>
- <DL>
- <DT>
- <B>FICL_SYSTEM *ficlInitSystem(int nDictCells)</B>
- </DT>
- <DD>
- Initializes Ficl's shared system data structures, and creates the dictionary allocating the specified number of CELLs from the heap (by a call to ficlMalloc)
- </DD>
- <DT>
- <B>void ficlTermSystem(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Reclaims memory allocated for the ficl system including all dictionaries and all virtual machines created by vmCreate. Any uses of the memory allocation words (allocate and resize) are your
- problem.
- </DD>
- <DT>
- <B>int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags)</B>
- </DT>
- <DD>
- Create a primitive word in ficl's main dictionary with the given name, code pointer, and properties (immediate, compile only, etc) as described by the flags (see ficl.h for flag
- descriptions of the form FW_XXXX)
- </DD>
- <DT>
- <B>int ficlExec(FICL_VM *pVM, char *text)</B>
- </DT>
- <DD>
- Feed the specified C string ('\0' terminated) to the given virtual machine for evaluation. Returns various exception codes (VM_XXXX in ficl.h) to indicate the reason for returning. Normal
- exit condition is VM_OUTOFTEXT, indicating that the VM consumed the string successfully and is back for more. ficlExec calls can be nested, and the function itself is re-entrant, but note
- that a VM is static, so you have to take reasonable precautions (for example, use one VM per thread in a multithreaded system if you want multiple threads to be able to execute commands).
- </DD>
- <DT>
- <B>int ficlExecC(FICL_VM *pVM, char *text, int nChars)</B>
- </DT>
- <DD>
- Same as ficlExec, but takes a count indicating the length of the supplied string. Setting nChars to -1 is equivalent to ficlExec (expects '\0' termination).
- </DD>
- <DT>
- <B>int ficlExecXT(FICL_VM *pVM, FICL_WORD *pFW)</B>
- </DT>
- <DD>
- Same as ficlExec, but takes a pointer to a FICL_WORD instead of a string. Executes the word and returns after it has finished. If executing the word results in an exception, this function
- will re-throw the same code if it is nested under another ficlExec family function, or return the exception code directly if not. This function is useful if you need to execute the same
- word repeatedly - you save the dictionary search and outer interpreter overhead.
- </DD>
- <DT>
- <B>void ficlFreeVM(FICL_VM *pVM)</B>
- </DT>
- <DD>
- Removes the VM in question from the system VM list and deletes the&nbsp; memory allocated to it. This is an optional call, since ficlTermSystem will do this cleanup for you. This function
- is handy if you're going to do a lot of dynamic creation of VMs.
- </DD>
- <DT>
- <B>FICL_VM *ficlNewVM(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Create, initialize, and return a VM from the heap using ficlMalloc. Links the VM into the system VM list for later reclamation by ficlTermSystem.
- </DD>
- <DT>
- <B>FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name)</B>
- </DT>
- <DD>
- Returns the address (also known as an XT in this case) of the specified word in the main dictionary. If not found, returns NULL. The address can be used in a call to ficlExecXT.
- </DD>
- <DT>
- <B>FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Returns a pointer to the main system dictionary, or NULL if the system is uninitialized.
- </DD>
- <DT>
- <B>FICL_DICT *ficlGetEnv(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Returns a pointer to the environment dictionary. This dictionary stores information that describes this implementation as required by the Standard.
- </DD>
- <DT>
- <B>void ficlSetEnv(FICL_SYSTEM *pSys, char *name, UNS32 value)</B>
- </DT>
- <DD>
- Enters a new constant into the environment dictionary, with the specified name and value.
- </DD>
- <DT>
- <B>void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, UNS32 hi, UNS32 lo)</B>
- </DT>
- <DD>
- Enters a new double-cell constant into the environment dictionary with the specified name and value.
- </DD>
- <DT>
- <B>FICL_DICT *ficlGetLoc(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Returns a pointer to the locals dictionary. This function is defined only if FICL_WANT_LOCALS is #defined as non-zero (see sysdep.h). The locals dictionary is the symbol table for <A href=
- "ficl_loc.html">local variables</A>.
- </DD>
- <DT>
- <B>void ficlCompileCore(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Defined in words.c, this function builds ficl's primitives.&nbsp;
- </DD>
- <DT>
- <B>void ficlCompileSoftCore(FICL_SYSTEM *pSys)</B>
- </DT>
- <DD>
- Defined in softcore.c, this function builds ANS required words and ficl extras by evaluating a text string (think of it as a memory mapped file ;-) ). The string itself is built from files
- in the softwords directory by PERL script softcore.pl.&nbsp;
- </DD>
- </DL>
- <HR>
- <TABLE border="0" cellspacing="5" cols="2">
- <TR>
- <TD colspan="2">
- <H2>
- <A name="manifest"></A>Ficl Source Files
- </H2>
- </TD>
- </TR>
- <TR>
- <TD>
- <B>ficl.h</B>
- </TD>
- <TD>
- Declares most public functions and all data structures. Includes sysdep.h and math.h
- </TD>
- </TR>
- <TR>
- <TD>
- <B>sysdep.h</B>
- </TD>
- <TD>
- Declares system dependent functions and contains build control macros. Edit this file to port to another system.
- </TD>
- </TR>
- <TR>
- <TD>
- <B>math.h</B>
- </TD>
- <TD>
- Declares functions for 64 bit math
- </TD>
- </TR>
- <TR>
- <TD>
- <B>dict.c</B>
- </TD>
- <TD>
- Dictionary
- </TD>
- </TR>
- <TR>
- <TD>
- <B>ficl.c</B>
- </TD>
- <TD>
- System initialization, termination, and ficlExec
- </TD>
- </TR>
- <TR>
- <TD>
- <B>float.c</B>
- </TD>
- <TD>
- Adds precompiled definitions from the optional FLOAT word set. Most of the file is conditioned on FICL_WANT_FLOAT
- </TD>
- </TR>
- <TR>
- <TD>
- <B>math64.c</B>
- </TD>
- <TD>
- Implementation of 64 bit math words (except the two unsigned primitives declared in sysdep.h and implemented in sysdep.c)
- </TD>
- </TR>
- <TR>
- <TD>
- <B>prefix.c</B>
- </TD>
- <TD>
- The optional prefix parse step (conditioned on FICL_EXTENDED_PREFIX). This parse step handles numeric constructs like 0xa100, for example. See the release notes for more on parse steps.
- </TD>
- </TR>
- <TR>
- <TD>
- <B>search.c</B>
- </TD>
- <TD>
- Contains C implementations of several of the SEARCH and SEARCH EXT words
- </TD>
- </TR>
- <TR>
- <TD>
- <B>softcore.c</B>
- </TD>
- <TD>
- Contains all of the "soft" words - those written in Forth and compiled by Ficl at startup time. Sources for these words are in the softwords directory. The files softwords/softcore.bat
- and softwords/softcore.pl generate softcore.c from the .fr sources.
- </TD>
- </TR>
- <TR>
- <TD>
- <B>softwords/</B>
- </TD>
- <TD>
- Directory contains sources and translation scripts for the words defined in softcore.c. Softcore.c depends on most of the files in this directory. See softcore.bat for the actual list of
- files that contribute to softcore.c. This is where you'll find source code for the object oriented extensions. PERL script softcore.pl converts the .fr files into softcore.c.
- </TD>
- </TR>
- <TR>
- <TD>
- <B>stack.c</B>
- </TD>
- <TD>
- Stack methods
- </TD>
- </TR>
- <TR>
- <TD>
- <B>sysdep.c</B>
- </TD>
- <TD>
- Implementation of system dependent functions declared in sysdep.h
- </TD>
- </TR>
- <TR>
- <TD>
- <B>testmain.c</B>
- </TD>
- <TD>
- The main() function for unix/linux/win32 console applications - use this as an example to integrate ficl into your system. Also contains some definitions for testing - also useful in
- unix/linux/win32 land.
- </TD>
- </TR>
- <TR>
- <TD>
- <B>tools.c</B>
- </TD>
- <TD>
- Contains C implementations of TOOLS and TOOLS EXT words, the debugger, and debugger support words.
- </TD>
- </TR>
- <TR>
- <TD>
- <B>vm.c</B>
- </TD>
- <TD>
- Virtual Machine methods
- </TD>
- </TR>
- <TR>
- <TD>
- <B>win32.c &amp; unix.c</B>
- </TD>
- <TD>
- Platform extensions words loaded in ficl.c by ficlCompilePlatform() - conditioned on FICL_WANT_PLATFORM
- </TD>
- </TR>
- <TR>
- <TD>
- <B>words.c</B>
- </TD>
- <TD>
- Exports ficlCompileCore(), the run-time dictionary builder, and contains most precompiled CORE and CORE-EXT words.
- </TD>
- </TR>
- </TABLE>
- <HR>
- <H2>
- <A name="extras"></A>Ficl extras
- </H2>
- <H3>
- <A name="exnumber"></A>Number syntax
- </H3>
- You can precede a number with "0x", as in C, and it will be interpreted as a hex value regardless of the value of <CODE>BASE</CODE>. Likewise, numbers prefixed with "0d" will be interpreted as
- decimal values. Example:
-<PRE>
-ok&gt; decimal 123 . cr
-123
-ok&gt; 0x123 . cr
-291
-ok&gt; 0x123 x. cr
-123
-</PRE>
- Note: ficl2.05 and later - this behavior is controlled by the <A href="ficl_parse.html">prefix parser</A> defined in <CODE>prefix.c</CODE>. You can add other prefixes by defining handlers for
- them in ficl or C.
- <H3>
- <A name="exsearch"></A> The <CODE>SEARCH</CODE> wordset and Ficl extensions
- </H3>
- <P>
- Ficl implements many of the search order words in terms of two primitives called <CODE><A href="#tosearch">&gt;SEARCH</A></CODE> and <CODE><A href="#searchfrom">SEARCH&gt;</A></CODE>. As
- their names suggest (assuming you're familiar with Forth), they push and pop the search order stack.
- </P>
- <P>
- The standard does not appear to specify any conditions under which the search order is reset to a sane state. Ficl resets the search order to its default state whenever <TT>ABORT</TT>
- happens. This includes stack underflows and overflows. <TT>QUIT</TT> does not affect the search order. The minimum search order (set by <TT>ONLY</TT>) is equivalent to
- </P>
-<PRE>
-FORTH-WORDLIST 1 SET-ORDER
-</PRE>
- <P>
- There is a default maximum of 16 wordlists in the search order. This can be changed by redefining FICL_DEFAULT_VOCS (declared in sysdep.h).
- </P>
- <P>
- <B>Note</B>: Ficl resets the search order whenever it does <TT>ABORT</TT>. If you don't like this behavior, just comment out the dictResetSearchOrder() lines in ficlExec().
- </P>
- <DL>
- <DT>
- <A name="tosearch"></A><CODE>&gt;search ( wid -- )</CODE>
- </DT>
- <DD>
- Push <TT>wid</TT> onto the search order. Many of the other search order words are written in terms of the <TT>SEARCH&gt;</TT> and <TT>&gt;SEARCH</TT> primitives. This word can be defined in
- ANS Forth as follows
- </DD>
- <DD>
- <TT>: &gt;search&nbsp;&nbsp; &gt;r get-order 1+ r&gt; swap set-order ;</TT>
- </DD>
- <DT>
- <A name="searchfrom"></A><TT>search&gt;&nbsp;&nbsp; ( -- wid )</TT>
- </DT>
- <DD>
- Pop <TT>wid</TT> off the search order (can be coded in ANS Forth as&nbsp;<TT>: search&gt;&nbsp; get-order nip 1- set-order ;</TT> )
- </DD>
- <DT>
- <A name="ficlsetcurrent"></A><TT>ficl-set-current&nbsp;&nbsp; ( wid -- old-wid )</TT>
- </DT>
- <DD>
- Set wid as compile wordlist, leaving the previous compile wordlist on the stack
- </DD>
- <DT>
- <A name="ficlvocabulary"></A><TT>ficl-vocabulary&nbsp;&nbsp; ( nBins "name" -- )</TT>
- </DT>
- <DD>
- Creates a <TT>ficl-wordlist</TT> with the specified number of hash table bins, binds it to the name, and associates the semantics of <TT>vocabulary</TT> with it (replaces the top wid in the
- search order list with its own wid when executed)
- </DD>
- <DT>
- <A name="ficlwordlist"></A><TT>ficl-wordlist&nbsp;&nbsp; ( nBins -- wid )</TT>
- </DT>
- <DD>
- Creates a wordlist with the specified number of hash table bins, and leaves the address of the wordlist on the stack. A <TT>ficl-wordlist</TT> behaves exactly as a regular wordlist, but it
- may search faster depending on the number of bins chosen and the number of words it contains at search time. As implemented in ficl, a wordlist is single threaded by default. <TT>
- ficl-named-wordlist</TT> takes a name for the wordlist and creates a word that pushes the <TT>wid</TT>. This is by contrast to <TT>VOCABULARY</TT>, which also has a name, but replaces the
- top of the search order with its <TT>wid</TT>.
- </DD>
- <DT>
- <A name="ficlforgetwid"></A><TT>forget-wid&nbsp;&nbsp; ( wid -- )</TT>
- </DT>
- <DD>
- Iterates through the specified wordlist and unlinks all definitions whose xt addresses are greater than or equal to the value of <TT>HERE</TT>, the dictionary fill pointer.&nbsp;
- </DD>
- <DT>
- <A name="ficlhide"></A><TT>hide&nbsp;&nbsp; ( -- current-wid-was )</TT>
- </DT>
- <DD>
- Push the <TT>hidden</TT> wordlist onto the search order, and set it as the current compile wordlist (unsing <TT>ficl-set-current</TT>). Leaves the previous compile wordlist ID. I use this
- word to hide implementation factor words that have low reuse potential so that they don't clutter the default wordlist. To undo the effect of hide, execute&nbsp; <B><TT>previous
- set-current</TT></B>
- </DD>
- <DT>
- <A name="ficlhidden"></A><TT>hidden&nbsp;&nbsp; ( -- wid )</TT>
- </DT>
- <DD>
- Wordlist for storing implementation factors of ficl provided words. To see what's in there, try:&nbsp; <B><TT>hide words previous set-current</TT></B>
- </DD>
- <DT>
- <A name="wid-get-name"></A><TT>wid-get-name&nbsp;&nbsp; ( wid -- c-addr u )</TT>
- </DT>
- <DD>
- Ficl wordlists (2.05 and later) have a name property that can be assigned. This is used by <TT>ORDER</TT> to list the names of wordlists in the search order.&nbsp;
- </DD>
- <DT>
- <A name="wid-set-name"></A><TT>wid-set-name&nbsp;&nbsp; ( c-addr wid -- )</TT>
- </DT>
- <DD>
- Ficl wordlists (2.05 and later) have a name property that can be assigned. This is used by <TT>ORDER</TT> to list the names of wordlists in the search order. The name is assumed to be a \0
- terminated string (C style), which conveniently is how Ficl stores word names.&nbsp; See softwords/softcore.fr definition of <TT>brand-wordlist</TT>&nbsp;
- </DD>
- <DT>
- <A name="wid-set-super"></A><TT>wid-set-super&nbsp;&nbsp; ( wid -- )</TT>
- </DT>
- <DD>
- Ficl wordlists have a parent wordlist pointer that is not specified in standard Forth. Ficl initializes this pointer to NULL whenever it creates a wordlist, so it ordinarily has no effect.
- This word sets the parent pointer to the wordlist specified on the top of the stack. Ficl's implementation of <TT>SEARCH-WORDLIST</TT> will chain backward through the parent link of the
- wordlist when searching. This simplifies Ficl's object model in that the search order does not need to reflect an object's class hierarchy when searching for a method. It is possible to
- implement Ficl object syntax in strict ANS Forth, but method finders need to manipulate the search order explicitly.
- </DD>
- </DL>
- <H3>
- <A name="exuser"></A>User variables
- </H3>
- <DL>
- <DT>
- <TT>user&nbsp;&nbsp; ( -- ) name</TT>
- </DT>
- <DD>
- Create a user variable with the given name. User variables are virtual machine local. Each VM allocates a fixed amount of storage for them. You can change the maximum number of user
- variables allowed by defining FICL_USER_CELLS on your compiiler's command line. Default is 16 user cells. User variables behave like <TT>VARIABLE</TT>s in all other respects (you use @ and
- ! on them, for example). Example:
- </DD>
- <DD>
- <DL>
- <DD>
- <TT>user current-class</TT>
- </DD>
- <DD>
- <TT>0 current-class !</TT>
- </DD>
- </DL>
- </DD>
- </DL>
- <H3>
- <A name="exmisc"></A>Miscellaneous
- </H3>
- <DL>
- <DT>
- <TT>-roll&nbsp;&nbsp; ( xu xu-1 ... x0 u -- x0 xu-1 ... x1 )&nbsp;</TT>
- </DT>
- <DD>
- Rotate u+1 items on top of the stack after removing u. Rotation is in the opposite sense to <TT>ROLL</TT>
- </DD>
- </DL>
- <DL>
- <DT>
- <A name="minusrot"></A><TT>-rot&nbsp;&nbsp; ( a b c -- c a b )</TT>
- </DT>
- <DD>
- Rotate the top three stack entries, moving the top of stack to third place. I like to think of this as <TT>1<SUP>1</SUP>/<SUB>2</SUB>swap</TT> because it's good for tucking a single cell
- value behind a cell-pair (like an object).&nbsp;
- </DD>
- </DL>
- <DL>
- <DT>
- <TT>.env&nbsp;&nbsp; ( -- )</TT>
- </DT>
- <DD>
- List all environment variables of the system
- </DD>
- <DT>
- <TT>.hash&nbsp;&nbsp; ( -- )</TT>
- </DT>
- <DD>
- List hash table performance statistics of the wordlist that's first in the search order
- </DD>
- <DT>
- <TT>.ver&nbsp;&nbsp; ( -- )</TT>
- </DT>
- <DD>
- Display ficl version ID
- </DD>
- <DT>
- <TT>&gt;name&nbsp;&nbsp; ( xt -- c-addr u )</TT>
- </DT>
- <DD>
- Convert a word's execution token into the address and length of its name
- </DD>
- <DT>
- <TT>body&gt;&nbsp;&nbsp; ( a-addr -- xt )</TT>
- </DT>
- <DD>
- Reverses the effect of <TT>CORE</TT> word <TT>&gt;body</TT> (converts a parameter field address to an execution token)
- </DD>
- <DT>
- <TT>compile-only</TT>
- </DT>
- <DD>
- Mark the most recently defined word as being executable only while in compile state. Many <TT>immediate</TT> words have this property.
- </DD>
- <DT>
- <TT>empty&nbsp;&nbsp; ( -- )</TT>&nbsp;
- </DT>
- <DD>
- Empty the parameter stack
- </DD>
- <DT>
- <TT>endif</TT>
- </DT>
- <DD>
- Synonym for <TT>THEN</TT>
- </DD>
- <DT>
- <A name="last-word"></A><TT>last-word&nbsp;&nbsp; ( -- xt )</TT>
- </DT>
- <DD>
- Pushes the xt address of the most recently defined word. This applies to colon definitions, constants, variables, and words that use <TT>create</TT>. You can print the name of the most
- recently defined word with&nbsp;
- </DD>
- <DD>
- <B><TT>last-word &gt;name type</TT>&nbsp;</B>
- </DD>
- <DT>
- <TT>parse-word&nbsp;&nbsp; ( &lt;spaces&gt;name -- c-addr u )</TT>
- </DT>
- <DD>
- Skip leading spaces and parse name delimited by a space. c-addr is the address within the input buffer and u is the length of the selected string. If the parse area is empty, the resulting
- string has a zero length. (From the Standard)
- </DD>
- <DT>
- <A name="qfetch"></A><TT>q@&nbsp;&nbsp; ( addr -- x )</TT>
- </DT>
- <DD>
- Fetch a 32 bit quantity from the specified address
- </DD>
- <DT>
- <A name="qbang"></A><TT>q!&nbsp;&nbsp; ( x addr -- )</TT>
- </DT>
- <DD>
- Store a 32 bit quantity to the specified address&nbsp;
- </DD>
- <DT>
- <TT>w@&nbsp;&nbsp; ( addr -- x )</TT>
- </DT>
- <DD>
- Fetch a 16 bit quantity from the specified address
- </DD>
- <DT>
- <TT>w!&nbsp;&nbsp; ( x addr -- )</TT>
- </DT>
- <DD>
- Store a 16 bit quantity to the specified address (the low 16 bits of the given value)
- </DD>
- <DT>
- <A name="xdot"></A><TT>x.&nbsp;&nbsp; ( x -- )</TT>
- </DT>
- <DD>
- Pop and display the value in hex format, regardless of the current value of <TT>BASE</TT>
- </DD>
- </DL>
- <H3>
- <A name="exficlwin"></A>Extra words defined in testmain.c (Win32 and POSIX versions)
- </H3>
- <DL>
- <DT>
- <TT>break&nbsp;&nbsp; ( -- )</TT>
- </DT>
- <DD>
- Does nothing - just a handy place to set a debugger breakpoint
- </DD>
- <DT>
- <TT>cd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( "directory-name&lt;newline&gt;" -- )</TT>
- </DT>
- <DD>
- Executes the Win32 chdir() function, changing the program's logged directory.
- </DD>
- <DT>
- <A name="clock"></A><TT>clock&nbsp;&nbsp; ( -- now )</TT>
- </DT>
- <DD>
- Wrapper for the ANSI C clock() function. Returns the number of clock ticks elapsed since process start.
- </DD>
- <DT>
- <A name="clockspersec"></A><TT>clocks/sec&nbsp;&nbsp; ( -- clocks_per_sec )</TT>
- </DT>
- <DD>
- Pushes the number of ticks in a second as returned by <TT>clock</TT>
- </DD>
- <DT>
- <A name="ficlload"></A><TT>load&nbsp;&nbsp;&nbsp; ( "filename&lt;newline&gt;" -- )</TT>
- </DT>
- <DD>
- Opens the Forth source file specified and loads it one line at a time, like <TT>INCLUDED (FILE)</TT>
- </DD>
- <DT>
- <TT>pwd&nbsp;&nbsp;&nbsp;&nbsp; ( -- )</TT>
- </DT>
- <DD>
- Prints the current working directory as set by <TT>cd</TT>
- </DD>
- <DT>
- <TT>system&nbsp; ( "command&lt;newline&gt;" -- )</TT>
- </DT>
- <DD>
- Issues a command to a shell; implemented with the Win32 system() call.
- </DD>
- <DT>
- <TT>spewhash&nbsp;&nbsp; ( "filename&lt;newline&gt;" -- )</TT>
- </DT>
- <DD>
- Dumps all threads of the current compilation wordlist to the specified text file. This was useful when I thought there might be some point in attempting to optimize the hash function. I no
- longer harbor those illusions.
- </DD>
- </DL>
- <H3>
- Words defined in FiclWin only
- </H3>
- <DL>
- <DT>
- <TT>!oreg&nbsp;&nbsp; ( c -- )</TT>
- </DT>
- <DD>
- Set the value of the simulated LED register as specified (0..255)
- </DD>
- <DT>
- <TT>@ireg&nbsp;&nbsp; ( -- c )</TT>
- </DT>
- <DD>
- Gets the value of the simulated switch block (0..255)
- </DD>
- <DT>
- <TT>!dac&nbsp;&nbsp;&nbsp; ( c -- )</TT>
- </DT>
- <DD>
- Sets the value of the bargraph control as specified. Valid values range from 0..255
- </DD>
- <DT>
- <TT>@adc&nbsp;&nbsp;&nbsp; ( -- c )</TT>
- </DT>
- <DD>
- Fetches the current position of the slider control. Range is 0..255
- </DD>
- <DT>
- <TT>status"&nbsp;&nbsp; ( "ccc&lt;quote&gt;" -- )</TT>
- </DT>
- <DD>
- Set the mainframe window's status line to the text specified, up to the first trailing quote character.
- </DD>
- <DT>
- <A name="ficlms"></A><TT><A href="http://www.taygeta.com/forth/dpans10.htm#10.6.2.1905">ms</A>&nbsp;&nbsp; ( u -- )</TT>
- </DT>
- <DD>
- Causes the running virtual machine to sleep() for the number of milliseconds specified by the top-of-stack value.
- </DD>
- </DL>
- <HR>
- <H2>
- <A name="ansinfo"></A>ANS Required Information
- </H2>
- <B>ANS Forth System</B><BR>
- <B>Providing names from the Core Extensions word set&nbsp;</B><BR>
- <B>Providing the Exception word set</B><BR>
- <B>Providing names from the Exception Extensions word set</B><BR>
- <B>Providing the Locals word set&nbsp;</B><BR>
- <B>Providing the Locals Extensions word set&nbsp;</B><BR>
- <B>Providing the Memory Allocation word set</B><BR>
- <B>Providing the Programming-Tools word set</B><BR>
- <B>Providing names from the Programming-Tools Extensions word set</B><BR>
- <B>Providing the Search-Order word set</B><BR>
- <B>Providing the Search-Order Extensions word set</B>
- <H3>
- Implementation-defined Options
- </H3>
- The implementation-defined items in the following list represent characteristics and choices left to the discretion of the implementor, provided that the requirements of the Standard are met. A
- system shall document the values for, or behaviors of, each item.&nbsp;
- <UL>
- <LI>
- <B>aligned address requirements (3.1.3.3 Addresses);</B>&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">System dependent. You can change the default address alignment by defining FICL_ALIGN on your compiler's command line. The default value is set to 2 in sysdep.h. This
- causes dictionary entries and <TT>ALIGN</TT> and <TT>ALIGNED</TT> to align on 4 byte boundaries. To align on <B>2<SUP>n</SUP></B> byte boundaries, set FICL_ALIGN to <B>n</B>.&nbsp;</FONT>
- </LI>
- <LI>
- <B>behavior of 6.1.1320 EMIT for non-graphic characters</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Depends on target system, C runtime library, and your implementation of ficlTextOut().</FONT>
- </LI>
- <LI>
- <B>character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">None implemented in the versions supplied in words.c. Because ficlExec() is supplied a text buffer externally, it's up to your system to define how that buffer will
- be obtained.</FONT>
- </LI>
- <LI>
- <B>character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750 KEY)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Depends on target system and implementation of ficlTextOut()</FONT>
- </LI>
- <LI>
- <B>character-aligned address requirements (3.1.3.3 Addresses)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl characters are one byte each. There are no alignment requirements.</FONT>
- </LI>
- <LI>
- <B>character-set-extensions matching characteristics (3.4.2 Finding definition n<FONT color="#000000">ames)</FONT></B><FONT color="#000000">;&nbsp;</FONT>
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">No special processing is performed on characters beyond case-folding. Therefore, extended characters will not match their unaccented counterparts.</FONT>
- </LI>
- <LI>
- <B>conditions under which control characters match a space delimiter (3.4.1.1 Delimiters)</B>;<FONT color="#FF6666">&nbsp;</FONT>
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl uses the Standard C function isspace() to distinguish space characters. The rest is up to your library vendor.</FONT>
- </LI>
- <LI>
- <B>format of the control-flow stack (3.2.3.2 Control-flow stack)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Uses the data stack</FONT>
- </LI>
- <LI>
- <B>conversion of digits larger than thirty-five (3.2.1.2 Digit conversion)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">The maximum supported value of <TT>BASE</TT> is 36. Ficl will assertion fail in function ltoa of vm.c if the base is found to be larger than 36 or smaller than 2.
- There will be no effect if NDEBUG is defined</FONT>, however, other than possibly unexpected behavior.&nbsp;
- </LI>
- <LI>
- <B>display after input terminates in 6.1.0695 ACCEPT and 6.2.1390 EXPECT</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Target system dependent</FONT>
- </LI>
- <LI>
- <B>exception abort sequence (as in 6.1.0680 ABORT")</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Does <TT>ABORT</TT></FONT>
- </LI>
- <LI>
- <B>input line terminator (3.2.4.1 User input device)</B>;<FONT color="#FF0000">&nbsp;</FONT>
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Target system dependent (implementation of outer loop that calls ficlExec)</FONT>
- </LI>
- <LI>
- <B>maximum size of a counted string, in characters (3.1.3.4 Counted strings, 6.1.2450 WORD)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">255</FONT>
- </LI>
- <LI>
- <B>maximum size of a parsed string (3.4.1 Parsing)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- Limited by available memory and the maximum unsigned value that can fit in a CELL (2<SUP>32</SUP>-1).&nbsp;
- </LI>
- <LI>
- <B>maximum size of a definition name, in characters (3.3.1.2 Definition names)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl stores the first 31 characters of a definition name.</FONT>
- </LI>
- <LI>
- <B>maximum string length for 6.1.1345 ENVIRONMENT?, in characters</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Same as maximum definition name length</FONT>
- </LI>
- <LI>
- <B>method of selecting 3.2.4.1 User input device</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- None supported. This is up to the target system&nbsp;
- </LI>
- <LI>
- <B>method of selecting 3.2.4.2 User output device</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- None supported. This is up to the target system&nbsp;
- </LI>
- <LI>
- <B>methods of dictionary compilation (3.3 The Forth dictionary)</B>;&nbsp;
- </LI>
- <LI>
- <B>number of bits in one address unit (3.1.3.3 Addresses)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Target system dependent. Ficl generally supports processors that can address 8 bit quantities, but there is no dependency that I'm aware of.</FONT>
- </LI>
- <LI>
- <B>number representation and arithmetic (3.2.1.1 Internal number representation)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- System dependent. Ficl represents a CELL internally as a union that can hold INT32 (a signed 32 bit scalar value), UNS32 (32 bits unsigned), and an untyped pointer. No specific byte
- ordering is assumed.&nbsp;
- </LI>
- <LI>
- <B>ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types, 3.1.4 Cell-pair types)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- Assuming a 32 bit implementation, range for signed single-cell values is -2<SUP>31</SUP>..2<SUP>31</SUP>-1. Range for unsigned single cell values is 0..2<SUP>32</SUP>-1. Range for signed
- double-cell values is -2<SUP>63</SUP>..2<SUP>63</SUP>-1. Range for unsigned single cell values is 0..2<SUP>64</SUP>-1.&nbsp;
- </LI>
- <LI>
- <B>read-only data-space regions (3.3.3 Data space)</B>;
- </LI>
- <LI>
- <BR>
- None&nbsp;
- </LI>
- <LI>
- <B>size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient regions)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- Default is 255. Depends on the setting of nPAD in ficl.h.&nbsp;
- </LI>
- <LI>
- <B>size of one cell in address units (3.1.3 Single-cell types)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">System dependent, generally four.</FONT>
- </LI>
- <LI>
- <B>size of one character in address units (3.1.2 Character types)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">System dependent, generally one.</FONT>
- </LI>
- <LI>
- <B>size of the keyboard terminal input buffer (3.3.3.5 Input buffers)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">This buffer is supplied by the host program. Ficl imposes no practical limit.</FONT>
- </LI>
- <LI>
- <B>size of the pictured numeric output string buffer (3.3.3.6 Other transient regions)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- Default is 255 characters. Depends on the setting of nPAD in ficl.h.&nbsp;
- </LI>
- <LI>
- <B>size of the scratch area whose address is returned by 6.2.2000 PAD (3.3.3.6 Other transient regions)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- Not presently supported&nbsp;
- </LI>
- <LI>
- <B>system case-sensitivity characteristics (3.4.2 Finding definition names)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl is not case sensitive</FONT>
- </LI>
- <LI>
- <B>system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">"ok&gt;"</FONT>
- </LI>
- <LI>
- <B>type of division rounding (3.2.2.1 Integer division, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1890 MOD)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Symmetric</FONT>
- </LI>
- <LI>
- <B>values of 6.1.2250 STATE when true</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">One (no others)</FONT>
- </LI>
- <LI>
- <B>values returned after arithmetic overflow (3.2.2.2 Other integer operations)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- System dependent. Ficl makes no special checks for overflow.&nbsp;
- </LI>
- <LI>
- <B>whether the current definition can be found after 6.1.1250 DOES&gt; (6.1.0450 :)</B>.&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">No. Definitions are unsmudged after ; only, and only then if no control structure matching problems have been detected.</FONT>
- </LI>
- </UL>
- <H3>
- Ambiguous Conditions
- </H3>
- A system shall document the system action taken upon each of the general or specific ambiguous conditions identified in this Standard. See 3.4.4 Possible actions on an ambiguous
- condition.&nbsp;
- <P>
- The following general ambiguous conditions could occur because of a combination of factors:&nbsp;
- </P>
- <UL>
- <LI>
- <B>a name is neither a valid definition name nor a valid number during text interpretation (3.4 The Forth text interpreter)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl does <TT>ABORT</TT> and prints the name followed by " not found".</FONT>
- </LI>
- <LI>
- <B>a definition name exceeded the maximum length allowed (3.3.1.2 Definition names)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl stores the first 31 characters of the definition name, and uses all characters of the name in computing its hash code. The actual length of the name, up to 255
- characters, is stored in the definition's length field.</FONT>
- </LI>
- <LI>
- <B>addressing a region not listed in 3.3.3 Data Space</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">No problem: all addresses in ficl are absolute. You can reach any 32 bit address in Ficl's address space.</FONT>
- </LI>
- <LI>
- <B>argument type incompatible with specified input parameter, e.g., passing a flag to a word expecting an n (3.1 Data types)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl makes no check for argument type compatibility. Effects of a mismatch vary widely depending on the specific problem and operands.</FONT>
- </LI>
- <LI>
- <B>attempting to obtain the execution token, (e.g., with 6.1.0070 ', 6.1.1550 FIND, etc.) of a definition with undefined interpretation semantics</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl returns a valid token, but the result of executing that token while interpreting may be undesirable.</FONT>
- </LI>
- <LI>
- <B>dividing by zero (6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1561 FM/MOD, 6.1.1890 MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 8.6.1.1820 M*/)</B>;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Results are target procesor dependent. Generally, Ficl makes no check for divide-by-zero. The target processor will probably throw an exception.</FONT>
- </LI>
- <LI>
- <B>insufficient data-stack space or return-stack space (stack overflow)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">With FICL_ROBUST (sysdep.h) set &gt;= 2, most parameter stack operations are checked for underflow and overflow. Ficl does not check the return stack.</FONT>
- </LI>
- <LI>
- <B>insufficient space for loop-control parameters</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">No check - Evil results.</FONT>
- </LI>
- <LI>
- <B>insufficient space in the dictionary</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl generates an error message if the dictionary is too full to create a definition header. It checks <TT>ALLOT</TT> as well, but it is possible to make an unchecked
- allocation request that overflows the dictionary.</FONT>
- </LI>
- <LI>
- <B>interpreting a word with undefined interpretation semantics</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl protects all ANS Forth words with undefined interpretation semantics from being executed while in interpret state. It is possible to defeat this protection using
- ' (tick) and <TT>EXECUTE</TT>, though.</FONT>
- </LI>
- <LI>
- <B>modifying the contents of the input buffer or a string literal (3.3.3.4 Text-literal regions, 3.3.3.5 Input buffers)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Varies depending on the nature of the buffer. The input buffer is supplied by ficl's host function, and may reside in read-only memory. If so, writing the input
- buffer can ganerate an exception. String literals are stored in the dictionary, and are writable.</FONT>
- </LI>
- <LI>
- <B>overflow of a pictured numeric output string</B>;
- </LI>
- <LI>
- <BR>
- In the unlikely event you are able to construct a pictured numeric string of more than 255 characters, the system will be corrupted unpredictably. The buffer area that holds pictured
- numeric output is at the end of the virtual machine. Whatever is mapped after the offending VM in memory will be trashed, along with the heap structures that contain it.&nbsp;
- </LI>
- <LI>
- <B>parsed string overflow</B>;
- </LI>
- <LI>
- <BR>
- Ficl does not copy parsed strings unless asked to. Ordinarily, a string parsed from the input buffer during normal interpretation is left in-place, so there is no possibility of overflow.
- If you ask to parse a string into the dictionary, as in <TT>SLITERAL</TT>, you need to have enough room for the string, otherwise bad things may happen. This is not usually a problem.&nbsp;
- </LI>
- <LI>
- <B>producing a result out of range, e.g., multiplication (using *) results in a value too big to be represented by a single-cell integer (6.1.0090 *, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0570
- &gt;NUMBER, 6.1.1561 FM/MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 6.2.0970 CONVERT, 8.6.1.1820 M*/)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Value will be truncated</FONT>
- </LI>
- <LI>
- <B>reading from an empty data stack or return stack (stack underflow)</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Most stack underflows are detected and prevented if FICL_ROBUST (sysdep.h) is set to 2 or greater. Otherwise, the stack pointer and size are likely to be
- trashed.</FONT>
- </LI>
- <LI>
- <B>unexpected end of input buffer, resulting in an attempt to use a zero-length string as a name</B>;&nbsp;
- </LI>
- <LI>
- <BR>
- <FONT color="#000000">Ficl returns for a new input buffer until a non-empty one is supplied.</FONT>
- </LI>
- </UL>
- The following specific ambiguous conditions are noted in the glossary entries of the relevant words:&nbsp;
- <UL>
- <LI>
- <B>&gt;IN greater than size of input buffer (3.4.1 Parsing)</B>
- </LI>
- <LI>
- <BR>
- Bad Things occur - unpredictable bacause the input buffer is supplied by the host program's outer loop.&nbsp;
- </LI>
- <LI>
- <B>6.1.2120 RECURSE appears after 6.1.1250 DOES&gt;</B>
- </LI>
- <LI>
- <BR>
- It finds the address of the definition before <TT>DOES&gt;</TT>
- </LI>
- <LI>
- <B>argument input source different than current input source for 6.2.2148 RESTORE-INPUT</B>
- </LI>
- <LI>
- <BR>
- Not implemented&nbsp;
- </LI>
- <LI>
- <B>data space containing definitions is de-allocated (3.3.3.2 Contiguous regions)</B>
- </LI>
- <LI>
- <BR>
- This is OK until the cells are overwritten with something else. The dictionary maintains a hash table, and the table must be updated in order to de-allocate words without corruption.&nbsp;
- </LI>
- <LI>
- <B>data space read/write with incorrect alignment (3.3.3.1 Address alignment)</B>
- </LI>
- <LI>
- <BR>
- Target processor dependent. Consequences include: none (Intel), address error exception (68K).&nbsp;
- </LI>
- <LI>
- <B>data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860 C,)</B>
- </LI>
- <LI>
- <BR>
- See above on data space read/write alignment&nbsp;
- </LI>
- <LI>
- <B>less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)</B>
- </LI>
- <LI>
- <BR>
- Ficl detects a stack underflow and reports it, executing <TT>ABORT,</TT> as long as FICL_ROBUST is two or larger.&nbsp;
- </LI>
- <LI>
- <B>loop-control parameters not available ( 6.1.0140 +LOOP, 6.1.1680 I, 6.1.1730 J, 6.1.1760 LEAVE, 6.1.1800 LOOP, 6.1.2380 UNLOOP)</B>
- </LI>
- <LI>
- <BR>
- Loop initiation words are responsible for checking the stack and guaranteeing that the control parameters are pushed. Any underflows will be detected early if FICL_ROBUST is set to two or
- greater. Note however that Ficl only checks for return stack underflows at the end of each line of text.&nbsp;
- </LI>
- <LI>
- <B>most recent definition does not have a name (6.1.1710 IMMEDIATE)</B>
- </LI>
- <LI>
- <BR>
- No problem.&nbsp;
- </LI>
- <LI>
- <B>name not defined by 6.2.2405 VALUE used by 6.2.2295 TO</B>
- </LI>
- <LI>
- <BR>
- Ficl's version of <TT>TO</TT> works correctly with <TT>VALUE</TT>s, <TT>CONSTANT</TT>s and <TT>VARIABLE</TT>s.&nbsp;
- </LI>
- <LI>
- <B>name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['], 6.2.2530 [COMPILE])</B>
- </LI>
- <LI>
- <BR>
- Ficl prints an error message and does <TT>ABORT</TT>
- </LI>
- <LI>
- <B>parameters are not of the same type (6.1.1240 DO, 6.2.0620 ?DO, 6.2.2440 WITHIN)</B>
- </LI>
- <LI>
- <BR>
- No check. Results vary depending on the specific problem.&nbsp;
- </LI>
- <LI>
- <B>6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO</B>
- </LI>
- <LI>
- <BR>
- The word is postponed correctly.&nbsp;
- </LI>
- <LI>
- <B>string longer than a counted string returned by 6.1.2450 WORD</B>
- </LI>
- <LI>
- <BR>
- Ficl stores the first FICL_STRING_MAX-1 chars in the destination buffer. (The extra character is the trailing space required by the standard. Yuck.)&nbsp;
- </LI>
- <LI>
- <B>u greater than or equal to the number of bits in a cell (6.1.1805 LSHIFT, 6.1.2162 RSHIFT)</B>
- </LI>
- <LI>
- <BR>
- Depends on target process or and C runtime library implementations of the &lt;&lt; and &gt;&gt; operators on unsigned values. For I386, the processor appears to shift modulo the number of
- bits in a cell.&nbsp;
- </LI>
- <LI>
- <B>word not defined via 6.1.1000 CREATE (6.1.0550 &gt;BODY, 6.1.1250 DOES&gt;)</B>
- </LI>
- <LI>
- <BR>
- <B>words improperly used outside 6.1.0490 &lt;# and 6.1.0040 #&gt; (6.1.0030 #, 6.1.0050 #S, 6.1.1670 HOLD, 6.1.2210 SIGN)</B><BR>
- Don't. <TT>CREATE</TT> reserves a field in words it builds for <TT>DOES&gt;</TT>to fill in. If you use <TT>DOES&gt;</TT> on a word not made by <TT>CREATE</TT>, it will overwrite the first
- cell of its parameter area. That's probably not what you want. Likewise, pictured numeric words assume that there is a string under construction in the VM's scratch buffer. If that's not
- the case, results may be unpleasant.
- </LI>
- </UL>
- <H3>
- Locals Implementation-defined options
- </H3>
- <UL>
- <LI>
- <B>maximum number of locals in a definition (13.3.3 Processing locals, 13.6.2.1795 LOCALS|)</B>
- </LI>
- <LI>
- <BR>
- Default is 16. Change by redefining FICL_MAX_LOCALS, defined in sysdep.h
- </LI>
- </UL>
- <H3>
- Locals Ambiguous conditions
- </H3>
- <UL>
- <LI>
- <B>executing a named local while in interpretation state (13.6.1.0086 (LOCAL))</B>
- </LI>
- <LI>
- <BR>
- Locals can be found in interpretation state while in the context of a definition under construction. Under these circumstances, locals behave correctly. Locals are not visible at all
- outside the scope of a definition.&nbsp;
- </LI>
- <LI>
- <B>name not defined by VALUE or LOCAL (13.6.1.2295 TO)</B>
- </LI>
- <LI>
- <BR>
- See the CORE ambiguous conditions, above (no change)
- </LI>
- </UL>
- <H3>
- Programming Tools Implementation-defined options
- </H3>
- <UL>
- <LI>
- <B>source and format of display by 15.6.1.2194 SEE</B>
- </LI>
- <LI>
- <BR>
- SEE de-compiles definitions from the dictionary. Because Ficl words are threaded by their header addresses, it is very straightforward to print the name and other characteristics of words
- in a definition. Primitives are so noted. Colon definitions are decompiled, but branch target labels are not reconstructed. Literals and string literals are so noted, and their contents
- displayed.
- </LI>
- </UL>
- <H3>
- Search Order Implementation-defined options
- </H3>
- <UL>
- <LI>
- <B>maximum number of word lists in the search order (16.3.3 Finding definition names, 16.6.1.2197 SET-ORDER)</B>&nbsp;
- </LI>
- <LI>
- <BR>
- Defaults to 16. Can be changed by redefining FICL_DEFAULT_VOCS, declared in sysdep.h&nbsp;
- </LI>
- <LI>
- <B>minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY)</B>&nbsp;
- </LI>
- <LI>
- <BR>
- Equivalent to <TT>FORTH-WORDLIST 1 SET-ORDER</TT>
- </LI>
- </UL>
- <H3>
- Search Order Ambiguous conditions
- </H3>
- <UL>
- <LI>
- <B>changing the compilation word list (16.3.3 Finding definition names)</B>
- </LI>
- <LI>
- <BR>
- Ficl stores a link to the current definition independently of the compile wordlist while it is being defined, and links it into the compile wordlist only after the definition completes
- successfully. Changing the compile wordlist mid-definition will cause the definition to link into the <I>new</I> compile wordlist.&nbsp;
- </LI>
- <LI>
- <B>search order empty (16.6.2.2037 PREVIOUS)</B>
- </LI>
- <LI>
- <BR>
- Ficl prints an error message if the search order underflows, and resets the order to its default state.&nbsp;
- </LI>
- <LI>
- <B>too many word lists in search order (16.6.2.0715 ALSO)</B>
- </LI>
- <LI>
- <BR>
- Ficl prints an error message if the search order overflows, and resets the order to its default state.
- </LI>
- </UL>
- </DIV>
- </BODY>
-</HTML>
+</b>
+<p>
+
+I am interested in hearing from anyone who uses Ficl. If you have a
+problem, a success story, a defect, an enhancement request, or if
+you would like to contribute to the ficl release, please
+<a href="mailto:john_sadler@alum.mit.edu">send me email</a>.
+<p>
+
+
+<h2><a name="features">Ficl Features</a></h2>
+
+<ul>
+
+<li>
+Simple to integrate into existing systems: the sample
+implementation requires three Ficl function calls (see the example
+program in <b>main.c</b>).
+
+<li>
+Written in ANSI C for portability.
+
+<li>
+Standard: Implements the ANS Forth CORE word set, part of the
+CORE EXT word set, SEARCH and SEARCH EXT, TOOLS and part of TOOLS EXT,
+LOCAL and LOCAL EXT, EXCEPTION, MEMORY, and various extras.
+
+<li>
+Extensible: you can export code written in Forth, C, or ASM in a
+straightforward way. Ficl provides open facilities for extending the
+language in an application specific way. You can even add new
+control structures (not surprising if you're familiar with Forth)
+
+<li>
+Ficl and C/C++ can interact in two ways: Ficl can wrap C code,
+and C functions can invoke Ficl code.
+
+<li>
+Ficl code is thread safe and re-entrant: your program can have one or more
+Ficl "systems", and each "system" can have one or Ficl virtual machines.
+Each Ficl virtual machine has an otherwise complete state, and each can
+be bound to a separate I/O channel (or none at all).
+An optional function called ficlLockDictionary() can control
+exclusive dictionary access. This function is stubbed out by
+default (See FICL_MULTITHREAD in sysdep.h). As long as there is only
+one "session" that can compile words into the dictionary, you do not
+need exclusive dictionary access for multithreading.
+<b>Note</b>:
+while the code is re-entrant, there are still restrictions on how you
+can use it safely in a multithreaded system. Specifically, the VM
+itself maintains state, so you generally need a VM per thread in a
+multithreaded system. If interrupt service routines make calls into Ficl
+code that alters VM state, then these generally need their
+own VM as well. Alternatively, you could provide a mutual exclusion
+mechanism to serialize access to a VM from multiple threads.
+
+<li>
+ROMable: Ficl is designed to work in RAM based and ROM code / RAM
+data environments. It does require somewhat more memory than a pure ROM
+implementation because it builds its system dictionary in RAM
+at startup time.
+
+<li>
+Written in ANSI C to be as simple as I can make it to understand,
+support, debug, and port. Compiles without complaint at <code>/Az /W4</code> (require
+ANSI C, max. warnings) under Microsoft Visual C++, and <code>-ansi</code>
+under GCC. Ports to several other toolchains and operating systems
+(notably FreeBSD and Linux flavors) exist.
+
+<li> Does full 32 bit math (but you need to implement two mixed
+precision math primitives (see sysdep.c)) </li>
+
+</ul>
+
+<hr>
+
+<h2><a name="porting">Porting Ficl</a></h2>
+
+To install Ficl on your target system, you need an ANSI C compiler and
+its runtime library. Inspect the system dependent macros and functions
+in <b>sysdep.h</tt> and <tt>sysdep.c</tt> and edit them to suit
+your system. For example, <tt>INT16</tt> is a <tt>short</tt> on some
+compilers and an <tt>int</tt> on others. Check the default <tt>CELL</tt>
+alignment controlled by <tt> FICL_ALIGN</tt>. If necessary, add new
+definitions of <tt>ficlMalloc, ficlFree, ficlRealloc</tt>, and <tt>ficlTextOut</tt>
+to work with your operating system. Finally, use <tt>testmain.c</tt> as
+a guide to installing the ficl system and one or more virtual machines
+into your code. You do not need to include <tt>testmain.c</tt> in your
+build.
+<p>
+Note: ficlLockDictionary can be left unimplemented in most
+multithreaded implementations - it's only necessary if you expect to
+have more than one thread modifying the dictionary at the same
+time. If you do decide to implement it, make sure calls to
+ficlLockDictionary can nest properly (see the comments in sysdep.h). You
+need to keep count of nested locks and unlocks and do the right
+thing.
+<p>
+
+Feel free to stub out the double precision math functions (which are
+presently implemented as inline assembly because it's so easy on many 32
+bit processors) with kludge code that only goes to 32 bit
+precision. In most applications, you won't notice the difference. If
+you're doing a lot of number crunching, consider implementing them
+correctly.
+
+
+<h3>Build Controls</h3>
+
+The file sysdep.h contains default values for build controls. Most of
+these are written such that if you define them on the compiler command
+line, the defaults are overridden. I suggest you take the defaults
+on everything below the "build controls" section until you're confident
+of your port. Beware of declaring too small a dictionary, for example.
+You need about 3200 cells for a full system, about 2000 if you
+strip out most of the "soft" words.
+
+<h3>Softcore</h3>
+Many words from all the supported wordsets are written in Forth, and
+stored as a big string that Ficl compiles when it starts. The sources
+for all of these words are in directory <b>softcore</b>. There is a
+.bat file (softcore.bat) and a PERL 5 script (softcore.pl) that convert
+Forth files into the file softcore.c, so softcore.c is really dependent
+on the Forth sources. This is not reflected in the Visual C++ project
+database. For the time being, it's a manual step. You can edit
+<b>make.bat</b> to change the list of files that contribute to
+<b>softcore.c</b>.
+
+<h3>To-Do List (target system dependent words)</h3>
+
+<ul>
+
+<li>
+Unimplemented system dependent <tt>CORE</tt> word: <tt>KEY</tt>
+(implement this yourself if you need it)
+
+<li>
+Kludged <tt>CORE</tt> word: <tt>ACCEPT</tt> (implement this
+better if you need to)
+
+</ul>
+
+<h2><a name="api">Application Programming Interface</a></h2>
+
+The following is a partial listing of functions that interface your
+system or program to Ficl. For a complete listing, see <b>ficl.h</b>
+(which is heavily commented). For examples, see <b>main.c</b> and the
+FiclWin sources (<a href="#download">below</a>).
+<dl>
+ <dt> <b>FICL_SYSTEM *ficlInitSystem(int nDictCells)</b> </dt>
+ <dd> Initializes Ficl's shared system data structures, and creates the
+dictionary allocating the specified number of CELLs from the heap (by a
+call to ficlMalloc) </dd>
+ <dt> <b>void ficlTermSystem(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Reclaims memory allocated for the ficl system including all
+dictionaries and all virtual machines created by vmCreate. Any uses of
+the memory allocation words (allocate and resize) are your
+problem. </dd>
+ <dt> <b>int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code,
+char flags)</b> </dt>
+ <dd> Create a primitive word in ficl's main dictionary with the given
+name, code pointer, and properties (immediate, compile only, etc) as
+described by the flags (see ficl.h for flag descriptions of
+the form FW_XXXX) </dd>
+ <dt> <b>int ficlExec(FICL_VM *pVM, char *text)</b> </dt>
+ <dd> Feed the specified C string ('\0' terminated) to the given
+virtual machine for evaluation. Returns various exception codes (VM_XXXX
+in ficl.h) to indicate the reason for returning. Normal exit
+condition is VM_OUTOFTEXT, indicating that the VM consumed the string
+successfully and is back for more. ficlExec calls can be nested, and
+the function itself is re-entrant, but note that a VM is
+static, so you have to take reasonable precautions (for example, use one
+VM per thread in a multithreaded system if you want multiple threads to
+be able to execute commands). </dd>
+ <dt> <b>int ficlExecC(FICL_VM *pVM, char *text, int nChars)</b> </dt>
+ <dd> Same as ficlExec, but takes a count indicating the length of the
+supplied string. Setting nChars to -1 is equivalent to ficlExec (expects
+'\0' termination). </dd>
+ <dt> <b>int ficlExecXT(FICL_VM *pVM, FICL_WORD *pFW)</b> </dt>
+ <dd> Same as ficlExec, but takes a pointer to a FICL_WORD instead of a
+string. Executes the word and returns after it has finished. If
+executing the word results in an exception, this function will
+re-throw the same code if it is nested under another ficlExec family
+function, or return the exception code directly if not. This function
+is useful if you need to execute the same word repeatedly -
+you save the dictionary search and outer interpreter overhead. </dd>
+ <dt> <b>void ficlFreeVM(FICL_VM *pVM)</b> </dt>
+ <dd> Removes the VM in question from the system VM list and deletes
+the&nbsp; memory allocated to it. This is an optional call, since
+ficlTermSystem will do this cleanup for you. This function is
+handy if you're going to do a lot of dynamic creation of VMs. </dd>
+ <dt> <b>FICL_VM *ficlNewVM(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Create, initialize, and return a VM from the heap using
+ficlMalloc. Links the VM into the system VM list for later reclamation
+by ficlTermSystem. </dd>
+ <dt> <b>FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name)</b> </dt>
+ <dd> Returns the address (also known as an XT in this case) of the
+specified word in the main dictionary. If not found, returns NULL. The
+address can be used in a call to ficlExecXT. </dd>
+ <dt> <b>FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Returns a pointer to the main system dictionary, or NULL if the
+system is uninitialized. </dd>
+ <dt> <b>FICL_DICT *ficlGetEnv(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Returns a pointer to the environment dictionary. This dictionary
+stores information that describes this implementation as required by the
+Standard. </dd>
+ <dt> <b>void ficlSetEnv(FICL_SYSTEM *pSys, char *name, UNS32 value)</b> </dt>
+ <dd> Enters a new constant into the environment dictionary, with the
+specified name and value. </dd>
+ <dt> <b>void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, UNS32 hi,
+UNS32 lo)</b> </dt>
+ <dd> Enters a new double-cell constant into the environment dictionary
+with the specified name and value. </dd>
+ <dt> <b>FICL_DICT *ficlGetLoc(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Returns a pointer to the locals dictionary. This function is
+defined only if FICL_WANT_LOCALS is #defined as non-zero (see sysdep.h).
+The locals dictionary is the symbol table for <a href="ficl_loc.html">local
+variables</a>. </dd>
+ <dt> <b>void ficlCompileCore(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Defined in words.c, this function builds ficl's primitives.&nbsp;
+ </dd>
+ <dt> <b>void ficlCompileSoftCore(FICL_SYSTEM *pSys)</b> </dt>
+ <dd> Defined in softcore.c, this function builds ANS required words
+and ficl extras by evaluating a text string (think of it as a memory
+mapped file ;-) ). The string itself is built from files in
+the softwords directory by PERL script softcore.pl.&nbsp; </dd>
+</dl>
+<hr>
+<table border="0" cellspacing="5" cols="2">
+ <tbody>
+ <tr>
+ <td colspan="2">
+ <h2> <a name="manifest"></a>Ficl Source Files </h2>
+ </td>
+ </tr>
+ <tr>
+ <td> <b>ficl.h</b> </td>
+ <td> Declares most public functions and all data structures.
+Includes sysdep.h and math.h </td>
+ </tr>
+ <tr>
+ <td> <b>sysdep.h</b> </td>
+ <td> Declares system dependent functions and contains build
+control macros. Edit this file to port to another system. </td>
+ </tr>
+ <tr>
+ <td> <b>math.h</b> </td>
+ <td> Declares functions for 64 bit math </td>
+ </tr>
+ <tr>
+ <td> <b>dict.c</b> </td>
+ <td> Dictionary </td>
+ </tr>
+ <tr>
+ <td> <b>ficl.c</b> </td>
+ <td> System initialization, termination, and ficlExec </td>
+ </tr>
+ <tr>
+ <td> <b>float.c</b> </td>
+ <td> Adds precompiled definitions from the optional FLOAT word
+set. Most of the file is conditioned on FICL_WANT_FLOAT </td>
+ </tr>
+ <tr>
+ <td> <b>math64.c</b> </td>
+ <td> Implementation of 64 bit math words (except the two unsigned
+primitives declared in sysdep.h and implemented in sysdep.c) </td>
+ </tr>
+ <tr>
+ <td> <b>prefix.c</b> </td>
+ <td> The optional prefix parse step (conditioned on
+FICL_EXTENDED_PREFIX). This parse step handles numeric constructs like
+0xa100, for example. See the release notes for more on parse steps. </td>
+ </tr>
+ <tr>
+ <td> <b>search.c</b> </td>
+ <td> Contains C implementations of several of the SEARCH and
+SEARCH EXT words </td>
+ </tr>
+ <tr>
+ <td> <b>softcore.c</b> </td>
+ <td> Contains all of the "soft" words - those written in Forth and
+compiled by Ficl at startup time. Sources for these words are in the
+softwords directory. The files softwords/softcore.bat and
+softwords/softcore.pl generate softcore.c from the .fr sources. </td>
+ </tr>
+ <tr>
+ <td> <b>softwords/</b> </td>
+ <td> Directory contains sources and translation scripts for the
+words defined in softcore.c. Softcore.c depends on most of the files in
+this directory. See softcore.bat for the actual list of
+files that contribute to softcore.c. This is where you'll find source
+code for the object oriented extensions. PERL script softcore.pl
+converts the .fr files into softcore.c. </td>
+ </tr>
+ <tr>
+ <td> <b>stack.c</b> </td>
+ <td> Stack methods </td>
+ </tr>
+ <tr>
+ <td> <b>sysdep.c</b> </td>
+ <td> Implementation of system dependent functions declared in
+sysdep.h </td>
+ </tr>
+ <tr>
+ <td> <b>testmain.c</b> </td>
+ <td> The main() function for unix/linux/win32 console applications
+- use this as an example to integrate ficl into your system. Also
+contains some definitions for testing - also useful in
+unix/linux/win32 land. </td>
+ </tr>
+ <tr>
+ <td> <b>tools.c</b> </td>
+ <td> Contains C implementations of TOOLS and TOOLS EXT words, the
+debugger, and debugger support words. </td>
+ </tr>
+ <tr>
+ <td> <b>vm.c</b> </td>
+ <td> Virtual Machine methods </td>
+ </tr>
+ <tr>
+ <td> <b>win32.c &amp; unix.c</b> </td>
+ <td> Platform extensions words loaded in ficl.c by
+ficlCompilePlatform() - conditioned on FICL_WANT_PLATFORM </td>
+ </tr>
+ <tr>
+ <td> <b>words.c</b> </td>
+ <td> Exports ficlCompileCore(), the run-time dictionary builder,
+and contains most precompiled CORE and CORE-EXT words. </td>
+ </tr>
+ </tbody>
+</table>
+<hr>
+<h2> <a name="extras"></a>Ficl extras </h2>
+<h3> <a name="exnumber"></a>Number syntax </h3>
+You can precede a number with "0x", as in C, and it will be interpreted
+as a hex value regardless of the value of <code>BASE</code>. Likewise,
+numbers prefixed with "0d" will be interpreted as decimal values.
+Example:
+<pre>ok&gt; decimal 123 . cr<br>123<br>ok&gt; 0x123 . cr<br>291<br>ok&gt; 0x123 x. cr<br>123<br></pre>
+Note: ficl2.05 and later - this behavior is controlled by the <a
+ href="ficl_parse.html">prefix parser</a> defined in <code>prefix.c</code>.
+You can add other prefixes by defining handlers for them in ficl
+or C.
+<h3> <a name="exsearch"></a> The <code>SEARCH</code> wordset and Ficl
+extensions </h3>
+<p> Ficl implements many of the search order words in terms of two
+primitives called <code><a href="#tosearch">&gt;SEARCH</a></code> and <code><a
+ href="#searchfrom">SEARCH&gt;</a></code>. As their names
+suggest (assuming you're familiar with Forth), they push and pop the
+search order stack. </p>
+<p> The standard does not appear to specify any conditions under which
+the search order is reset to a sane state. Ficl resets the search order
+to its default state whenever <tt>ABORT</tt> happens. This includes
+stack underflows and overflows. <tt>QUIT</tt> does not affect the search
+order. The minimum search order (set by <tt>ONLY</tt>) is equivalent
+to </p>
+<pre>FORTH-WORDLIST 1 SET-ORDER<br></pre>
+<p> There is a default maximum of 16 wordlists in the search order. This
+can be changed by redefining FICL_DEFAULT_VOCS (declared in sysdep.h). </p>
+<p> <b>Note</b>: Ficl resets the search order whenever it does <tt>ABORT</tt>.
+If you don't like this behavior, just comment out the
+dictResetSearchOrder() lines in ficlExec(). </p>
+<dl>
+ <dt> <a name="tosearch"></a><code>&gt;search ( wid -- )</code> </dt>
+ <dd> Push <tt>wid</tt> onto the search order. Many of the other search
+order words are written in terms of the <tt>SEARCH&gt;</tt> and <tt>&gt;SEARCH</tt>
+primitives. This word can be defined in ANS Forth as follows </dd>
+ <dd> <tt>: &gt;search&nbsp;&nbsp; &gt;r get-order 1+ r&gt; swap
+set-order ;</tt> </dd>
+ <dt> <a name="searchfrom"></a><tt>search&gt;&nbsp;&nbsp; ( -- wid )</tt> </dt>
+ <dd> Pop <tt>wid</tt> off the search order (can be coded in ANS Forth
+as&nbsp;<tt>: search&gt;&nbsp; get-order nip 1- set-order ;</tt> ) </dd>
+ <dt> <a name="ficlsetcurrent"></a><tt>ficl-set-current&nbsp;&nbsp; (
+wid -- old-wid )</tt> </dt>
+ <dd> Set wid as compile wordlist, leaving the previous compile
+wordlist on the stack </dd>
+ <dt> <a name="ficlvocabulary"></a><tt>ficl-vocabulary&nbsp;&nbsp; (
+nBins "name" -- )</tt> </dt>
+ <dd> Creates a <tt>ficl-wordlist</tt> with the specified number of
+hash table bins, binds it to the name, and associates the semantics of <tt>vocabulary</tt>
+with it (replaces the top wid in the search order list with
+its own wid when executed) </dd>
+ <dt> <a name="ficlwordlist"></a><tt>ficl-wordlist&nbsp;&nbsp; ( nBins
+-- wid )</tt> </dt>
+ <dd> Creates a wordlist with the specified number of hash table bins,
+and leaves the address of the wordlist on the stack. A <tt>ficl-wordlist</tt>
+behaves exactly as a regular wordlist, but it may search
+faster depending on the number of bins chosen and the number of words it
+contains at search time. As implemented in ficl, a wordlist is single
+threaded by default. <tt> ficl-named-wordlist</tt> takes a name for the
+wordlist and creates a word that pushes the <tt>wid</tt>. This is by
+contrast to <tt>VOCABULARY</tt>, which also has a name, but replaces
+the top of the search order with its <tt>wid</tt>. </dd>
+ <dt> <a name="ficlforgetwid"></a><tt>forget-wid&nbsp;&nbsp; ( wid -- )</tt> </dt>
+ <dd> Iterates through the specified wordlist and unlinks all
+definitions whose xt addresses are greater than or equal to the value of <tt>HERE</tt>,
+the dictionary fill pointer.&nbsp; </dd>
+ <dt> <a name="ficlhide"></a><tt>hide&nbsp;&nbsp; ( -- current-wid-was
+)</tt> </dt>
+ <dd> Push the <tt>hidden</tt> wordlist onto the search order, and set
+it as the current compile wordlist (unsing <tt>ficl-set-current</tt>).
+Leaves the previous compile wordlist ID. I use this word to
+hide implementation factor words that have low reuse potential so that
+they don't clutter the default wordlist. To undo the effect of hide,
+execute&nbsp; <b><tt>previous set-current</tt></b> </dd>
+ <dt> <a name="ficlhidden"></a><tt>hidden&nbsp;&nbsp; ( -- wid )</tt> </dt>
+ <dd> Wordlist for storing implementation factors of ficl provided
+words. To see what's in there, try:&nbsp; <b><tt>hide words previous
+set-current</tt></b> </dd>
+ <dt> <a name="wid-get-name"></a><tt>wid-get-name&nbsp;&nbsp; ( wid --
+c-addr u )</tt> </dt>
+ <dd> Ficl wordlists (2.05 and later) have a name property that can be
+assigned. This is used by <tt>ORDER</tt> to list the names of wordlists
+in the search order.&nbsp; </dd>
+ <dt> <a name="wid-set-name"></a><tt>wid-set-name&nbsp;&nbsp; ( c-addr
+wid -- )</tt> </dt>
+ <dd> Ficl wordlists (2.05 and later) have a name property that can be
+assigned. This is used by <tt>ORDER</tt> to list the names of wordlists
+in the search order. The name is assumed to be a \0 terminated
+string (C style), which conveniently is how Ficl stores word
+names.&nbsp; See softwords/softcore.fr definition of <tt>brand-wordlist</tt>&nbsp;</dd>
+ <dt> <a name="wid-set-super"></a><tt>wid-set-super&nbsp;&nbsp; ( wid
+-- )</tt> </dt>
+ <dd> Ficl wordlists have a parent wordlist pointer that is not
+specified in standard Forth. Ficl initializes this pointer to NULL
+whenever it creates a wordlist, so it ordinarily has no effect.
+This word sets the parent pointer to the wordlist specified on the top
+of the stack. Ficl's implementation of <tt>SEARCH-WORDLIST</tt> will
+chain backward through the parent link of the wordlist when
+searching. This simplifies Ficl's object model in that the search order
+does not need to reflect an object's class hierarchy when searching for
+a method. It is possible to implement Ficl object syntax in
+strict ANS Forth, but method finders need to manipulate the search order
+explicitly. </dd>
+</dl>
+<h3> <a name="exuser"></a>User variables </h3>
+<dl>
+ <dt> <tt>user&nbsp;&nbsp; ( -- ) name</tt> </dt>
+ <dd> Create a user variable with the given name. User variables are
+virtual machine local. Each VM allocates a fixed amount of storage for
+them. You can change the maximum number of user variables
+allowed by defining FICL_USER_CELLS on your compiiler's command line.
+Default is 16 user cells. User variables behave like <tt>VARIABLE</tt>s
+in all other respects (you use @ and ! on them, for example).
+Example: </dd>
+ <dd>
+ <dl>
+ <dd> <tt>user current-class</tt> </dd>
+ <dd> <tt>0 current-class !</tt> </dd>
+ </dl>
+ </dd>
+</dl>
+<h3> <a name="exmisc"></a>Miscellaneous </h3>
+<dl>
+ <dt> <tt>-roll&nbsp;&nbsp; ( xu xu-1 ... x0 u -- x0 xu-1 ... x1
+)&nbsp;</tt> </dt>
+ <dd> Rotate u+1 items on top of the stack after removing u. Rotation
+is in the opposite sense to <tt>ROLL</tt> </dd>
+</dl>
+<dl>
+ <dt> <a name="minusrot"></a><tt>-rot&nbsp;&nbsp; ( a b c -- c a b )</tt> </dt>
+ <dd> Rotate the top three stack entries, moving the top of stack to
+third place. I like to think of this as <tt>1<sup>1</sup>/<sub>2</sub>swap</tt>
+because it's good for tucking a single cell value behind a
+cell-pair (like an object).&nbsp; </dd>
+</dl>
+<dl>
+ <dt> <tt>.env&nbsp;&nbsp; ( -- )</tt> </dt>
+ <dd> List all environment variables of the system </dd>
+ <dt> <tt>.hash&nbsp;&nbsp; ( -- )</tt> </dt>
+ <dd> List hash table performance statistics of the wordlist that's
+first in the search order </dd>
+ <dt> <tt>.ver&nbsp;&nbsp; ( -- )</tt> </dt>
+ <dd> Display ficl version ID </dd>
+ <dt> <tt>&gt;name&nbsp;&nbsp; ( xt -- c-addr u )</tt> </dt>
+ <dd> Convert a word's execution token into the address and length of
+its name </dd>
+ <dt> <tt>body&gt;&nbsp;&nbsp; ( a-addr -- xt )</tt> </dt>
+ <dd> Reverses the effect of <tt>CORE</tt> word <tt>&gt;body</tt>
+(converts a parameter field address to an execution token) </dd>
+ <dt> <tt>compile-only</tt> </dt>
+ <dd> Mark the most recently defined word as being executable only
+while in compile state. Many <tt>immediate</tt> words have this
+property. </dd>
+ <dt> <tt>empty&nbsp;&nbsp; ( -- )</tt>&nbsp; </dt>
+ <dd> Empty the parameter stack </dd>
+ <dt> <tt>endif</tt> </dt>
+ <dd> Synonym for <tt>THEN</tt> </dd>
+ <dt> <a name="last-word"></a><tt>last-word&nbsp;&nbsp; ( -- xt )</tt> </dt>
+ <dd> Pushes the xt address of the most recently defined word. This
+applies to colon definitions, constants, variables, and words that use <tt>create</tt>.
+You can print the name of the most recently defined word
+with&nbsp; </dd>
+ <dd> <b><tt>last-word &gt;name type</tt>&nbsp;</b> </dd>
+ <dt> <tt>parse-word&nbsp;&nbsp; ( &lt;spaces&gt;name -- c-addr u )</tt> </dt>
+ <dd> Skip leading spaces and parse name delimited by a space. c-addr
+is the address within the input buffer and u is the length of the
+selected string. If the parse area is empty, the resulting
+string has a zero length. (From the Standard) </dd>
+ <dt> <a name="qfetch"></a><tt>q@&nbsp;&nbsp; ( addr -- x )</tt> </dt>
+ <dd> Fetch a 32 bit quantity from the specified address </dd>
+ <dt> <a name="qbang"></a><tt>q!&nbsp;&nbsp; ( x addr -- )</tt> </dt>
+ <dd> Store a 32 bit quantity to the specified address&nbsp; </dd>
+ <dt> <tt>w@&nbsp;&nbsp; ( addr -- x )</tt> </dt>
+ <dd> Fetch a 16 bit quantity from the specified address </dd>
+ <dt> <tt>w!&nbsp;&nbsp; ( x addr -- )</tt> </dt>
+ <dd> Store a 16 bit quantity to the specified address (the low 16 bits
+of the given value) </dd>
+ <dt> <a name="xdot"></a><tt>x.&nbsp;&nbsp; ( x -- )</tt> </dt>
+ <dd> Pop and display the value in hex format, regardless of the
+current value of <tt>BASE</tt> </dd>
+</dl>
+<h3> <a name="exficlwin"></a>Extra words defined in testmain.c (Win32
+and POSIX versions) </h3>
+<dl>
+ <dt> <tt>break&nbsp;&nbsp; ( -- )</tt> </dt>
+ <dd> Does nothing - just a handy place to set a debugger breakpoint </dd>
+ <dt> <tt>cd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (
+"directory-name&lt;newline&gt;" -- )</tt> </dt>
+ <dd> Executes the Win32 chdir() function, changing the program's
+logged directory. </dd>
+ <dt> <a name="clock"></a><tt>clock&nbsp;&nbsp; ( -- now )</tt> </dt>
+ <dd> Wrapper for the ANSI C clock() function. Returns the number of
+clock ticks elapsed since process start. </dd>
+ <dt> <a name="clockspersec"></a><tt>clocks/sec&nbsp;&nbsp; ( --
+clocks_per_sec )</tt> </dt>
+ <dd> Pushes the number of ticks in a second as returned by <tt>clock</tt> </dd>
+ <dt> <a name="ficlload"></a><tt>load&nbsp;&nbsp;&nbsp; (
+"filename&lt;newline&gt;" -- )</tt> </dt>
+ <dd> Opens the Forth source file specified and loads it one line at a
+time, like <tt>INCLUDED (FILE)</tt> </dd>
+ <dt> <tt>pwd&nbsp;&nbsp;&nbsp;&nbsp; ( -- )</tt> </dt>
+ <dd> Prints the current working directory as set by <tt>cd</tt> </dd>
+ <dt> <tt>system&nbsp; ( "command&lt;newline&gt;" -- )</tt> </dt>
+ <dd> Issues a command to a shell; implemented with the Win32 system()
+call. </dd>
+ <dt> <tt>spewhash&nbsp;&nbsp; ( "filename&lt;newline&gt;" -- )</tt> </dt>
+ <dd> Dumps all threads of the current compilation wordlist to the
+specified text file. This was useful when I thought there might be some
+point in attempting to optimize the hash function. I no longer
+harbor those illusions. </dd>
+</dl>
+<h3> Words defined in FiclWin only </h3>
+<dl>
+ <dt> <tt>!oreg&nbsp;&nbsp; ( c -- )</tt> </dt>
+ <dd> Set the value of the simulated LED register as specified (0..255)
+ </dd>
+ <dt> <tt>@ireg&nbsp;&nbsp; ( -- c )</tt> </dt>
+ <dd> Gets the value of the simulated switch block (0..255) </dd>
+ <dt> <tt>!dac&nbsp;&nbsp;&nbsp; ( c -- )</tt> </dt>
+ <dd> Sets the value of the bargraph control as specified. Valid values
+range from 0..255 </dd>
+ <dt> <tt>@adc&nbsp;&nbsp;&nbsp; ( -- c )</tt> </dt>
+ <dd> Fetches the current position of the slider control. Range is
+0..255 </dd>
+ <dt> <tt>status"&nbsp;&nbsp; ( "ccc&lt;quote&gt;" -- )</tt> </dt>
+ <dd> Set the mainframe window's status line to the text specified, up
+to the first trailing quote character. </dd>
+ <dt> <a name="ficlms"></a><tt><a
+ href="http://www.taygeta.com/forth/dpans10.htm#10.6.2.1905">ms</a>&nbsp;&nbsp;
+( u -- )</tt> </dt>
+ <dd> Causes the running virtual machine to sleep() for the number of
+milliseconds specified by the top-of-stack value. </dd>
+</dl>
+<hr>
+<h2> <a name="ansinfo"></a>ANS Required Information </h2>
+<b>ANS Forth System</b><br>
+<b>Providing names from the Core Extensions word set&nbsp;</b><br>
+<b>Providing the Exception word set</b><br>
+<b>Providing names from the Exception Extensions word set</b><br>
+<b>Providing the Locals word set&nbsp;</b><br>
+<b>Providing the Locals Extensions word set&nbsp;</b><br>
+<b>Providing the Memory Allocation word set</b><br>
+<b>Providing the Programming-Tools word set</b><br>
+<b>Providing names from the Programming-Tools Extensions word set</b><br>
+<b>Providing the Search-Order word set</b><br>
+<b>Providing the Search-Order Extensions word set</b>
+<h3> Implementation-defined Options </h3>
+The implementation-defined items in the following list represent
+characteristics and choices left to the discretion of the implementor,
+provided that the requirements of the Standard are met. A system
+shall document the values for, or behaviors of, each item.&nbsp;
+<ul>
+ <li> <b>aligned address requirements (3.1.3.3 Addresses);</b>&nbsp; </li>
+ <li> <br>
+ <font color="#000000">System dependent. You can change the default
+address alignment by defining FICL_ALIGN on your compiler's command
+line. The default value is set to 2 in sysdep.h. This causes
+dictionary entries and <tt>ALIGN</tt> and <tt>ALIGNED</tt> to align on 4
+byte boundaries. To align on <b>2<sup>n</sup></b> byte boundaries, set
+FICL_ALIGN to <b>n</b>.&nbsp;</font> </li>
+ <li> <b>behavior of 6.1.1320 EMIT for non-graphic characters</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Depends on target system, C runtime library,
+and your implementation of ficlTextOut().</font> </li>
+ <li> <b>character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">None implemented in the versions supplied in
+words.c. Because ficlExec() is supplied a text buffer externally, it's
+up to your system to define how that buffer will be obtained.</font> </li>
+ <li> <b>character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750
+KEY)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Depends on target system and implementation
+of ficlTextOut()</font> </li>
+ <li> <b>character-aligned address requirements (3.1.3.3 Addresses)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Ficl characters are one byte each. There are
+no alignment requirements.</font> </li>
+ <li> <b>character-set-extensions matching characteristics (3.4.2
+Finding definition n<font color="#000000">ames)</font></b><font
+ color="#000000">;&nbsp;</font> </li>
+ <li> <br>
+ <font color="#000000">No special processing is performed on
+characters beyond case-folding. Therefore, extended characters will not
+match their unaccented counterparts.</font> </li>
+ <li> <b>conditions under which control characters match a space
+delimiter (3.4.1.1 Delimiters)</b>;<font color="#ff6666">&nbsp;</font> </li>
+ <li> <br>
+ <font color="#000000">Ficl uses the Standard C function isspace()
+to distinguish space characters. The rest is up to your library vendor.</font> </li>
+ <li> <b>format of the control-flow stack (3.2.3.2 Control-flow stack)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Uses the data stack</font> </li>
+ <li> <b>conversion of digits larger than thirty-five (3.2.1.2 Digit
+conversion)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">The maximum supported value of <tt>BASE</tt>
+is 36. Ficl will assertion fail in function ltoa of vm.c if the base is
+found to be larger than 36 or smaller than 2. There will be no
+effect if NDEBUG is defined</font>, however, other than possibly
+unexpected behavior.&nbsp; </li>
+ <li> <b>display after input terminates in 6.1.0695 ACCEPT and
+6.2.1390 EXPECT</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Target system dependent</font> </li>
+ <li> <b>exception abort sequence (as in 6.1.0680 ABORT")</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Does <tt>ABORT</tt></font> </li>
+ <li> <b>input line terminator (3.2.4.1 User input device)</b>;<font
+ color="#ff0000">&nbsp;</font> </li>
+ <li> <br>
+ <font color="#000000">Target system dependent (implementation of
+outer loop that calls ficlExec)</font> </li>
+ <li> <b>maximum size of a counted string, in characters (3.1.3.4
+Counted strings, 6.1.2450 WORD)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">255</font> </li>
+ <li> <b>maximum size of a parsed string (3.4.1 Parsing)</b>;&nbsp; </li>
+ <li> <br>
+Limited by available memory and the maximum unsigned value that can fit
+in a CELL (2<sup>32</sup>-1).&nbsp; </li>
+ <li> <b>maximum size of a definition name, in characters (3.3.1.2
+Definition names)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl stores the first 31 characters of a
+definition name.</font> </li>
+ <li> <b>maximum string length for 6.1.1345 ENVIRONMENT?, in characters</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Same as maximum definition name length</font> </li>
+ <li> <b>method of selecting 3.2.4.1 User input device</b>;&nbsp; </li>
+ <li> <br>
+None supported. This is up to the target system&nbsp; </li>
+ <li> <b>method of selecting 3.2.4.2 User output device</b>;&nbsp; </li>
+ <li> <br>
+None supported. This is up to the target system&nbsp; </li>
+ <li> <b>methods of dictionary compilation (3.3 The Forth dictionary)</b>;&nbsp;</li>
+ <li> <b>number of bits in one address unit (3.1.3.3 Addresses)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Target system dependent. Ficl generally
+supports processors that can address 8 bit quantities, but there is no
+dependency that I'm aware of.</font> </li>
+ <li> <b>number representation and arithmetic (3.2.1.1 Internal number
+representation)</b>;&nbsp; </li>
+ <li> <br>
+System dependent. Ficl represents a CELL internally as a union that can
+hold INT32 (a signed 32 bit scalar value), UNS32 (32 bits unsigned), and
+an untyped pointer. No specific byte ordering is
+assumed.&nbsp; </li>
+ <li> <b>ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types,
+3.1.4 Cell-pair types)</b>;&nbsp; </li>
+ <li> <br>
+Assuming a 32 bit implementation, range for signed single-cell values
+is -2<sup>31</sup>..2<sup>31</sup>-1. Range for unsigned single cell
+values is 0..2<sup>32</sup>-1. Range for signed double-cell
+values is -2<sup>63</sup>..2<sup>63</sup>-1. Range for unsigned single
+cell values is 0..2<sup>64</sup>-1.&nbsp; </li>
+ <li> <b>read-only data-space regions (3.3.3 Data space)</b>; </li>
+ <li> <br>
+None&nbsp; </li>
+ <li> <b>size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient
+regions)</b>;&nbsp; </li>
+ <li> <br>
+Default is 255. Depends on the setting of nPAD in ficl.h.&nbsp; </li>
+ <li> <b>size of one cell in address units (3.1.3 Single-cell types)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">System dependent, generally four.</font> </li>
+ <li> <b>size of one character in address units (3.1.2 Character types)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">System dependent, generally one.</font> </li>
+ <li> <b>size of the keyboard terminal input buffer (3.3.3.5 Input
+buffers)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">This buffer is supplied by the host program.
+Ficl imposes no practical limit.</font> </li>
+ <li> <b>size of the pictured numeric output string buffer (3.3.3.6
+Other transient regions)</b>;&nbsp; </li>
+ <li> <br>
+Default is 255 characters. Depends on the setting of nPAD in
+ficl.h.&nbsp; </li>
+ <li> <b>size of the scratch area whose address is returned by
+6.2.2000 PAD (3.3.3.6 Other transient regions)</b>;&nbsp; </li>
+ <li> <br>
+Not presently supported&nbsp; </li>
+ <li> <b>system case-sensitivity characteristics (3.4.2 Finding
+definition names)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl is not case sensitive</font> </li>
+ <li> <b>system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">"ok&gt;"</font> </li>
+ <li> <b>type of division rounding (3.2.2.1 Integer division, 6.1.0100
+*/, 6.1.0110 */MOD, 6.1.0230 /, 6.1.0240 /MOD, 6.1.1890 MOD)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Symmetric</font> </li>
+ <li> <b>values of 6.1.2250 STATE when true</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">One (no others)</font> </li>
+ <li> <b>values returned after arithmetic overflow (3.2.2.2 Other
+integer operations)</b>;&nbsp; </li>
+ <li> <br>
+System dependent. Ficl makes no special checks for overflow.&nbsp; </li>
+ <li> <b>whether the current definition can be found after 6.1.1250
+DOES&gt; (6.1.0450 :)</b>.&nbsp; </li>
+ <li> <br>
+ <font color="#000000">No. Definitions are unsmudged after ; only,
+and only then if no control structure matching problems have been
+detected.</font> </li>
+</ul>
+<h3> Ambiguous Conditions </h3>
+A system shall document the system action taken upon each of the
+general or specific ambiguous conditions identified in this Standard.
+See 3.4.4 Possible actions on an ambiguous condition.&nbsp;
+<p> The following general ambiguous conditions could occur because of a
+combination of factors:&nbsp; </p>
+<ul>
+ <li> <b>a name is neither a valid definition name nor a valid number
+during text interpretation (3.4 The Forth text interpreter)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl does <tt>ABORT</tt> and prints the name
+followed by " not found".</font> </li>
+ <li> <b>a definition name exceeded the maximum length allowed
+(3.3.1.2 Definition names)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl stores the first 31 characters of the
+definition name, and uses all characters of the name in computing its
+hash code. The actual length of the name, up to 255
+characters, is stored in the definition's length field.</font> </li>
+ <li> <b>addressing a region not listed in 3.3.3 Data Space</b>;&nbsp;
+ </li>
+ <li> <br>
+ <font color="#000000">No problem: all addresses in ficl are
+absolute. You can reach any 32 bit address in Ficl's address space.</font> </li>
+ <li> <b>argument type incompatible with specified input parameter,
+e.g., passing a flag to a word expecting an n (3.1 Data types)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Ficl makes no check for argument type
+compatibility. Effects of a mismatch vary widely depending on the
+specific problem and operands.</font> </li>
+ <li> <b>attempting to obtain the execution token, (e.g., with
+6.1.0070 ', 6.1.1550 FIND, etc.) of a definition with undefined
+interpretation semantics</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl returns a valid token, but the result of
+executing that token while interpreting may be undesirable.</font> </li>
+ <li> <b>dividing by zero (6.1.0100 */, 6.1.0110 */MOD, 6.1.0230 /,
+6.1.0240 /MOD, 6.1.1561 FM/MOD, 6.1.1890 MOD, 6.1.2214 SM/REM, 6.1.2370
+UM/MOD, 8.6.1.1820 M*/)</b>; </li>
+ <li> <br>
+ <font color="#000000">Results are target procesor dependent.
+Generally, Ficl makes no check for divide-by-zero. The target processor
+will probably throw an exception.</font> </li>
+ <li> <b>insufficient data-stack space or return-stack space (stack
+overflow)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">With FICL_ROBUST (sysdep.h) set &gt;= 2, most
+parameter stack operations are checked for underflow and overflow. Ficl
+does not check the return stack.</font> </li>
+ <li> <b>insufficient space for loop-control parameters</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">No check - Evil results.</font> </li>
+ <li> <b>insufficient space in the dictionary</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl generates an error message if the
+dictionary is too full to create a definition header. It checks <tt>ALLOT</tt>
+as well, but it is possible to make an unchecked allocation
+request that overflows the dictionary.</font> </li>
+ <li> <b>interpreting a word with undefined interpretation semantics</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Ficl protects all ANS Forth words with
+undefined interpretation semantics from being executed while in
+interpret state. It is possible to defeat this protection using
+' (tick) and <tt>EXECUTE</tt>, though.</font> </li>
+ <li> <b>modifying the contents of the input buffer or a string
+literal (3.3.3.4 Text-literal regions, 3.3.3.5 Input buffers)</b>;&nbsp;</li>
+ <li> <br>
+ <font color="#000000">Varies depending on the nature of the buffer.
+The input buffer is supplied by ficl's host function, and may reside in
+read-only memory. If so, writing the input buffer can ganerate
+an exception. String literals are stored in the dictionary, and are
+writable.</font> </li>
+ <li> <b>overflow of a pictured numeric output string</b>; </li>
+ <li> <br>
+In the unlikely event you are able to construct a pictured numeric
+string of more than 255 characters, the system will be corrupted
+unpredictably. The buffer area that holds pictured numeric
+output is at the end of the virtual machine. Whatever is mapped after
+the offending VM in memory will be trashed, along with the heap
+structures that contain it.&nbsp; </li>
+ <li> <b>parsed string overflow</b>; </li>
+ <li> <br>
+Ficl does not copy parsed strings unless asked to. Ordinarily, a string
+parsed from the input buffer during normal interpretation is left
+in-place, so there is no possibility of overflow. If you ask
+to parse a string into the dictionary, as in <tt>SLITERAL</tt>, you
+need to have enough room for the string, otherwise bad things may
+happen. This is not usually a problem.&nbsp; </li>
+ <li> <b>producing a result out of range, e.g., multiplication (using
+*) results in a value too big to be represented by a single-cell integer
+(6.1.0090 *, 6.1.0100 */, 6.1.0110 */MOD, 6.1.0570
+&gt;NUMBER, 6.1.1561 FM/MOD, 6.1.2214 SM/REM, 6.1.2370 UM/MOD, 6.2.0970
+CONVERT, 8.6.1.1820 M*/)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Value will be truncated</font> </li>
+ <li> <b>reading from an empty data stack or return stack (stack
+underflow)</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Most stack underflows are detected and
+prevented if FICL_ROBUST (sysdep.h) is set to 2 or greater. Otherwise,
+the stack pointer and size are likely to be trashed.</font> </li>
+ <li> <b>unexpected end of input buffer, resulting in an attempt to
+use a zero-length string as a name</b>;&nbsp; </li>
+ <li> <br>
+ <font color="#000000">Ficl returns for a new input buffer until a
+non-empty one is supplied.</font> </li>
+</ul>
+The following specific ambiguous conditions are noted in the glossary
+entries of the relevant words:&nbsp;
+<ul>
+ <li> <b>&gt;IN greater than size of input buffer (3.4.1 Parsing)</b> </li>
+ <li> <br>
+Bad Things occur - unpredictable bacause the input buffer is supplied
+by the host program's outer loop.&nbsp; </li>
+ <li> <b>6.1.2120 RECURSE appears after 6.1.1250 DOES&gt;</b> </li>
+ <li> <br>
+It finds the address of the definition before <tt>DOES&gt;</tt> </li>
+ <li> <b>argument input source different than current input source for
+6.2.2148 RESTORE-INPUT</b> </li>
+ <li> <br>
+Not implemented&nbsp; </li>
+ <li> <b>data space containing definitions is de-allocated (3.3.3.2
+Contiguous regions)</b> </li>
+ <li> <br>
+This is OK until the cells are overwritten with something else. The
+dictionary maintains a hash table, and the table must be updated in
+order to de-allocate words without corruption.&nbsp; </li>
+ <li> <b>data space read/write with incorrect alignment (3.3.3.1
+Address alignment)</b> </li>
+ <li> <br>
+Target processor dependent. Consequences include: none (Intel), address
+error exception (68K).&nbsp; </li>
+ <li> <b>data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860
+C,)</b> </li>
+ <li> <br>
+See above on data space read/write alignment&nbsp; </li>
+ <li> <b>less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)</b> </li>
+ <li> <br>
+Ficl detects a stack underflow and reports it, executing <tt>ABORT,</tt>
+as long as FICL_ROBUST is two or larger.&nbsp; </li>
+ <li> <b>loop-control parameters not available ( 6.1.0140 +LOOP,
+6.1.1680 I, 6.1.1730 J, 6.1.1760 LEAVE, 6.1.1800 LOOP, 6.1.2380 UNLOOP)</b> </li>
+ <li> <br>
+Loop initiation words are responsible for checking the stack and
+guaranteeing that the control parameters are pushed. Any underflows will
+be detected early if FICL_ROBUST is set to two or greater.
+Note however that Ficl only checks for return stack underflows at the
+end of each line of text.&nbsp; </li>
+ <li> <b>most recent definition does not have a name (6.1.1710
+IMMEDIATE)</b> </li>
+ <li> <br>
+No problem.&nbsp; </li>
+ <li> <b>name not defined by 6.2.2405 VALUE used by 6.2.2295 TO</b> </li>
+ <li> <br>
+Ficl's version of <tt>TO</tt> works correctly with <tt>VALUE</tt>s, <tt>CONSTANT</tt>s
+and <tt>VARIABLE</tt>s.&nbsp; </li>
+ <li> <b>name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['],
+6.2.2530 [COMPILE])</b> </li>
+ <li> <br>
+Ficl prints an error message and does <tt>ABORT</tt> </li>
+ <li> <b>parameters are not of the same type (6.1.1240 DO, 6.2.0620
+?DO, 6.2.2440 WITHIN)</b> </li>
+ <li> <br>
+No check. Results vary depending on the specific problem.&nbsp; </li>
+ <li> <b>6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO</b> </li>
+ <li> <br>
+The word is postponed correctly.&nbsp; </li>
+ <li> <b>string longer than a counted string returned by 6.1.2450 WORD</b> </li>
+ <li> <br>
+Ficl stores the first FICL_STRING_MAX-1 chars in the destination
+buffer. (The extra character is the trailing space required by the
+standard. Yuck.)&nbsp; </li>
+ <li> <b>u greater than or equal to the number of bits in a cell
+(6.1.1805 LSHIFT, 6.1.2162 RSHIFT)</b> </li>
+ <li> <br>
+Depends on target process or and C runtime library implementations of
+the &lt;&lt; and &gt;&gt; operators on unsigned values. For I386, the
+processor appears to shift modulo the number of bits in a
+cell.&nbsp; </li>
+ <li> <b>word not defined via 6.1.1000 CREATE (6.1.0550 &gt;BODY,
+6.1.1250 DOES&gt;)</b> </li>
+ <li> <br>
+ <b>words improperly used outside 6.1.0490 &lt;# and 6.1.0040 #&gt;
+(6.1.0030 #, 6.1.0050 #S, 6.1.1670 HOLD, 6.1.2210 SIGN)</b><br>
+Don't. <tt>CREATE</tt> reserves a field in words it builds for <tt>DOES&gt;</tt>to
+fill in. If you use <tt>DOES&gt;</tt> on a word not made by <tt>CREATE</tt>,
+it will overwrite the first cell of its parameter area.
+That's probably not what you want. Likewise, pictured numeric words
+assume that there is a string under construction in the VM's scratch
+buffer. If that's not the case, results may be unpleasant. </li>
+</ul>
+<h3> Locals Implementation-defined options </h3>
+<ul>
+ <li> <b>maximum number of locals in a definition (13.3.3 Processing
+locals, 13.6.2.1795 LOCALS|)</b> </li>
+ <li> <br>
+Default is 16. Change by redefining FICL_MAX_LOCALS, defined in
+sysdep.h </li>
+</ul>
+<h3> Locals Ambiguous conditions </h3>
+<ul>
+ <li> <b>executing a named local while in interpretation state
+(13.6.1.0086 (LOCAL))</b> </li>
+ <li> <br>
+Locals can be found in interpretation state while in the context of a
+definition under construction. Under these circumstances, locals behave
+correctly. Locals are not visible at all outside the scope of
+a definition.&nbsp; </li>
+ <li> <b>name not defined by VALUE or LOCAL (13.6.1.2295 TO)</b> </li>
+ <li> <br>
+See the CORE ambiguous conditions, above (no change) </li>
+</ul>
+<h3> Programming Tools Implementation-defined options </h3>
+<ul>
+ <li> <b>source and format of display by 15.6.1.2194 SEE</b> </li>
+ <li> <br>
+SEE de-compiles definitions from the dictionary. Because Ficl words are
+threaded by their header addresses, it is very straightforward to print
+the name and other characteristics of words in a definition.
+Primitives are so noted. Colon definitions are decompiled, but branch
+target labels are not reconstructed. Literals and string literals are so
+noted, and their contents displayed. </li>
+</ul>
+<h3> Search Order Implementation-defined options </h3>
+<ul>
+ <li> <b>maximum number of word lists in the search order (16.3.3
+Finding definition names, 16.6.1.2197 SET-ORDER)</b>&nbsp; </li>
+ <li> <br>
+Defaults to 16. Can be changed by redefining FICL_DEFAULT_VOCS,
+declared in sysdep.h&nbsp; </li>
+ <li> <b>minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY)</b>&nbsp;</li>
+ <li> <br>
+Equivalent to <tt>FORTH-WORDLIST 1 SET-ORDER</tt> </li>
+</ul>
+<h3> Search Order Ambiguous conditions </h3>
+<ul>
+ <li> <b>changing the compilation word list (16.3.3 Finding definition
+names)</b> </li>
+ <li> <br>
+Ficl stores a link to the current definition independently of the
+compile wordlist while it is being defined, and links it into the
+compile wordlist only after the definition completes
+successfully. Changing the compile wordlist mid-definition will cause
+the definition to link into the <i>new</i> compile wordlist.&nbsp; </li>
+ <li> <b>search order empty (16.6.2.2037 PREVIOUS)</b> </li>
+ <li> <br>
+Ficl prints an error message if the search order underflows, and resets
+the order to its default state.&nbsp; </li>
+ <li> <b>too many word lists in search order (16.6.2.0715 ALSO)</b> </li>
+ <li> <br>
+Ficl prints an error message if the search order overflows, and resets
+the order to its default state. </li>
+</ul>
+</div>
+</body>
+</html>
diff --git a/doc/ficl1.ico b/doc/ficl1.ico
deleted file mode 100644
index 403bd6f56cb9..000000000000
--- a/doc/ficl1.ico
+++ /dev/null
Binary files differ
diff --git a/doc/ficl_debug.html b/doc/ficl_debug.html
deleted file mode 100644
index 647b7b27a8d0..000000000000
--- a/doc/ficl_debug.html
+++ /dev/null
@@ -1,111 +0,0 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
- <meta name="Author" content="john sadler">
- <title>Ficl Debugger</title>
-</head>
-<body>
-<link REL="SHORTCUT ICON" href="ficl.ico">
-<h1><b>Ficl Debugger</b></h1>
-
-<script language="javascript" src="ficlheader.js"></script>
-
-<table COLS=1 WIDTH="650" >
-<tr>
-<td>
-<p>Ficl release 2.05 includes a simple step debugger for colon definitions
-and does> words. If you use it and can suggest improvements (or better
-yet if you write some), please let me know.</p>
-<h2>Using the debugger</h2>
-To debug a word, set up the stack with any parameters the word requires,
-then type:
-
-<b><pre>debug &lt;your word here></pre></b>
-
-<p>If the word is unnamed, or all you have is an xt, you can instead use:</p>
-<b><code>debug-xt ( xt -- )</code></b>
-<p>The debugger invokes <tt>see</tt> on the word, printing a crude source
-listing, then stops at the first instruction of the definition. There are
-four (case insensitive) commands you can use from here onwards:</p>
-
-<dl>
-<dt>I (step in)</dt>
-<dd>If the next instruction is a colon defintion or does> word, steps into
-that word's code. If the word is a primitive, simply executes the word.</dd>
-
-<dt>O (step over)</dt>
-<dd>Executes the next instruction in its entirety</dd>
-
-<dt>G (go)</dt>
-<dd>Run the word to completion and exit the debugger</dd>
-
-<dt>L (list)</dt>
-<dd>Lists the source code of the word presently being stepped</dd>
-
-<dt>Q (quit)</dt>
-<dd>Abort the word and exit the debugger, clearing the stack</dd>
-
-<dt>X (eXecute)</dt>
-<dd>Interpret the remainder of the line as ficl words for their side effects.
-Any errors will abort the debug session and reset the VM. Usage example:
-<pre>
-x drop 3 \ fix argument on stack
-</pre>
-</dd>
-
-<dt>Anything else</dt>
-<dd>Prints a list of available debugger commands</dd>
-</dl>
-
-<h2>The on-step event</h2>
-<p>If there is a defined word named <code>on-step</code> when the debugger starts, that
-word will be executed before every step. As a guideline, this word should
-have no side effects. Its intended use is to display the stacks and any other
-VM state you're interested in, but you
-may have some better ideas. If so, please let me know. The default on-step is:<p>
-<b><code>: on-step ." S: " .s cr ;</code></b>
-
-<h3>Other useful words for debugging and on-step</h3>
-<dl>
-<dt><code>r.s ( -- )</code></dt>
-<dd>Prints a represention of the state of the return stack non-destructively. You have to have
-a good understanding of the return stack side-effects of control words to make sense of it,
-but it does give an accurate representation of what's there. Example: <code>DO .. LOOP</code>s stack
-three parameters on the return stack: the loop count and limit, and the <code>LEAVE</code> target
-address.</dd>
-<dt><code>.s ( -- )</code></dt>
-<dd>Prints the parameter stack non-destructively</dd>
-<dt><code>f.s ( -- )</code></dt>
-<dd>Prints the float stack non-destructively (only available if FICL_WANT_FLOAT is enabled)</dd>
-</dl>
-<h2>Debugger internals</h2>
-<p>
-The debugger words are mostly located in source file <tt>tools.c</tt>. There are
-supporting words (<code>debug</code> and <code>on-step</code>) in softcore.fr as well.
-There are two main words that make the debugger go: debug-xt and step-break.
-Debug-xt takes the xt of a word to debug (as returned by <tt>'</tt>, for example)
-checks to see if it is debuggable (not a primitive), sets a breakpoint at its
-first instruction, and runs <code>see</code> on it. To set a breakpoint,
-<code>debug-xt</code>
-replaces the instruction at the breakpoint with the xt of <code>step-break</code>, and
-stores the original instruction and its address in a static breakpoint
-record. To clear the breakpoint, <code>step-break</code> simply replaces the original
-instruction and adjusts the target virtual machine's instruction pointer
-to run it.
-</p>
-<p><code>Step-break</code> is responsible for processing debugger commands and setting
-breakpoints at subsequent instructions.</p>
-<h3>To Do</h3>
-<bl>
-<li>The debugger needs to exit automatically when it encounters the end of the word
-it was asked to debug. Perhaps this could be a special kind of breakpoint?
-</li>
-<li>Add user-set breakpoints</li>
-<li>Add "step out" command</li>
-</bl>
-</td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/doc/ficl_guts.htm b/doc/ficl_guts.htm
deleted file mode 100644
index ba982c454a3f..000000000000
--- a/doc/ficl_guts.htm
+++ /dev/null
@@ -1,69 +0,0 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <meta name="Author" content="john sadler">
- <meta name="Description" content="the coolest embedded scripting language ever">
- <title>Ficl - Internals</title>
-</head>
-<body>
-<link REL="SHORTCUT ICON" href="ficl.ico">
-<h1><b>Ficl Internal Structures</b></h1>
-
-<script language="javascript" src="ficlheader.js"></script>
-
-<h2>Contents</h2>
-
-<h2>Major Data Structures</h2>
-<p>
-A running memory image of Ficl consists of one or more FICL_SYSTEMs,
-each of which owns exactly one dictionary (FICL_DICT),
-and one or more virtual machines (FICL_VM). Each VM owns two stacks
-(FICL_STACK) - one for parameters (the parameter stack)
-and one for return addresses (the return stack).
-Ficl is a permissive, untyped language by nature,
-so its fundamental unit of storage is a CELL: a chunk of memory
-large enough to hold an address or a scalar type.
-</p>
-<h3>FICL_SYSTEM</h3>
-The system structure associates one or more virtual machines with a dictionary. All FICL_SYSTEMS
-include a link pointer that is used to keep track of every allocated system so that memory
-can be freed by ficlTermSystem. Each system contains a list of virtual machines associated with
-it. Each system has at least one virtual machine. In a typical implementation, there is one virtual
-machine per native OS thread, and there may be several VMs sharing a single FICL_SYSTEM, or one
-FICL_SYSTEM per VM if the implementation needs to support multiple user sessions in a robust way.
-
-A FICL_SYSTEM also includes a special dictionary for local variable support (if enabled
-by FICL_WANT_LOCALS) and another for environment variable support. Environment variables
-describe the configuration of the system in conformance with American National Standard Forth
-(ANS Forth).
-<h3>FICL_DICT</h3>
-A dictionary manages a fixed-size block of contiguous memory. It serves two roles: to keep track
-of allocated memory, and to collect symbol tables called wordlists. Each dictionary contains at
-least one wordlist. The dictionary organized memory (perhaps this is too kind) as an array of
-CELLs that grows from low memory to high memory within fixed limits determined by the
-FICL_DEFAULT_DICT parameter in sysdep.h.
-
-A wordlist is the controlling structure of a Ficl symbol table. Each wordlist is a hash table
-containing pointers to FICL_WORDs. Each FICL_WORD associates a pointer to code with one or more
-CELLs of the dictionay. Each word usually has a name as well, but this is not required. It is
-possible to create anonymous words using :NONAME.
-
-Each word's code pointer determines that word's runtime behavior, and by implication the purpose
-of its payload data. Some words interpret their payload as a list of Ficl words, and execute them.
-This is how new behaviors of the language are defined. Other words view their payload field as
-a location in which one or more CELLs can be stored (VARIABLEs, for example). At runtime, such
-words push the address of their payload area onto the parameter stack.
-<h3>FICL_VM</h3>
-The virtual machine collects state related to execution of Ficl words. Each VM includes
-registers used by the inner interpreter, some state variables (AKA user variables) such as
-the current numeric base, and a jmpbuf.
-A VM has a pointer to the FICL_SYSTEM of which it is a part. It also has a pointer to an incoming
-text string that it is interpreting. There are VM methods that excute a word given its address
-(xt), and ones that interpret a text string.
-<h3>FICL_STACK</h3>
-Each VM owns a parameter stack, a return stack, and if float support is enabled, a float parameter
-stack. Parameters, return addresses, and floats are all CELL sized, and values may be
-moved back and forth among stacks using various Ficl words for that purpose.
-</BODY>
-</HTML>
diff --git a/doc/ficl_loc.html b/doc/ficl_loc.html
deleted file mode 100644
index 6e00e74b9ee3..000000000000
--- a/doc/ficl_loc.html
+++ /dev/null
@@ -1,161 +0,0 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <meta name="Author" content="john sadler">
- <meta name="Description" content="the coolest embedded scripting language ever">
- <meta name="GENERATOR" content="Mozilla/4.73 [en] (Win98; U) [Netscape]">
- <title>ficl Local Variables</title>
-</head>
-<body>
-
-<h1>
-<b>Local Variables in Ficl</b></h1>
-
-
-<script language="javascript" src="ficlheader.js"></script>
-
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h2>
-<a NAME="locals"></a>Local Variables</h2>
-Named locally scoped variables came late to Forth. Purists feel that experienced
-Forth programmers can (and should) write supportable code using only anonymous
-stack variables and good factoring, but they complain that novices use
-global variables too much. Local variables cost little in terms of code
-size and execution speed, and are very convenient for OO programming, where
-stack effects are more complex. I use them a lot (maybe I'm a weenie).&nbsp;
-<br><a href="http://www.taygeta.com/forth/dpans13.htm">Please refer to
-the Standard</a> for more information on local variables.
-<h2>
-<a NAME="jhlocal"></a>Johns-Hopkins local variables</h2>
-ANS Forth does not specify a complete and satisfying local variable facility.
-Instead it defines a foundation upon which to build one. Ficl comes with
-an adaptation of the Johns-Hopkins local variable syntax developed by John
-Hayes et al. This is my preferred form, and I've extended it to make <a href="ficl_oop.html">OOP</a>
-a bit simpler. Local variables can only be declared inside a definition,
-and are only visible in that definition. Here's the syntax of a JH local
-variable declaration:
-<blockquote><tt><b>{ </b>&lt;initialized-locals><b> | </b>&lt;cleared-locals><b>
--- </b>&lt;ignored><b> }</b></tt></blockquote>
-The declaration is designed to look like a stack comment, but it uses curly
-braces instead of parens. The &lt;initialized-locals> names get their initial
-values from the stack when the word executes. The &lt;cleared-locals> names
-are (you guessed it) set to zero when the word executes, and any characters
-between -- and } are treated as a comment. The | and -- sections are optional,
-but they must appear in the order shown if they appear at all.&nbsp;
-<br><b>Double cell locals </b>(AKA 2locals): ordinarily, each local represents
-one cell. Local variable names prefixed with the characters "2:" in the declaration
-are double-cell locals. The prefix is not part of the local variable's name, only
-part of the declaration.
-They behave the same as single cell locals in all
-other respects. I use 2locals quite a bit in Ficl's OO classes, because
-objects in Ficl require two cells on the stack. You can modify the
-value of a double cell local with <tt><a href="http://www.taygeta.com/forth/dpans13.htm#13.6.1.2295">TO</a></tt>
-the same as you would a single cell local.
-<br>Following are some examples to illustrate usage (they are not intended
-to be good code otherwise). Try these out in FiclWin to get a feeling for
-how they work. Also see <code>softwords/string.fr</code> for an example of use of locals
-in OO code.
-<blockquote><b><tt>: local-demo&nbsp; { a b | c -- }</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; ." a = " a . cr</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; ." b = " b . cr</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; ." c = " c . cr ;</tt></b>
-<br><b><tt>1 2 local-demo&nbsp; ( you should see 1 2 0 )</tt></b>
-<p><b><tt>: my2dup&nbsp; { 2:x }&nbsp;&nbsp; x x ;&nbsp; ( uses a 2local
-)</tt></b>
-<br><b><tt>1 2 my2dup .s&nbsp;</tt></b>
-<br><b><tt>.( you should see 1 2 1 2 on the stack ) cr empty</tt></b>
-<p><b><tt>: my2swap&nbsp;&nbsp; { 2:x 2:y -- y x }&nbsp;&nbsp; y x ;&nbsp;
-( note use of 2locals )</tt></b>
-<br><b><tt>1 2 3 4 my2swap .s</tt></b>
-<br><b><tt>.( you should see 3 4 1 2 on the stack ) cr empty</tt></b>
-<p><b><tt>: totally-lame-swap&nbsp; { x y | temp -- y x }</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; y to temp</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; x to y</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; temp to x</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; x y ;</tt></b></blockquote>
-The last definition introduces the use of <tt>TO</tt> applied to local
-variables. <tt>TO</tt> knows whether it's operating on a <tt>LOCAL</tt>,
-a <tt>2LOCAL</tt>, or a <tt>VALUE</tt>, and does the right thing accordingly.&nbsp;
-<br>&nbsp;
-<h2>Other local variable syntaxes (deprecated)</h2>
-There are other syntaxes in use for local variables. You get the same compiled
-code regardless of which style of local declaration you choose, but the
-Johns-Hopkins syntax is more readable, more flexible, and supports <tt>2LOCAL</tt>s
-- if you agree, then skip this section.&nbsp;
-<p>Ficl includes support for <tt>LOCALS</tt> and <tt>LOCALS EXT</tt> words
-(all three of them!). I've implemented both of the local variable syntaxes
-suggested in DPANS Appendix A.13. Examples: (By the way, Ficl implements
-<tt>-ROT</tt>
-as <tt>: -rot&nbsp;&nbsp; 2 -roll ;</tt> )
-<blockquote><b><tt>\ Using LOCALS| from LOCALS EXT</tt></b>
-<br><b><tt>: -rot&nbsp;&nbsp; ( a b c -- c a b )</tt></b>
-<br><b><tt>&nbsp;&nbsp; locals| c b a |</tt></b>
-<br><b><tt>&nbsp; c a b&nbsp;</tt></b>
-<br><b><tt>;</tt></b></blockquote>
-
-<ul><b><tt>\ Using LOCAL END-LOCAL</tt></b>
-<br><b><tt>: -rot&nbsp;&nbsp; ( a b c -- c a b )</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; local c</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; local b</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; local a</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; end-locals</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; c a b</tt></b>
-<br><b><tt>;</tt></b></ul>
-
-<h2>
-Build Controls</h2>
-Local variable support is optional because it adds a small amount of overhead
-to the outer interpreter. You can disable it by setting FICL_WANT_LOCALS
-to 0 in sysdep.h. Beware: <a href="ficl_oop.html">Ficl's OOP</a> code makes
-heavy use of local variables, so if you disable locals, you're going to
-lose other capabilities too. Local variables can make Forth code quite
-a bit easier to read, so I'd encourage you to experiment with them.&nbsp;
-<p>The default maximum number of local variables is 16. It's controlled
-by FICL_MAX_LOCALS in sysdep.h.&nbsp;
-<h2>
-Release notes for local variables</h2>
-<p>Ficl 2.05 adds 2LOCALS using the "2:" prefix</p>
-<p>Ficl 2.02 includes by default an implementation of the Johns Hopkins local
-syntax (as best I can determine it from examples on the web). This syntax
-lets you declare local variables that look very much like a stack comment.
-Variables in the declaration appear in the "correct" order for a stack
-comment. Everything after the -- is treated as a comment. In addition,
-you can insert a | before the -- to declare one or more zero-initialized
-locals. Example:&nbsp;</p>
-<blockquote><b><tt>:tuck0&nbsp;&nbsp; { a b c | d -- 0 a b c }</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; d a b c ;</tt></b></blockquote>
-The | and -- delimiters can appear at most once, and must appear in the
-order shown in the example to work correctly. The local declaration ends
-at the first occurrence of }. The declaration must all be on one line as
-presently implemented.&nbsp;
-<p><b>Deprecated</b>: Ficl 2.01 added yet another local syntax that models
-a stack comment. This one is not compiled in the release, but you can add
-it by editing softwords/softcore.bat to include the file ficllocal.fr.
-In this case, parameters are re-ordered so that the rightmost initialized
-param comes from the top of the stack. The syntax is:&nbsp;
-<blockquote><b><tt>{{ &lt;initialized params> -- &lt;cleared params> }}</tt></b></blockquote>
-You can omit either the initialized or the cleared parameters. Parameters
-after the double dash are set to zero initially. Those to the left are
-initialized from the stack at execution time. Examples (lame ones, admittedly):&nbsp;
-<br>&nbsp;
-<blockquote>
-<pre><b><tt>: -rot&nbsp;&nbsp; ( a b c -- c a b )
-&nbsp;&nbsp;&nbsp; {{ a b c }}</tt></b>&nbsp;
-&nbsp;&nbsp;&nbsp; <b><tt>c a b&nbsp;</tt></b>&nbsp;
-<b><tt>;</tt></b>&nbsp;
-
-<b><tt>: tuck0&nbsp; ( a b c -- 0 a b c )</tt></b>&nbsp;
-<b><tt>&nbsp;&nbsp;&nbsp; {{ a b c -- d }}</tt></b>&nbsp;
-<b><tt>&nbsp;&nbsp;&nbsp; d a b c&nbsp;</tt></b>&nbsp;
-<b><tt>;&nbsp;</tt></b></pre>
-</blockquote>
-</td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/doc/ficl_logo.jpg b/doc/ficl_logo.jpg
deleted file mode 100644
index c3332dbf65a1..000000000000
--- a/doc/ficl_logo.jpg
+++ /dev/null
Binary files differ
diff --git a/doc/ficl_oop.html b/doc/ficl_oop.html
deleted file mode 100644
index 438eaebdcfb2..000000000000
--- a/doc/ficl_oop.html
+++ /dev/null
@@ -1,1387 +0,0 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <meta name="Author" content="john sadler">
- <meta name="Description" content="object oriented programming in the coolest embedded scripting language ever">
- <meta name="GENERATOR" content="Mozilla/4.73 [en] (Win98; U) [Netscape]">
- <title>Ficl Object Oriented Programming</title>
-</head>
-<body>
-
-<h1>
-<b>Object Oriented Programming in ficl</b></h1>
-
-
-<script language="javascript" src="ficlheader.js"></script>
-
-
-<h2>
-Contents</h2>
-
-<ul>
-<li>
-<a href="#objects">Object Oriented Programming in ficl</a></li>
-
-<li>
-<a href="#ootutorial">Ficl OO Tutorial</a></li>
-
-<li>
-<a href="#cstring">Ficl String Classes</a></li>
-
-<li>
-<a href="ficl.html#oopgloss">OOP glossary</a></li>
-
-<li>
-<a href="#glossinstance">Instance variable glossary</a></li>
-
-<li>
-<a href="#glossclass">Class methods glossary</a></li>
-
-<li>
-<a href="#objectgloss"><tt>OBJECT</tt> base class methods glossary</a></li>
-
-<li>
-<a href="#stockclasses">Supplied Classes</a></li>
-</ul>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h2>
-<a NAME="objects"></a>Object Oriented Programming in ficl</h2>
-
-<h3>
-Review of <a href="http://whatis.techtarget.com/definition/0,289893,sid9_gci212681,00.html">OO</a> ideas</h3>
-Click <a href="oo_in_c.html#review">here</a> for a short review of OO ideas,
-terms, and implementations in other languages, or <a href="http://www.soft-design.com/softinfo/objects.html">here</a>
-for an introduction to the terms and principles of Object Oriented Programming
-<h3>
-Design goals of Ficl OO syntax</h3>
-Ficl's object extensions provide the traditional OO benefits of associating
-data with the code that manipulates it, and reuse through single inheritance.
-Ficl also has some unusual capabilities that support interoperation with
-systems written in C.&nbsp;
-<ul>
-<li>
-Ficl objects are normally late bound for safety (late binding guarantees
-that the appropriate method will always be invoked for a particular object).
-Early binding is also available, provided you know the object's class at
-compile-time.</li>
-
-<li>
-Ficl OOP supports single inheritance, aggregation, and arrays of objects.</li>
-
-<li>
-Classes have independent name spaces for their methods: methods are only
-visible in the context of a class or object. Methods can be overridden
-or added in subclasses; there is no fixed limit on the number of methods
-of a class or subclass.</li>
-
-<li>
-Ficl OOP syntax is regular and unified over classes and objects. In ficl,
-all classes are objects. Class methods include the ability to subclass
-and instantiate.</li>
-
-<li>
-Ficl can adapt legacy data structures with object wrappers. You can model
-a structure in a Ficl class, and create an instance that refers to an address
-in memory that holds an instance of the structure. The <i>ref object</i>
-can then manipulate the structure directly. This lets you wrap data structures
-written and instantiated in C.</li>
-</ul>
-
-<h3>
-Acknowledgements</h3>
-Ficl is not the first Forth to include Object Oriented extensions. Ficl's
-OO syntax owes a debt to the work of John Hayes and Dick Pountain, among
-others. OO Ficl is different from other OO Forths in a few ways, though
-(some things never change). First, unlike several implementations, the
-syntax is documented (<a href="#ootutorial">below</a>) beyond the source
-code. In Ficl's spirit of working with C code, the OO syntax provides means
-to adapt existing data structures. I've tried to make Ficl's OO model simple
-and safe by unifying classes and objects, providing late binding by default,
-and separating namespaces so that methods and regular Forth words are not
-easily confused.&nbsp;</td>
-</tr>
-</table>
-
-<br>&nbsp;
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h3>
-Ficl Object Model</h3>
-All classes in Ficl are derived from the common base class <tt><a href="#objectgloss">OBJECT,</a></tt>
-as shown in the <a href="#figure1">figure</a> below. All classes are instances
-of <tt><a href="#glossclass">METACLASS</a></tt>. This means that classes
-are objects, too. <tt>METACLASS</tt> implements the methods for messages
-sent to classes. Class methods create instances and subclasses, and give
-information about the class. Each class is represented by a data stucture
-of three elements:&nbsp;
-<ul>
-<li>
-The address (named <tt>.CLASS</tt> ) of a parent class, or zero if it's
-a base class (only <tt>OBJECT</tt> and <tt>METACLASS</tt> have this property)</li>
-
-<li>
-The size (named <tt>.SIZE</tt> ) in address units of an instance of the
-class</li>
-
-<li>
-A wordlist ID (named <tt>.WID</tt> ) for the methods of the class</li>
-</ul>
-In the figure below, <tt>METACLASS</tt> and <tt>OBJECT</tt> are real system-supplied
-classes. The others are contrived to illustrate the relationships among
-derived classes, instances, and the two system base classes. The dashed
-line with an arrow at the end indicates that the object/class at the arrow
-end is an instance of the class at the other end. The vertical line with
-a triangle denotes inheritance.&nbsp;
-<p>Note for the curious: <tt>METACLASS</tt> behaves like a class - it responds
-to class messages and has the same properties as any other class. If you
-want to twist your brain in knots, you can think of <tt>METACLASS</tt>
-as an instance of itself.&nbsp;
-<br>&nbsp;</td>
-</tr>
-</table>
-
-<p><a NAME="figure1"></a><img SRC="ficl_oop.jpg" VSPACE=10 height=442 width=652>
-<br>&nbsp;
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h2>
-<a NAME="ootutorial"></a>Ficl OO Syntax Tutorial</h2>
-
-<h3>
-Introduction</h3>
-It's helpful to have some familiarity with Forth and the customary Forth
-stack notation to understand this tutorial. To get started, take a look
-at this <a href="http://www.taygeta.com/forth_intro/stackflo.html">web-based
-Forth tutorial</a>. If you're comfortable with both OO and Forth, you can
-<a href="#ootutorial-finally">jump
-ahead</a>.
-<p>A Ficl <a href="oo_in_c.html#object-def">object</a> associates a <a href="oo_in_c.html#class-def">class</a>
-with an <a href="oo_in_c.html#instance-def">instance</a> (the storage for
-one set of instance variables). This is done explicitly on Ficl's stack,
-in that any Ficl object is represented by a cell pair:&nbsp;
-<blockquote><b><tt>( instance-addr class-addr )</tt></b></blockquote>
-The instance-addr is the address of the object's storage, and the class-addr
-is the address of its class. Whenever a named Ficl object executes (eg.
-when you type its name and press enter at the Ficl prompt), it leaves this
-"signature". All methods by convention expect a class and instance on the
-stack when they execute, too. In many other OO languages, including C++,
-instances contain information about their classes (a <a href="http://www.mvps.org/vbvision/vtable.htm">vtable</a>
-pointer, for example). By making this pairing explicit rather than implicit,
-Ficl can be OO about chunks of data that don't realize that they are objects,
-without sacrificing any robustness for native objects. That means that
-you can use Ficl to write object wrappers for data structures created in
-C or assembly language, as long as you can determine how they're laid out
-in memory.&nbsp;
-<br>Whenever&nbsp; you create an object in Ficl, you specify its class.
-After that, the object always pushes its class and the address of its <a href="http://www.aware.com/Glossary/main.htm#P">payload
-</a>(instance
-variable space) when invoked by name.&nbsp;
-<p>Classes are special kinds of objects that store the methods of their
-instances, the size of an instance's payload, and a parent class pointer.
-Classes themselves are instances of a special base class called <tt>METACLASS</tt>,
-and all classes inherit from class <tt>OBJECT</tt>. This is confusing at
-first, but it means that Ficl has a very simple syntax for constructing
-and using objects. Class methods include subclassing (<tt>SUB</tt>), creating
-initialized and uninitialized instances (<tt>NEW</tt> and <tt>INSTANCE</tt>),
-and creating reference instances (<tt>REF</tt>), described later. Classes
-also have methods for disassembling their methods (<tt>SEE</tt>), identifying
-themselves (<tt>ID</tt>), and listing their pedigree (<tt>PEDIGREE</tt>).
-All objects inherit (from <tt>OBJECT</tt>) methods for initializing instances
-and arrays of instances, for performing array operations, and for getting
-information about themselves.&nbsp;
-<h3>
-Methods and messages</h3>
-Methods are the functions that objects execute in response to messages.
-A message is a request to an object for a behavior that the object supports.
-When it receives a message, the target object looks up a method that performs
-the behavior for its class, and executes it. Any specific message may be
-bound to different methods in different objects, according to class. This
-separation of messages and methods allows objects to behave <a href="http://www.whatis.com/polymorp.htm">polymorphically</a>.
-(In Ficl, methods are words defined in the context of a class, and messages
-are the names of those words.) Ficl classes associate messages with methods
-for their instances (a fancy way of saying that each class owns a wordlist).
-Ficl provides a late-binding operator <b><tt>--></tt></b> that sends messages
-to objects at run-time, and an early-binding operator <b><tt>=></tt></b>
-that compiles a specific class's method. These operators are the only supported
-way to invoke methods. Regular Forth words are not visible to the method-binding
-operators,&nbsp; so there's no chance of confusing a message with a regular
-word of the same name.&nbsp;</td>
-</tr>
-</table>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h3>
-<a NAME="ootutorial-finally"></a>Tutorial (finally!)</h3>
-This is a tutorial. It works best if you follow along by pasting the examples
-into ficlWin, the Win32 version of Ficl included with the release sources
-(or some other build that includes the OO part of softcore.c). If you're
-not familiar with Forth, please see one of these <a href="#links">references</a>.
-Ficl's OOP words are in vocabulary <tt>OOP</tt>. To put <tt>OOP</tt> in
-the search order and make it the compilation wordlist, type:&nbsp;
-<pre>
-ONLY ( reset to default search order )
-ALSO OOP DEFINITIONS
-</pre>
-(<b>Note for beginners</b>: to see the effect of the commands above, type
-<tt>ORDER</tt>
-after each line. You can repeat the sequence above if you like.)
-<p>To start, we'll work with the two base classes <tt>OBJECT</tt> and <tt>METACLASS</tt>.
-Try this:&nbsp;
-<pre>
-metaclass --> methods
-</pre>
-The line above contains three words. The first is the name of a class,
-so it pushes its signature on the stack. Since all classes are instances
-of <tt>METACLASS</tt>, <tt>METACLASS</tt> behaves as if it is an instance
-of itself (this is the only class with this property). It pushes the same
-address twice: once for the class and once for the payload, since they
-are the same. The next word finds a method in the context of a class and
-executes it. In this case, the name of the method is <tt>methods</tt>.
-Its job is to list all the methods that a class knows. What you get when
-you execute this line is a list of all the class methods Ficl provides.&nbsp;
-<pre>
-object --> sub c-led
-</pre>
-Causes base-class <tt>OBJECT</tt> to derive from itself a new class called
-c-led. Now we'll add some instance variables and methods to the new class...&nbsp;
-<br><b>Note</b>: I like to prefix the names of classes with "c-", and the
-names of member variables with a dot, but this is just a convention. If
-you don't like it, you can pick your own.
-<pre>
-c-byte obj: .state
-: init { 2:this -- }
- this --> super --> init
- ." initializing an instance of "
- this --> class --> id type cr ;
-: on { led# 2:this -- }
- this --> .state --> get
- 1 led# lshift or dup !oreg
- this --> .state --> set ;
-: off { led# 2:this -- }
- this --> .state --> get
- 1 led# lshift invert and dup !oreg
- this --> .state --> set&nbsp; ;
-end-class
-</pre>
-The first line adds an instance variable called <tt>.state</tt> to the
-class. This particular instance variable is an object - it will be an instance
-of c-byte, one of ficl's stock classes (the source for which can be found
-in the distribution in sorftowrds/classes.fr).&nbsp;
-<br>Next we've defined a method called <tt>init</tt>. This line also declares
-a <a href="ficl_loc.html">local variable</a> called <b><tt>this</tt></b>
-(the 2 in front tells Ficl that this is a double-cell local). All methods
-by convention expect the address of the class and instance on top of the
-stack when called.&nbsp; The next three lines define <tt>init</tt>'s behavior.
-It first calls its superclass's version of <tt>init</tt> (which in this
-case is <tt>object => init</tt> - this default implementation clears all
-instance variables). The rest displays some text and causes the instance
-to print its class name (<tt>this --> class --> id</tt>).
-<br>The <b><tt>init</tt></b> method is special for Ficl objects: whenever
-you create an initialized instance using <b><tt>new</tt></b> or <b><tt>new-array</tt></b>,
-Ficl calls the class's <tt>init</tt> method for you on that instance. The
-default <tt>init</tt> method supplied by <tt>object</tt> clears the instance,
-so we didn't really need to override it in this case (see the source code
-in ficl/softwords/oo.fr).&nbsp;
-<br>The <tt>ON</tt> and <tt>OFF</tt> methods defined above hide the details
-of turning LEDs on and off. The interface to FiclWin's simulated hardware
-is handled by <tt>!OREG</tt>. The class keeps the LED state in a shadow
-variable (<tt>.STATE</tt>) so that <tt>ON</tt> and <tt>OFF</tt> can work
-in terms of LED number rather than a bitmask.
-<p>Now make an instance of the new class:&nbsp;
-<pre>
-c-led --> new led
-</pre>
-And try a few things...&nbsp;
-<pre>
-led --> methods
-led --> pedigree
-1 led --> on
-1 led --> off
-</pre>
-Or you could type this with the same effect:&nbsp;
-<pre>
-led 2dup --> methods --> pedigree
-</pre>
-Notice (from the output of <tt>methods</tt>) that we've overridden the
-init method supplied by object, and added two more methods for the member
-variables. If you type <tt>WORDS</tt>, you'll see that these methods are
-not visible outside the context of the class that contains them. The method
-finder <b><tt>--></tt></b> uses the class to look up methods. You can use
-this word in a definition, as we did in <tt>init</tt>, and it performs
-late binding, meaning that the mapping from message (method name) to method
-(the code) is deferred until run-time. To see this, you can decompile the
-init method like this:&nbsp;
-<pre>
-c-led --> see init
-</pre>
-or
-<pre>
-led --> class --> see init
-</pre>
-
-<h3>
-Early binding</h3>
-Ficl also provides early binding if you ask for it. Early binding is not
-as safe as late binding, but it produces code that is more compact and
-efficient because it compiles method addresses rather then their names.
-In the preferred uses of early binding, the class is assumed to be the
-one you're defining. This kind of early binding can only be used inside
-a class definition. Early bound methods still expect to find a class and
-instance cell-pair on top of the stack when they run.
-<br>Here's an example that illustrates a potential problem:
-<pre>
-object --> sub c1
-: m1 { 2:this -- } ." c1's m1" cr ;
-: m2 { 2:this -- } ." Running " this my=> m1 ; ( early )
-: m3 { 2:this -- } ." Running " this --> m1 ( late )
-end-class
-c1 --> sub c2
-: m1 { 2:this -- } ." c2's m1" cr ;
-end-class
-c2 --> new i2
-i2 --> m1 ( runs the m1 defined in c2 )
-i2 --> m2 ( is this what you wanted? )
-i2 --> m3 { runs the overridden m1)
-</pre>
-Even though we overrode method m1 in class c2, the definition of m2 with
-early binding forced the use of m1 as defined in c1. If that's what you
-want, great, but more often you'll want the flexibility of overriding parent
-class behaviors appropriately.&nbsp;
-<ol>
-<li>
-<code>my=></code> binds early to a method in the class being defined,
-as in the example above.
-</li>
-<li>
-<code>my=[ ]</code> binds a sequence of methods in the current class.
-Useful when the class has object members. Lines like <code>this --> state
---> set</code> in the definition of c-led above can be replaced with
-<code>this my=[ state set ]</code> to get early binding.
-</li>
-<li>
-<code>=></code> (dangerous) pops a class off the stack and compiles
-the method in that class. Since you have to specify the class explicitly,
-there is a real danger that this will be out of sync with the class you
-really wanted. I recommend the <code>my=</code> operations.
-</li>
-</ol>
-Early binding using <code>=></code> is dangerous because it partially
-defeats the data-to-code matching mechanism object oriented languages were
-created to provide, but it does increase run-time speed by binding the
-method at compile time. In many cases, such as the <code>init</code> method,
-you can be reasonably certain of the class of thing you're working on.
-This is also true when invoking class methods, since all classes are instances
-of <code>metaclass</code>. Here's an example from the definition of <code>metaclass</code>
-in oo.fr (don't paste this into ficlWin - it's already there):
-<pre>
-: new \ ( class metaclass "name" -- )
- metaclass => instance --> init ;
-</pre>
-Try this...
-<pre>
-metaclass --> see new
-</pre>
-Decompiling the method with <code>SEE</code> shows the difference between the
-two strategies. The early bound method is compiled inline, while the late-binding
-operator compiles the method name and code to find and execute it in the
-context of whatever class is supplied on the stack at run-time.
-<br>Notice that the primitive early-binding operator <code>=></code> requires
-a class at compile time. For this reason, classes are <code>IMMEDIATE</code>,
-meaning that they push their signature at compile time or run time. I'd
-recommend that you avoid early binding until you're very comfortable with
-Forth, object-oriented programming, and Ficl's OOP syntax.
-<br>
-<h3>
-More About Instance Variables</h3>
-<i>Untyped</i> instance variable methods (created by <tt>cell: cells: char:</tt>
-and <tt>chars:</tt>) just push the address of the corresponding instance
-variable when invoked on an instance of the class. It's up to you to remember
-the size of the instance variable and manipulate it with the usual Forth
-words for fetching and storing.&nbsp;
-<p>As advertised earlier, Ficl provides ways to objectify existing data
-structures without changing them. Instead, you can create a Ficl class
-that models the structure, and instantiate a <b>ref </b>from this class,
-supplying the address of the structure. After that, the <i>ref instance</i>
-behaves as a Ficl object, but its instance variables take on the values
-in the existing structure. Example (from ficlclass.fr):&nbsp;
-<blockquote><b><tt>object subclass c-wordlist</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; c-wordlist ref: .parent</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; c-ptr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj:
-.name</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; c-cell&nbsp;&nbsp;&nbsp;&nbsp; obj: .size</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; c-word&nbsp;&nbsp;&nbsp;&nbsp; ref: .hash</tt></b>
-<p><b><tt>&nbsp;&nbsp;&nbsp; : ?</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2drop ." ficl wordlist
-" cr ;</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; : push&nbsp; drop&nbsp; >search ;</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; : pop&nbsp;&nbsp; 2drop previous ;</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; : set-current&nbsp;&nbsp; drop set-current
-;</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; : words&nbsp;&nbsp; --> push&nbsp; words
-previous ;</tt></b>
-<br><b><tt>end-class</tt></b></blockquote>
-In this case, <tt>c-wordlist</tt> describes Ficl's wordlist structure;
-named-wid creates a wordlist and binds it to a ref instance of <tt>c-wordlist</tt>.
-The fancy footwork with <tt>POSTPONE</tt> and early binding is required
-because classes are immediate. An equivalent way to define named-wid with
-late binding is:&nbsp;
-<blockquote><b><tt>: named-wid&nbsp;&nbsp; ( "name" -- )</tt></b>
-<br><b><tt>&nbsp;&nbsp;&nbsp; wordlist&nbsp; postpone c-wordlist&nbsp;
---> ref ;</tt></b></blockquote>
-To do the same thing at run-time (and call it my-wordlist):&nbsp;
-<blockquote><b><tt>wordlist&nbsp; c-wordlist --> ref&nbsp; my-wordlist</tt></b></blockquote>
-Now you can deal with the wordlist through the ref instance:&nbsp;
-<blockquote><b><tt>my-wordlist --> push</tt></b>
-<br><b><tt>my-wordlist --> set-current</tt></b>
-<br><b><tt>order</tt></b></blockquote>
-Ficl can also model linked lists and other structures that contain pointers
-to structures of the same or different types. The class constructor word
-<b><tt><a href="#exampleref:">ref:</a></tt></b>
-makes an aggregate reference to a particular class. See the <a href="#glossinstance">instance
-variable glossary</a> for an <a href="#exampleref:">example</a>.&nbsp;
-<p>Ficl can make arrays of instances, and aggregate arrays into class descripions.
-The <a href="#glossclass">class methods</a> <b><tt>array</tt></b> and <b><tt>new-array</tt></b>
-create uninitialized and initialized arrays, respectively, of a class.
-In order to initialize an array, the class must define (or inherit) a reasonable
-<b><tt>init</tt></b>
-method. <b><tt>New-array</tt></b> invokes it on each member of the array
-in sequence from lowest to highest. Array instances and array members use
-the object methods <b><tt>index</tt></b>, <b><tt>next</tt></b>, and <b><tt>prev</tt></b>
-to navigate. Aggregate a member array of objects using <b><tt><a href="#arraycolon">array:</a></tt></b>.
-The objects are not automatically initialized in this case - your class
-initializer has to call <b><tt>array-init</tt></b> explicitly if you want
-this behavior.&nbsp;
-<p>For further examples of OOP in Ficl, please see the source file ficl/softwords/ficlclass.fr.
-This file wraps several Ficl internal data structures in objects and gives
-use examples.&nbsp;</td>
-</tr>
-
-<tr>
-<td>
-<h2>
-<a NAME="cstring"></a>Ficl String classes</h2>
-c-string (ficl 2.04 and later) is a reasonably useful dynamic string class.
-Source code for the class is located in ficl/softwords/string.fr. Features:
-dynamic creation and resizing; deletion, char cout, concatenation, output,
-comparison; creation from quoted string constant (s").
-<p>Examples of use:
-<blockquote>
-<pre><b>c-string --> new homer
-s" In this house, " homer --> set
-s" we obey the laws of thermodynamics!" homer --> cat
-homer --> type</b></pre>
-</blockquote>
-</td>
-</tr>
-</table>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h2>
-<a NAME="oopgloss"></a>OOP Glossary</h2>
-Note: with the exception of the binding operators (the first two definitions
-here), all of the words in this section are internal factors that you don't
-need to worry about. These words provide method binding for all classes
-and instances. Also described are supporting words and execution factors.
-All are defined in softwords/oo.fr.&nbsp;
-<dl>
-<dt>
-<b><tt>-->&nbsp;&nbsp; ( instance class "method-name" -- xn )</tt></b></dt>
-
-<dd>
-Late binding: looks up and executes the given method in the context of
-the class on top of the stack.&nbsp;</dd>
-
-<dt>
-<b><tt>c->&nbsp;&nbsp; ( instance class "method-name" -- xn exc )</tt></b></dt>
-
-<dd>
-Late binding with <tt>CATCH</tt>: looks up and <tt>CATCH</tt>es the given
-method in the context of the class on top of the stack, pushes zero or
-exception code upon return.</dd>
-
-<dt>
-<b><tt>my=> comp: ( "method-name" -- )&nbsp; exec: ( inst class -- xn )</tt></b></dt>
-
-<dd>
-Early binding: compiles code to execute the method of the class being defined.
-Only visible and valid in the scope of a <tt>--> sub</tt> .. <tt>end-class</tt>
-class definition.</dd>
-
-<dt>
-<b><tt>my=[ comp: ( "obj1 obj2 .. method ]" -- ) exec:( inst class -- xn
-)</tt></b></dt>
-
-<dd>
-Early binding: compiles code to execute a chain of methods of the class
-being defined. Only visible and valid in the scope of a <tt>--> sub</tt>
-.. <tt>end-class</tt> class definition.</dd>
-
-<dt>
-<b><tt>=>&nbsp;&nbsp; comp: ( class meta "method-name" -- )&nbsp; exec:
-( inst class -- xn )</tt></b></dt>
-
-<dd>
-Early binding: compiles code to execute the method of the class specified
-at compile time.</dd>
-
-<dt>
-<b><tt>do-do-instance</tt></b></dt>
-
-<dd>
-When executed, causes the instance to push its ( instance class ) stack
-signature. Implementation factor of <b><tt>metaclass --> sub</tt></b>.
-Compiles <b><tt>.do-instance</tt></b> in the context of a class; <tt>.do-instance</tt>
-implements the <tt>does></tt> part of a named instance.&nbsp;</dd>
-
-<dt>
-<b><tt>exec-method&nbsp;&nbsp; ( instance class c-addr u -- xn )</tt></b></dt>
-
-<dd>
-Given the address and length of a message (method name) on the stack, finds
-the method in the context of the specified class and invokes it. Upon entry
-to the method, the instance and class are on top of the stack, as usual.
-If unable to find the method, prints an error message and aborts.</dd>
-
-<dt>
-<b><tt>find-method-xt&nbsp;&nbsp; ( class "method-name" -- class xt )</tt></b></dt>
-
-<dd>
-Attempts to map the message to a method in the specified class. If successful,
-leaves the class and the execution token of the method on the stack. Otherwise
-prints an error message and aborts.</dd>
-
-<dt>
-<b><tt>lookup-method&nbsp;&nbsp; ( class c-addr u -- class xt )</tt></b></dt>
-
-<dd>
-Given the address and length of a message (method name) on the stack, finds
-the method in the context of the specified class. If unable to find the
-method, prints an error message and aborts.</dd>
-
-<dt>
-<b><tt>parse-method&nbsp;&nbsp; comp: ( "method-name" -- )&nbsp; exec:
-( -- c-addr u )</tt></b></dt>
-
-<dd>
-Parse "name" from the input stream and compile code to push its length
-and address when the enclosing definition runs.</dd>
-</dl>
-</td>
-</tr>
-</table>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h3>
-<a NAME="glossinstance"></a>Instance Variable Glossary</h3>
-<b>Note</b>: these words are only visible when creating a subclass! To
-create a subclass, use the <tt>sub</tt> method on <tt>object</tt> or any
-class derived from it (<i>not</i> <tt>metaclass</tt>). Source code for
-Ficl OOP is in ficl/softwords/oo.fr.&nbsp;
-<br>Instance variable words do two things: they create methods that do
-an action appropriate for the type of instance variable they represent,
-and they reserve space in the class template for the instance variable.
-We'll use the term <i>instance variable</i> to refer both to the method
-that gives access to a particular field of an object, and to the field
-itself. Rather than give esentially the same example over and over, here's
-one example that shows several of the instance variable construction words
-in use:
-<blockquote><tt>object subclass c-example</tt>
-<br><tt>&nbsp;&nbsp; cell:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-.cell0</tt>
-<br><tt>&nbsp;&nbsp; c-4byte&nbsp;&nbsp; obj: .nCells</tt>
-<br><tt>&nbsp;4 c-4byte array: .quad</tt>
-<br><tt>&nbsp;&nbsp; char:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-.length</tt>
-<br><tt>79 chars:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .name</tt>
-<br><tt>end-class</tt>&nbsp;</blockquote>
-This class only defines instance variables, and it inherits some methods
-from <tt>object</tt>. Each untyped instance variable (.cell0, .length,
-.name) pushes its address when executed. Each object instance variable
-pushes the address and class of the aggregate object. Similar to C, an
-array instance variable leaves its base address (and its class) when executed.
-The word <tt>subclass</tt> is shorthand for "<tt>--> sub</tt>"&nbsp;
-<dl>
-<dt>
-<b><font face="Courier New"><font size=-1>cell:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-( offset "name" -- offset' )</font></font></b></dt>
-
-<dt>
-<b><font face="Courier New"><font size=-1>Execution:&nbsp; ( -- cell-addr
-)</font></font></b></dt>
-
-<dd>
-Create an untyped instance variable one cell wide. The instance variable
-leaves its payload's address when executed.&nbsp;</dd>
-
-<dt>
-<b><tt>cells:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( offset nCells "name"
--- offset' )</tt></b></dt>
-
-<dt>
-<b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Execution:&nbsp; ( -- cell-addr )</tt></b></dt>
-
-<dd>
-Create an untyped instance variable n cells wide.</dd>
-
-<dt>
-<b><tt>char:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( offset "name"
--- offset' )</tt></b></dt>
-
-<dt>
-<b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Execution:&nbsp; ( -- char-addr )</tt></b></dt>
-
-<dd>
-Create an untyped member variable one char wide</dd>
-
-<dt>
-<b><tt>chars:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( offset nChars "name"
--- offset' )</tt></b></dt>
-
-<dt>
-<b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Execution:&nbsp; ( -- char-addr )</tt></b></dt>
-
-<dd>
-Create an untyped member variable n chars wide.</dd>
-
-<dt>
-<b><tt>obj:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( offset class
-meta "name" -- offset' )</tt></b></dt>
-
-<dt>
-<b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Execution:&nbsp; ( -- instance class )</tt></b></dt>
-
-<dd>
-Aggregate an uninitialized instance of <b>class</b> as a member variable
-of the class under construction.</dd>
-
-<dt>
-<a NAME="arraycolon"></a><b><tt>array:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-( offset n class meta "name" -- offset' )</tt></b></dt>
-
-<dt>
-<b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Execution:&nbsp; ( -- instance class )</tt></b></dt>
-
-<dd>
-Aggregate an uninitialized array of instances of the class specified as
-a member variable of the class under construction.</dd>
-
-<dt>
-<a NAME="exampleref:"></a><b><tt>ref:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-( offset class meta "name" -- offset' )</tt></b></dt>
-
-<dt>
-<b><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
-Execution:&nbsp; ( -- ref-instance ref-class )</tt></b></dt>
-
-<dd>
-Aggregate a reference to a class instance. There is no way to set the value
-of an aggregated ref - it's meant as a way to manipulate existing data
-structures with a Ficl OO model. For example, if your system contains a
-linked list of 4 byte quantities, you can make a class that represents
-a list element like this:&nbsp;</dd>
-
-<dl>
-<dd>
-<tt>object subclass c-4list</tt></dd>
-
-<dd>
-<tt>c-4list ref: .link</tt></dd>
-
-<dd>
-<tt>c-4byte obj: .payload</tt></dd>
-
-<dd>
-<tt>end-class;</tt></dd>
-
-<dd>
-<tt>address-of-existing-list c-4list --> ref mylist</tt></dd>
-</dl>
-
-<dd>
-The last line binds the existing structure to an instance of the class
-we just created. The link method pushes the link value and the class c_4list,
-so that the link looks like an object to Ficl and like a struct to C (it
-doesn't carry any extra baggage for the object model - the Ficl methods
-alone take care of storing the class information).&nbsp;</dd>
-
-<dd>
-Note: Since a ref: aggregate can only support one class, it's good for
-modeling static structures, but not appropriate for polymorphism. If you
-want polymorphism, aggregate a c_ref (see classes.fr for source) into your
-class - it has methods to set and get an object.</dd>
-
-<dd>
-By the way, it is also possible to construct a pair of classes that contain
-aggregate pointers to each other. Here's an example:</dd>
-
-<dl>
-<dd>
-<tt>object subclass akbar</tt></dd>
-
-<dd>
-<tt>suspend-class&nbsp;&nbsp;&nbsp;&nbsp; \ put akbar on hold while we
-define jeff</tt></dd>
-
-<dd>
-<tt>object subclass jeff</tt></dd>
-
-<dd>
-<tt>&nbsp;&nbsp;&nbsp; akbar ref: .significant-other</tt></dd>
-
-<dd>
-<tt>&nbsp;&nbsp;&nbsp; ( your additional methods here )</tt></dd>
-
-<dd>
-<tt>end-class&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \ done with
-jeff</tt></dd>
-
-<dd>
-<tt>akbar --> resume-class&nbsp; \ resume defining akbar</tt></dd>
-
-<dd>
-<tt>&nbsp;&nbsp;&nbsp; jeff ref: .significant-other</tt></dd>
-
-<dd>
-<tt>&nbsp;&nbsp;&nbsp; ( your additional methods here )</tt></dd>
-
-<dl><tt>end-class&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \ done
-with akbar</tt></dl>
-</dl>
-</dl>
-</td>
-</tr>
-</table>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h3>
-<a NAME="glossclass"></a>Class Methods Glossary</h3>
-These words are methods of <tt>metaclass</tt>. They define the manipulations
-that can be performed on classes. Methods include various kinds of instantiation,
-programming tools, and access to member variables of classes. Source is
-in softwords/oo.fr.&nbsp;
-<dl>
-<dt>
-<b><tt>instance&nbsp;&nbsp;&nbsp;&nbsp; ( class metaclass "name" -- instance
-class )</tt></b>&nbsp;</dt>
-
-<dd>
-Create an uninitialized instance of the class, giving it the name specified.
-The method leaves the instance 's signature on the stack (handy if you
-want to initialize). Example:</dd>
-
-<dd>
-<tt>c_ref --> instance uninit-ref&nbsp; 2drop</tt></dd>
-
-<dt>
-<b><tt>new&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class
-metaclass "name" -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Create an initialized instance of class, giving it the name specified.
-This method calls init to perform initialization.&nbsp;</dd>
-
-<dt>
-<b><tt>array&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( nObj class metaclass
-"name" -- nObjs instance class )</tt></b>&nbsp;</dt>
-
-<dd>
-Create an array of nObj instances of the specified class. Instances are
-not initialized. Example:</dd>
-
-<dd>
-<tt>10 c_4byte --> array&nbsp; 40-raw-bytes&nbsp; 2drop drop</tt></dd>
-
-<dt>
-<b><tt>new-array&nbsp;&nbsp;&nbsp; ( nObj class metaclass "name" -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Creates an initialized array of nObj instances of the class. Same syntax
-as <tt>array</tt></dd>
-
-<dt>
-<a NAME="alloc"></a><b><tt>alloc&nbsp;&nbsp; ( class metaclass -- instance
-class )</tt></b></dt>
-
-<dd>
-Creates an anonymous instance of <b>class</b> from the heap (using a call
-to ficlMalloc() to get the memory). Leaves the payload and class addresses
-on the stack. Usage example:</dd>
-
-<dd>
-<tt>c-ref --> alloc&nbsp; 2constant instance-of-ref</tt></dd>
-
-<dd>
-Creates a double-cell constant that pushes the payload and class address
-of a heap instance of c-ref.</dd>
-
-<dt>
-<a NAME="allocarray"></a><b><tt>alloc-array&nbsp;&nbsp; ( nObj class metaclass
--- instance class )</tt></b></dt>
-
-<dd>
-Same as new-array, but creates anonymous instances from the heap using
-a call to ficlMalloc(). Each instance is initialized using the class's
-<tt>init</tt>
-method</dd>
-
-<dt>
-<a NAME="allot"></a><b><tt>allot&nbsp;&nbsp; ( class metaclass -- instance
-class )</tt></b></dt>
-
-<dd>
-Creates an anonymous instance of <b>class</b> from the dictionary. Leaves
-the payload and class addresses on the stack. Usage example:</dd>
-
-<dd>
-<tt>c-ref --> allot&nbsp; 2constant instance-of-ref</tt></dd>
-
-<dd>
-Creates a double-cell constant that pushes the payload and class address
-of a heap instance of c-ref.</dd>
-
-<dt>
-<a NAME="allotarray"></a><b><tt>allot-array&nbsp;&nbsp; ( nObj class metaclass
--- instance class )</tt></b></dt>
-
-<dd>
-Same as new-array, but creates anonymous instances from the dictionary.
-Each instance is initialized using the class's
-<tt>init</tt> method</dd>
-
-<dt>
-<b><tt>ref&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance-addr
-class metaclass "name" -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Make a ref instance of the class that points to the supplied instance address.
-No new instance space is allotted. Instead, the instance refers to the
-address supplied on the stack forever afterward. For wrapping existing
-structures.</dd>
-</dl>
-
-<dl>
-<dt>
-<b><tt>sub&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class
-metaclass -- old-wid addr[size] size )</tt></b></dt>
-
-<dd>
-Derive a subclass. You can add or override methods, and add instance variables.
-Alias: <tt>subclass</tt>. Examples:</dd>
-
-<dl>
-<dd>
-<tt>c_4byte --> sub c_special4byte</tt></dd>
-
-<dd>
-<tt>( your new methods and instance variables here )</tt></dd>
-
-<dd>
-<tt>end-class</tt></dd>
-
-<dd>
-or</dd>
-
-<dd>
-<tt>c_4byte subclass c_special4byte</tt></dd>
-
-<dd>
-<tt>( your new methods and instance variables here )</tt></dd>
-
-<dd>
-<tt>end-class</tt></dd>
-</dl>
-
-<dt>
-<b><tt>.size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class metaclass
--- instance-size )</tt></b>&nbsp;</dt>
-
-<dd>
-Returns address of the class's instance size field, in address units. This
-is a metaclass member variable.</dd>
-
-<dt>
-<b><tt>.super&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class metaclass --
-superclass )</tt></b>&nbsp;</dt>
-
-<dd>
-Returns address of the class's superclass field. This is a metaclass member
-variable.</dd>
-
-<dt>
-<b><tt>.wid&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class metaclass
--- wid )</tt></b>&nbsp;</dt>
-
-<dd>
-Returns the address of the class's wordlist ID field. This is a metaclass
-member variable.</dd>
-
-<dt>
-<b><tt>get-size</tt></b></dt>
-
-<dd>
-Returns the size of an instance of the class in address units. Imeplemented
-as</dd>
-
-<dd>
-<tt>: get-size&nbsp;&nbsp; metaclass => .size @ ;</tt></dd>
-
-<dt>
-<b><tt>get-wid</tt></b></dt>
-
-<dd>
-Returns the wordlist ID of the class. Implemented as&nbsp;</dd>
-
-<dd>
-<tt>: get-wid&nbsp;&nbsp; metaclass => .wid @ ;</tt></dd>
-
-<dt>
-<b><tt>get-super</tt></b></dt>
-
-<dd>
-Returns the class's superclass. Implemented as</dd>
-
-<dd>
-<tt>: get-super&nbsp;&nbsp; metaclass => .super @ ;</tt></dd>
-
-<dt>
-<b><tt>id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (
-class metaclass -- c-addr u )</tt></b>&nbsp;</dt>
-
-<dd>
-Returns the address and length of a string that names the class.</dd>
-
-<dt>
-<b><tt>methods&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class metaclass -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Lists methods of the class and all its superclasses</dd>
-
-<dt>
-<b><tt>offset-of&nbsp;&nbsp;&nbsp; ( class metaclass "name" -- offset )</tt></b></dt>
-
-<dd>
-Pushes the offset from the instance base address of the named member variable.
-If the name is not that of an instance variable method, you get garbage.
-There is presently no way to detect this error. Example:</dd>
-
-<dl>
-<dd>
-<tt>metaclass --> offset-of .wid</tt></dd>
-</dl>
-
-<dt>
-<b><tt>pedigree&nbsp;&nbsp;&nbsp;&nbsp; ( class metaclass -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Lists the pedigree of the class (inheritance trail)</dd>
-
-<dt>
-<b><tt>see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( class
-metaclass "name" -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Decompiles the specified method - obect version of <tt>SEE</tt>, from the
-<tt>TOOLS</tt>
-wordset.</dd>
-</dl>
-</td>
-</tr>
-</table>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h3>
-<a NAME="objectgloss"></a><tt>object</tt> base-class Methods Glossary</h3>
-These are methods that are defined for all instances by the base class
-<tt>object</tt>.
-The methods include default initialization, array manipulations, aliases
-of class methods, upcasting, and programming tools.&nbsp;
-<dl>
-<dt>
-<b><tt>init&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance
-class -- )</tt>&nbsp;</b></dt>
-
-<dd>
-Default initializer called automatically for all instances created with
-<tt>new</tt>
-or <tt>new-array</tt>. Zero-fills the instance. You do not normally need
-to invoke <tt>init</tt> explicitly.</dd>
-
-<dt>
-<b><tt>array-init&nbsp;&nbsp; ( nObj instance class -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Applies <tt>init</tt> to an array of objects created by <tt>new-array</tt>.
-Note that <tt>array:</tt> does not cause aggregate arrays to be initialized
-automatically. You do not normally need to invoke <tt>array-init</tt> explicitly.</dd>
-
-<dt>
-<a NAME="oofree"></a><b><tt>free&nbsp;&nbsp; ( instance class -- )</tt></b></dt>
-
-<dd>
-Releases memory used by an instance previously created with <tt>alloc</tt>
-or <tt>alloc-array</tt>. Note - this method is not presently protected
-against accidentally deleting something from the dictionary. If you do
-this, Bad Things are likely to happen. Be careful for the moment to apply
-free only to instances created with <tt>alloc</tt> or <tt>alloc-array</tt>.</dd>
-
-<dt>
-<b><tt>class&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance class
--- class metaclass )</tt></b>&nbsp;</dt>
-
-<dd>
-Convert an object signature into that of its class. Useful for calling
-class methods that have no object aliases.</dd>
-
-<dt>
-<b><tt>super&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance class
--- instance parent-class )</tt></b>&nbsp;</dt>
-
-<dd>
-Upcast an object to its parent class. The parent class of <tt>object</tt>
-is zero. Useful for invoking an overridden parent class method.</dd>
-
-<dt>
-<b><tt>pedigree&nbsp;&nbsp;&nbsp;&nbsp; ( instance class -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Display an object's pedigree - its chain of inheritance. This is an alias
-for the corresponding class method.</dd>
-
-<dt>
-<b><tt>size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance
-class -- sizeof(instance) )</tt></b>&nbsp;</dt>
-
-<dd>
-Returns the size, in address units, of one instance. Does not know about
-arrays! This is an alias for the class method <tt>get-size</tt></dd>
-
-<dt>
-<b><tt>methods&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance class -- )</tt></b>&nbsp;</dt>
-
-<dd>
-Class method alias. Displays the list of methods of the class and all superclasses
-of the instance.</dd>
-
-<dt>
-<b><tt>index&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( n instance class
--- instance[n] class )</tt></b>&nbsp;</dt>
-
-<dd>
-Convert array-of-objects base signature into signature for array element
-n. No check for bounds overflow. Index is zero-based, like C, so&nbsp;</dd>
-
-<dl>
-<dd>
-<tt>0 my-obj --> index</tt>&nbsp;</dd>
-</dl>
-
-<dd>
-is equivalent to&nbsp;</dd>
-
-<dl>
-<dd>
-<tt>my-obj</tt></dd>
-</dl>
-
-<dd>
-Check out the <a href="#minusrot">description of <tt>-ROT</tt></a> for
-help in dealing with indices on the stack.</dd>
-
-<dt>
-<b><tt>next&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance[n]
-class -- instance[n+1] class )</tt></b>&nbsp;</dt>
-
-<dd>
-Convert an array-object signature&nbsp; into the signature of the next
-object in the array. No check for bounds overflow.</dd>
-
-<dt>
-<b><tt>prev&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ( instance[n]
-class -- instance[n-1] class )</tt></b>&nbsp;</dt>
-
-<br>Convert an object signature into the signature of the previous object
-in the array. No check for bounds underflow.</dl>
-</td>
-</tr>
-</table>
-
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" >
-<tr>
-<td>
-<h3>
-<a NAME="stockclasses"></a>Supplied Classes (See classes.fr)</h3>
-
-<dl>
-<dt>
-<b><tt>metaclass&nbsp;</tt></b></dt>
-
-<dd>
-Describes all classes of Ficl. Contains class methods. Should never be
-directly instantiated or subclassed. Defined in oo.fr. Methods described
-above.</dd>
-
-<dt>
-<b><tt>object</tt>&nbsp;</b></dt>
-
-<dd>
-Mother of all Ficl objects. Defines default initialization and array indexing
-methods. Defined in oo.fr. Methods described above.</dd>
-
-<dt>
-<b><tt>c-ref</tt>&nbsp;</b></dt>
-
-<dd>
-Holds the signature of another object. Aggregate one of these into a data
-structure or container class to get polymorphic behavior. Methods &amp;
-members:&nbsp;</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; ( inst class -- ref-inst ref-class )</tt></dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( ref-inst ref-class inst class -- )</tt></dd>
-
-<dd>
-<tt>.instance&nbsp;&nbsp; ( inst class -- a-addr ) </tt>cell member that
-holds the instance</dd>
-
-<dd>
-<tt>.class&nbsp;&nbsp; ( inst class -- a-addr ) </tt>cell member that holds
-the class</dd>
-
-<dt>
-<b><tt>c-byte&nbsp;</tt></b></dt>
-
-<dd>
-Primitive class derived from <tt>object</tt>, with a 1-byte payload. Set
-and get methods perform correct width fetch and store. Methods &amp; members:</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; ( inst class -- c )</tt></dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( c inst class -- )</tt></dd>
-
-<dd>
-<tt>.payload&nbsp;&nbsp; ( inst class -- addr ) </tt>member holds instance's
-value</dd>
-
-<dt>
-<b><tt>c-2byte</tt></b>&nbsp;</dt>
-
-<dd>
-Primitive class derived from <tt>object</tt>, with a 2-byte payload. Set
-and get methods perform correct width fetch and store. Methods &amp; members:</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; ( inst class -- 2byte )</tt></dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( 2byte inst class -- )</tt></dd>
-
-<dd>
-<tt>.payload&nbsp;&nbsp; ( inst class -- addr ) </tt>member holds instance's
-value</dd>
-
-<dt>
-<b><tt>c-4byte</tt></b>&nbsp;</dt>
-
-<dd>
-Primitive class derived from <tt>object</tt>, with a 4-byte payload. Set
-and get methods perform correct width fetch and store. Methods &amp; members:</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; ( inst class -- x )</tt></dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( x inst class -- )</tt></dd>
-
-<dd>
-<tt>.payload&nbsp;&nbsp; ( inst class -- addr ) </tt>member holds instance's
-value</dd>
-
-<dt>
-<b><tt>c-cell</tt></b>&nbsp;</dt>
-
-<dd>
-Primitive class derived from <tt>object</tt>, with a cell payload (equivalent
-to c-4byte in 32 bit implementations, 64 bits wide on Alpha). Set and get
-methods perform correct width fetch and store. Methods &amp; members:</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; ( inst class -- x )</tt></dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( x inst class -- )</tt></dd>
-
-<dd>
-<tt>.payload&nbsp;&nbsp; ( inst class -- addr ) </tt>member holds instance's
-value</dd>
-
-<dt>
-<b><tt>c-ptr</tt></b></dt>
-
-<dd>
-Base class derived from <tt>object</tt> for pointers to non-object types.
-This class is not complete by itself: several methods depend on a derived
-class definition of <tt>@size</tt>. Methods &amp; members:</dd>
-
-<dd>
-<tt>.addr&nbsp;&nbsp; ( inst class -- a-addr )</tt> member variable - holds
-the pointer address</dd>
-
-<dd>
-<tt>get-ptr&nbsp;&nbsp; ( inst class -- ptr )</tt></dd>
-
-<dd>
-<tt>set-ptr&nbsp;&nbsp; ( ptr inst class -- )</tt></dd>
-
-<dd>
-<tt>inc-ptr&nbsp;&nbsp; ( inst class -- )</tt> Adds @size to pointer address</dd>
-
-<dd>
-<tt>dec-ptr&nbsp;&nbsp; ( inst class -- )</tt> Subtracts @size from pointer
-address</dd>
-
-<dd>
-<tt>index-ptr&nbsp;&nbsp; ( i inst class -- )</tt> Adds i*@size to pointer
-address</dd>
-
-<dt>
-<b><tt>c-bytePtr</tt></b></dt>
-
-<dd>
-Pointer to byte derived from c-ptr. Methods &amp; members:</dd>
-
-<dd>
-<tt>@size&nbsp;&nbsp; ( inst class -- size )</tt> Push size of the pointed-to
-thing</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; (&nbsp; inst class -- c ) </tt>Fetch the pointer's
-referent byte</dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( c inst class -- ) </tt>Store c at the pointer address</dd>
-
-<dt>
-<b><tt>c-2bytePtr</tt></b></dt>
-
-<dd>
-Pointer to double byte derived from c-ptr. Methods &amp; members:</dd>
-
-<dd>
-<tt>@size&nbsp;&nbsp; ( inst class -- size )</tt> Push size of the pointed-to
-thing</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; (&nbsp; inst class -- x ) </tt>Fetch the pointer's
-referent 2byte</dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( x inst class -- )</tt> Store 2byte x at the pointer
-address</dd>
-
-<dt>
-<b><tt>c-4bytePtr</tt></b></dt>
-
-<dd>
-Pointer to quad-byte derived from c-ptr. Methods &amp; members:</dd>
-
-<dd>
-<tt>@size&nbsp;&nbsp; ( inst class -- size )</tt> Push size of the pointed-to
-thing</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; (&nbsp; inst class -- x ) </tt>Fetch the pointer's
-referent 2byte</dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( x inst class -- )</tt> Store 2byte x at the pointer
-address</dd>
-
-<dt>
-<b><tt>c-cellPtr</tt></b></dt>
-
-<dd>
-Pointer to cell derived from c-ptr. Methods &amp; members:</dd>
-
-<dd>
-<tt>@size&nbsp;&nbsp; ( inst class -- size )</tt> Push size of the pointed-to
-thing</dd>
-
-<dd>
-<tt>get&nbsp;&nbsp; (&nbsp; inst class -- x ) </tt>Fetch the pointer's
-referent cell</dd>
-
-<dd>
-<tt>set&nbsp;&nbsp; ( x inst class -- )</tt> Storex at the pointer address</dd>
-
-<dt>
-<b><tt>c-string</tt></b>&nbsp; (see string.fr)</dt>
-
-<dd>
-Dynamically allocated string similar to MFC CString (Partial list of methods
-follows)</dd>
-
-<dd>
-<font face="Courier New"><font size=-1>set ( c-addr u 2:this -- ) </font></font><font size=+0>Initialize
-buffer to the specified string</font></dd>
-
-<dd>
-<font face="Courier New"><font size=-1>get ( 2:this -- c-addr u ) Return
-buffer contents as counted string</font></font></dd>
-
-<dd>
-<font face="Courier New"><font size=-1>cat ( c-addr u 2:this -- ) Append
-given string to end of buffer</font></font></dd>
-
-<dd>
-<font face="Courier New"><font size=-1>compare ( 2string 2:this -- n ) Return
-result of lexical compare</font></font></dd>
-
-<dd>
-<font face="Courier New"><font size=-1>type ( 2:this -- ) Print buffer to
-the output stream</font></font></dd>
-
-<dd>
-<font face="Courier New"><font size=-1>hashcode ( 2:this -- x ) Return hashcode
-of string (as in dictionary)</font></font></dd>
-
-<dd>
-<font face="Courier New"><font size=-1>free ( 2:this -- ) Release internal
-buffer</font></font></dd>
-
-<dt>
-<b><tt>c-hashstring</tt>&nbsp; </b>(see string.fr)</dt>
-
-<dd>
-Derived from c-string. This class adds a hashcode member variable.</dd>
-</dl>
-</td>
-</tr>
-</table>
-
-</body>
-</html>
diff --git a/doc/ficl_parse.html b/doc/ficl_parse.html
deleted file mode 100644
index a90607778f0e..000000000000
--- a/doc/ficl_parse.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
- <meta name="Author" content="john sadler">
- <meta name="Description" content="the coolest embedded scripting language ever">
- <title>Ficl Parse Steps</title>
-</head>
-<body>
-<link REL="SHORTCUT ICON" href="ficl.ico">
-<table BORDER=0 CELLSPACING=3 COLS=1 WIDTH="675" ><tr><td>
-<h1>Ficl Parse Steps</h1>
-<script language="javascript" src="ficlheader.js"></script>
-
-<h2>Overview</h2>
-<p>
-Ficl 2.05 and later includes an extensible parser chain. Ficl feeds every incoming token
-(chunk of text with no internal whitespace) to each step in the parse chain in turn. The
-first parse step that successfully matches the token applies semantics to it and returns
-a TRUE flag, ending the sequence. If all parse steps fire without a match, ficl prints
-an error message and resets the virtual machine. Parse steps can be written in precompiled
-code, or in ficl itself, and can be appended to the chain at run-time if you like.
-</p>
-<p>
-More detail:
-</p>
-<ul>
-<li>
-If compiling and local variable support is enabled, attempt to find the token in the local
-variable dictionary. If found, execute the token's compilation semantics and return
-</li>
-<li>
-Attempt to find the token in the system dictionary. If found, execute the token's semantics
-(may be different when compiling than when interpreting) and return
-</li>
-<li>
-If prefix support is enabled (Compile-time constant FICL_WANT_PREFIX in sysdep.h is non-zero),
-attempt to match the beginning of the token to the list of known prefixes. If there's a match,
-execute the associated prefix method.
-</li>
-<li>
-Attempt to convert the token to a number in the present <code>BASE</code>. If successful, push the
-value onto the stack if interpreting, compile it if compiling. Return
-</li>
-<li>
-All previous parse steps failed to recognize the token. Print "<token> not found" and abort
-</li>
-</ul>
-You can add steps to the parse chain, and you can add prefixes.
-<h2>Adding Parse Steps</h2>
-You can add a parse step in two ways. The first is to write a ficl word that
-has the correct stack signature for a parse step:
-<pre>
-my-parse-step ( c-addr u -- ??? flag )
-</pre>
-Where <code>c-addr u</code> are the address and length of the incoming token,
-and <code>flag</code> is <code>true</code> if the parse step recognizes the token
-and <code>false</code> otherwise.
-<br>
-Install the parse step using <code>add-parse-step</code>.
-A trivial example:
-<pre>
-: ?silly ( c-addr u -- flag )
- ." Oh no! Not another " type cr true ;
-' ?silly add-parse-step
-parse-order
-</pre>
-<p>
-The other way to add a parse step is by writing it in C, and inserting it into the
-parse chain with:
-</p>
-<pre>
-void ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep);
-</pre>
-Where <code>name</code> is the display name of the parse step in the parse chain (as revealed
-by <code>parse-order</code>). Parameter pStep is a pointer to the code for the parse step itself,
-and must match the following declaration:
-<pre>
-typedef int (*FICL_PARSE_STEP)(FICL_VM *pVM, STRINGINFO si);
-</pre>
-<p>
-Upon entry to the parse step, <code>si</code> points to the incoming token. The parse step
-must return <code>FICL_TRUE</code> if it succeeds in matching the token, and
-<code>FICL_TRUE</code> otherwise. If it succeeds in matching a token, the parse step
-applies semantics to it before returning. See <code>ficlParseNumber()</code> in words.c for
-an example.
-</p>
-
-<h2>Adding Prefixes</h2>
-<p>
-What's a prefix, anyway? A prefix (contributed by Larry Hastings) is a token that's
-recognized as the beginning of another token. Its presence modifies the semantics of
-the rest of the token. An example is <code>0x</code>, which causes digits following
-it to be converted to hex regardless of the current value of <code>BASE</code>.
-</p><p>
-Caveat: Prefixes are matched in sequence, so the more of them there are,
-the slower the interpreter gets. On the other hand, because the prefix parse step occurs
-immediately after the dictionary lookup step, if you have a prefix for a particular purpose,
-using it may save time since it stops the parse process.
-</p><p>
-Each prefix is a ficl word stored in a special wordlist called <code>&lt;prefixes&gt;</code>. When the
-prefix parse step (<code>?prefix</code> AKA ficlParsePrefix()) fires, it searches each word
-in <code>&lt;prefixes&gt;</code> in turn, comparing it with the initial characters of the incoming
-token. If a prefix matches, the parse step returns the remainder of the token to the input stream
-and executes the code associated with the prefix. This code can be anything you like, but it would
-typically do something with the remainder of the token. If the prefix code does not consume the
-rest of the token, it will go through the parse process again (which may be what you want).
-</p><p>
-Prefixes are defined in prefix.c and in softwords/prefix.fr. The easiest way to add a new prefix is
-to insert it into prefix.fr and rebuild the system. You can also add prefixes interactively
-by bracketing prefix definitions as follows (see prefix,fr):
-</p>
-<pre>
-start-prefixes ( defined in prefix.fr )
-\ make dot-paren a prefix (create an alias for it in the prefixes list)
-: .( .( ;
-: 0b 2 __tempbase ; immediate
-end-prefixes
-</pre>
-<p>
-The precompiled word <code>__tempbase</code> is a helper for prefixes that specify a
-temporary value of <code>BASE</code>.
-</p><p>
-Constant <code>FICL_EXTENDED_PREFIX</code> controls the inclusion of a bunch of additional
-prefix definitions. This is turned off in the default build since several of these prefixes
-alter standard behavior, but you might like them.
-</p>
-
-<h2>Notes</h2>
-<p>
-Prefixes and parser extensions are non-standard, although with the exception of prefix support,
-ficl's default parse order follows the standard. Inserting parse steps in some other order
-will almost certainly break standard behavior.
-</p>
-<p>
-The number of parse steps that can be added to the system is limited by the value of
-<code>FICL_MAX_PARSE_STEPS</code> (defined in sysdep.h unless you define it first), which defaults
-to 8. More parse steps means slower average interpret and compile performance,
-so be sparing. Same applies to the number of prefixes defined for the system, since each one
-has to be matched in turn before it can be proven that no prefix matches. On the other hand,
-if prefixes are defined, use them when possible: since they are matched early in the parse order,
-a prefix match short circuits the parse process, saving time relative to
-(for example) using a number builder parse step at the end of the parse chain.
-</p>
-<p>
-Compile time constant <code>FICL_EXTENDED_PREFIX</code> enables several more prefix
-definitions in prefix.c and prefix.fr. Please note that this will slow average compile and
-interpret speed in most cases.
-</p>
-<h2>Parser Glossary</h2>
-<dl>
-<dt><b><code>parse-order ( -- )</code></b></dt>
-<dd>
-Prints the list of parse steps in the order in which they are evaluated.
-Each step is the name of a ficl word with the following signature:
-<pre>
-parse-step ( c-addr u -- ??? flag )
-</pre>
-A parse step consumes a counted string (the incoming token) from the stack,
-and exits leaving a flag on top of the stack (it may also leave other parameters as side effects).
-The flag is true if the parse step succeeded at recognizing the token, false otherwise.
-</dd>
-<dt><b><code>add-parse-step ( xt -- )</code></b></dt>
-<dd>
-Appends a parse step to the parse chain. XT is the adress (execution token) of a ficl
-word to use as the parse step. The word must have the following signature:
-<pre>
-parse-step ( c-addr u -- ??? flag )
-</pre>
-A parse step consumes a counted string (the incoming token) from the stack,
-and exits leaving a flag on top of the stack (it may also leave other parameters as side effects).
-The flag is true if the parse step succeeded at recognizing the token, false otherwise.
-</dd>
-<dt><b><code>show-prefixes ( -- )</code></b></dt>
-<dd>
-Defined in <code>softwords/prefix.fr</code>.
-Prints the list of all prefixes. Each prefix is a ficl word that is executed if its name
-is found at the beginning of a token. See <code>softwords/prefix.fr</code> and <code>prefix.c</code> for examples.
-</dd>
-<dt><b><code>start-prefixes ( -- )</code></b></dt>
-<dd>
-Defined in <code>softwords/prefix.fr</code>.
-Declares the beginning of one or more prefix definitions (it just switches the compile wordlist
-to <code>&lt;prefixes&gt;</code>
-</dd>
-<dt><b><code>end-prefixes ( -- )</code></b></dt>
-<dd>
-Defined in <code>softwords/prefix.fr</code>.
-Restores the compilation wordlist that was in effect before the last invocation of
-<code>start-prefixes</code>. Note: the prior wordlist ID is stored in a Ficl variable, so
-attempts to nest <code>start-prefixes end-prefixes</code> blocks wil result in mildly silly
-side effects.
-</dd>
-</dl>
-</td></tr></table>
-</body>
-</html> \ No newline at end of file
diff --git a/doc/ficlheader.js b/doc/ficlheader.js
deleted file mode 100644
index 56ff63529e2b..000000000000
--- a/doc/ficlheader.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function ficlHeader()
-{
- document.write("<table BORDER=0 CELLSPACING=3 WIDTH='640' %>");
- document.write("<tr %>");
- document.write("<td %> <b %>Forth Inspired Command Language</b %></td %>");
- document.write("<td ROWSPAN='4' %><a href='http://ficl.sourceforge.net' %><img SRC='ficl_logo.jpg' border='0' alt='The ficl home page' height=64 width=64 %></a %></td %>");
- document.write("<td ROWSPAN='4' %><A href='http://sourceforge.net' %><IMG src='http://sourceforge.net/sflogo.php?group_id=24441' width='88' height='31' border='0' alt='Sourceforge Logo' %></A %></td %>");
- document.write("<td ROWSPAN='4' %><a href='http://www.links2go.net/topic/Forth' %><img SRC='skey.gif' ALT='Key Resources -- Forth' BORDER=0 height=81 width=81 %></a %></td %>");
- document.write("</tr %>");
- document.write("<tr %><td %><b %>Author: <a href='mailto:john_sadler@alum.mit.edu' %> John Sadler</a %></b %></td %></tr %>");
- document.write("<tr %><td %><b %>Created: 19 July 1997</b %></td %></tr %>");
- document.write("<tr %><td %><b %>Current Revision: 3.00a -- July 2001</b %></td %></tr %>");
- document.write("<tr %><td %><b %>Last Modified " + document.lastModified + "</b %></td %></tr %>");
- document.write("<tr %><td COLSPAN=4 %><b %><a href='index.html' %>Home</a %>&nbsp;|&nbsp;<a href='http://sourceforge.net/mail/?group_id=24441' %>Join Mailing Lists</a %>&nbsp;|&nbsp;<a href='http://sourceforge.net/projects/ficl' %>Project Page</a %>&nbsp|&nbsp;<a href='http://sourceforge.net/project/showfiles.php?group_id=24441' %>Download</a %></b %></td %></tr %>");
- document.write("</table %>");
-}
-
-ficlHeader();
-
diff --git a/doc/graphics/4ring.gif b/doc/graphics/4ring.gif
new file mode 100644
index 000000000000..b3ca2f61a087
--- /dev/null
+++ b/doc/graphics/4ring.gif
Binary files differ
diff --git a/doc/graphics/ficl.4.128.jpg b/doc/graphics/ficl.4.128.jpg
new file mode 100644
index 000000000000..0bebbb5ad3db
--- /dev/null
+++ b/doc/graphics/ficl.4.128.jpg
Binary files differ
diff --git a/doc/graphics/ficl.4.64.jpg b/doc/graphics/ficl.4.64.jpg
new file mode 100644
index 000000000000..7cca654ad50b
--- /dev/null
+++ b/doc/graphics/ficl.4.64.jpg
Binary files differ
diff --git a/doc/graphics/ficl.4.96.jpg b/doc/graphics/ficl.4.96.jpg
new file mode 100644
index 000000000000..67fb5f38cd77
--- /dev/null
+++ b/doc/graphics/ficl.4.96.jpg
Binary files differ
diff --git a/doc/ficl_oop.jpg b/doc/graphics/ficl_oop.jpg
index b4aee1021a98..b4aee1021a98 100644
--- a/doc/ficl_oop.jpg
+++ b/doc/graphics/ficl_oop.jpg
Binary files differ
diff --git a/doc/ficl_top.jpg b/doc/graphics/ficl_top.jpg
index f206d7131b91..f206d7131b91 100644
--- a/doc/ficl_top.jpg
+++ b/doc/graphics/ficl_top.jpg
Binary files differ
diff --git a/doc/graphics/sourceforge.jpg b/doc/graphics/sourceforge.jpg
new file mode 100644
index 000000000000..befbd3c1b946
--- /dev/null
+++ b/doc/graphics/sourceforge.jpg
Binary files differ
diff --git a/doc/index.html b/doc/index.html
index 850acfd0cd13..3f811e3b5497 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -1,116 +1,382 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
- <HEAD>
- <META name="Author" content="john sadler">
- <META name="Description" content="Ficl - embedded scripting with object oriented programming">
- <META name="Keywords" content="scripting prototyping tcl OOP Forth interpreter C">
-<STYLE>
- H1 {font: Arial; color: navy}
- H2 {font: Arial; color: navy}
- LI {font: Arial}
-</STYLE>
- <LINK rel="SHORTCUT ICON" href="ficl.ico">
- <TITLE>
- Ficl - Embedded Scripting - Index
- </TITLE>
- </HEAD>
- <BODY>
- <H1>
- <B>Ficl Documentation</B>
- </H1>
-<SCRIPT language="javascript" src="ficlheader.js" type="text/javascript">
-</SCRIPT>
- <TABLE summary="table of contents" border="0" cellspacing="3" cols="2" width="675">
- <TR>
- <TD width="500">
- <H2>
- Contents
- </H2>
- <UL>
- <LI>
- <A href="ficl_rel.html">Release notes</A>
- </LI>
- <LI>
- <A href="ficl.html#whatis">What is ficl?</A>
- </LI>
- <LI>
- <A href="http://sourceforge.net/projects/ficl">Ficl project page on Sourceforge</A>
- </LI>
- <LI>
- <A href="http://sourceforge.net/project/showfiles.php?group_id=24441">Download</A>
- </LI>
- <LI>
- <A href="ficl.html#links">Tutorials and References</A>
- </LI>
- <LI>
- <A href="ficl.html#includesficl">Ficl Inside!</A>
- </LI>
- <LI>
- <A href="ficl.html#lawyerbait">Disclaimer &mp; License</A>
- </LI>
- <LI>
- <A href="ficl.html#features">Ficl features</A>
- </LI>
- <LI>
- <A href="ficl.html#porting">Porting</A>
- </LI>
- <LI>
- <A href="ficl.html#api">Application Programming Interface</A>
- </LI>
- <LI>
- <A href="ficl.html#manifest">Distribution source files</A>
- </LI>
- <LI>
- <A href="ficl_loc.html">Local variables</A>
- </LI>
- <LI>
- <A href="ficl_oop.html">Object Oriented Programming in ficl</A>
- </LI>
- <LI>
- <A href="ficl_debug.html">Ficl Debugger</A>
- </LI>
- <LI>
- <A href="ficl.html#extras">Ficl extras</A>
- <UL>
- <LI>
- <A href="ficl.html#exnumber">Number syntax</A>
- </LI>
- <LI>
- <A href="ficl_parse.html">Parser extensions and prefix support</A>
- </LI>
- <LI>
- <A href="ficl.html#exsearch">Search order words</A>
- </LI>
- <LI>
- <A href="ficl.html#exuser">User variables</A>
- </LI>
- <LI>
- <A href="ficl.html#exmisc">Miscellaneous useful words</A>
- </LI>
- <LI>
- <A href="ficl.html#exficlwin">FiclWin words</A>
- </LI>
- </UL>
- </LI>
- <LI>
- <A href="ficl.html#ansinfo">ANS required information</A>
- </LI>
- </UL>
- </TD>
- <TD width="175">
- <A href="http://nav.webring.yahoo.com/hub?ring=forth&mp;list"><IMG src="http://www.iidbs.com/images/4ring.gif" width="155" height="140" border="0" alt="Forth Webring Logo"></A>
- <CENTER>
- <FONT size="3"><BR>
- <A href="http://www.webring.org/cgi-bin/webring?ring=forth;id=47;prev5">Previous 5 Sites</A><BR>
- <A href="http://www.webring.org/cgi-bin/webring?ring=forth;id=47;prev">Previous</A><BR>
- <A href="http://www.webring.org/cgi-bin/webring?ring=forth;id=47;next">Next</A><BR>
- <A href="http://www.webring.org/cgi-bin/webring?ring=forth;id=47;next5">Next 5 Sites</A><BR>
- <A href="http://www.webring.org/cgi-bin/webring?ring=forth;random">Random Site</A><BR>
- <A href="http://www.webring.org/cgi-bin/webring?ring=forth;list">List Sites</A></FONT>
- </CENTER>
- </TD>
- </TR>
- </TABLE>
- </BODY>
-</HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='WhatisFicl'>
+What is Ficl?
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+Ficl is a programming language interpreter designed to be embedded
+into other systems as a command, macro, and development prototyping
+language.
+<p>
+
+Ficl is an acronym for "Forth Inspired Command Language".
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FiclFeatures'>
+Ficl Features
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+
+<p><dt>
+Ficl is <b><i>easy to port.</i></b>
+<dd>
+
+
+
+<ul>
+
+<li>
+It typically takes under 2 hours to port to a new platform.
+
+<li>
+Ficl is written in strict ANSI C.
+
+<li>
+Ficl can run natively on 32- and 64-bit processors.
+
+</ul>
+
+
+
+<p><dt>
+Ficl has a <b><i>small memory footprint.</i></b>
+<dd>
+
+
+
+A fully featured Win32 console version takes less than 100K
+of memory, and a minimal version is less
+than half that.
+
+
+
+<p><dt>
+Ficl is <b><i>easy to integrate</i></b> into your program.
+<dd>
+
+
+
+Where most Forths view themselves as the center of the system and
+expect the rest of the system to be coded in Forth, Ficl acts as a
+component of your program. It is easy to export code written in C or
+ASM to Ficl (in the style of TCL), or to invoke Ficl code from a
+compiled module.
+
+
+
+<p><dt>
+Ficl is <b><i>fast.</i></b>
+<dd>
+
+
+
+Thanks to its
+<a href=http://www.complang.tuwien.ac.at/forth/threaded-code.html#switch-threading>"switch-threaded"</a>
+virtual machine design, Ficl 4 is faster than ever&mdash;about 3x the speed of Ficl 3.
+Ficl also features blindingly fast "just in time" compiling, removing the "compile" step from
+the usual compile-debug-edit iterative debugging cycle.
+
+
+
+<p><dt>
+Ficl is a <b><i>complete and powerful programming language.</i></b>
+<dd>
+
+
+
+Ficl is an implementation of the FORTH language, a language providing
+a wide range of standard programming language features:
+<ul>
+
+<li>
+Integer and floating-point numbers, with a rich set of operators.
+
+<li>
+Arrays.
+
+<li>
+File I/O.
+
+<li>
+Flow control (<code>if/then/else</code> and many looping structures).
+
+<li>
+Subroutines with named arguments.
+
+<li>
+Language extensibility.
+
+<li>
+Powerful code pre-processing features.
+
+</ul>
+
+
+
+<p><dt>
+Ficl is <b><i>standards-compliant.</i></b>
+<dd>
+
+
+
+Ficl conforms to the 1994 ANSI Standard for FORTH (DPANS94).
+See <a href=dpans.html>ANS Required Information</a> for
+more detail.
+
+
+<p><dt>
+Ficl is <b><i>extensible.</i></b>
+<dd>
+
+
+
+Ficl is extensible both at compile-time and at run-time.
+You can add new script functions, new native functions,
+even new control structures.
+
+
+
+
+<p><dt>
+Ficl adds <b><i>object oriented programming features.</i></b>
+<dd>
+
+
+
+Ficl's flexible OOP library can be used to wrap
+data structures or classes of the host system without altering them.
+(And remember how we said Ficl was extensible? Ficl's object-oriented
+programming extensions are written in Ficl.)
+
+
+
+<p><dt>
+Ficl is <b><i>interactive.</i></b>
+<dd>
+
+
+
+Ficl can be used interactively, like most other FORTHs, Python,
+and Smalltalk. You can inspect data, run commands, or even
+define new commands, all on a running Ficl VM.
+Ficl also has a built-in script debugger that allows you to
+step through Ficl code as it is executed.
+
+
+<p><dt>
+Ficl is <b><i>ROMable.</i></b>
+<dd>
+
+
+
+Ficl is designed to work in RAM based and ROM code / RAM
+data environments.
+
+
+
+<p><dt>
+Ficl is <b><i>safe for multithreaded programs.</i></b>
+<dd>
+
+
+
+Ficl is reentrant and thread-safe. After initialization,
+it does not write to any global data.
+
+
+<p><dt>
+Ficl is <b><i>open-source and free.</i></b>
+<dd>
+
+
+
+The <a href=license.html>Ficl licence</a> is a BSD-style
+license, requiring only that you document that you are
+using Ficl. There are no licensing costs for using Ficl.
+
+
+</dl>
+
+
+<a name=whatsnew>
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='WhatsNewInFicl40'>
+What's New In Ficl 4.0?
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+</a>
+
+Ficl 4.0 is a major change for Ficl. Ficl 4.0 is <i>smaller</i>,
+<i>faster</i>, <i>more powerful</i>, and <i>easier to use</i>
+than ever before. (Or your money back!)
+<p>
+
+Ficl 4.0 features a major engine rewrite. Previous versions
+of Ficl stored compiled words as an array of pointers to data
+structure; Ficl 4.0 adds "instructions", and changes over to
+mostly using a "switch-threaded" model. The result? Ficl 4.0
+is approximately <i>three times</i> as fast as Ficl 3.03.
+<p>
+
+Ficl 4.0 also adds the ability to store the "softcore" words
+as LZ77 compressed text. Decompression is so quick as to be
+nearly unmeasurable (0.00384 seconds on a 750MHz AMD Duron-based
+machine). And even with the runtime decompressor, the resulting
+Ficl executable is over 13k smaller!
+<p>
+
+Another new feature: Ficl 4.0 can take advantage of native
+support for double-word math. If your platform supports it,
+set the preprocessor symbol <code>FICL_HAVE_NATIVE_2INTEGER</code>
+to 1, and create <code>typedefs</code> for <code>ficl2Integer</code>
+and <code>ficl2Unsigned</code>.
+<p>
+
+Ficl 4.0 also features a retooled API, and a redesigned directory
+tree. The API is now far more consistent. But for those of you
+who are upgrading from Ficl 3.03 or before, you can enable API
+backwards compatibility by turning on the compile-time flag
+<code>FICL_WANT_COMPATIBILITY</code>.
+<p>
+
+Ficl 4.0 also extends support every kind of local and
+global value imaginable. Every values can individually
+be local or global, single-cell or double-cell, and
+integer or floating-point.
+And <code>TO</code> <i>always</i> does the right thing.
+<p>
+
+If you're using Ficl under Windows, you'll be happy
+to know that there's a brand-new build process.
+The Ficl build process now builds Ficl as
+<ul>
+
+<li>
+a static library (.LIB),
+
+<li>
+a dynamic library (.DLL, with a .LIB import library), and
+
+<li>
+a standalone executable (.EXE).
+
+</ul>
+
+Furthermore, each of these targets can be built in
+Debug or Release, Singlethreaded or Multithreaded,
+and optionally using the DLL version of the C runtime
+library for Multithreaded builds. (And, plus, the
+<code>/objects/common</code> nonsense is gone!)
+<p>
+
+
+Finally, Ficl 4.0 adds a <code>contrib</code>
+directory, a repository for user-contributed code that isn't
+part of the standard Ficl release. The only package there
+right now is <b>XClasses</b>, a Python-based IDL that generates
+the definition files for C++-based classes, the equivalent Ficl
+classes, and code to allow the Ficl classes to call the C++ methods.
+Using <b>XClasses</b> you can write your class once, and use it
+immediately from both C++ and Ficl.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='GettingFicl'>
+Getting Ficl
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+You can download Ficl from the
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441>
+Ficl download page at Sourceforge</a>.
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
diff --git a/doc/license.html b/doc/license.html
new file mode 100644
index 000000000000..324b134a1941
--- /dev/null
+++ b/doc/license.html
@@ -0,0 +1,103 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl licensing</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl licensing
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FiclLicenseAndDisclaimer'>
+Ficl License And Disclaimer
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<font size=+1>
+Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+<br>
+All rights reserved.
+</font>
+<p>
+
+<b>
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+<ol>
+
+<li>
+Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+<li>
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+</ol>
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+</b>
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/links.html b/doc/links.html
new file mode 100644
index 000000000000..5073ef5d3266
--- /dev/null
+++ b/doc/links.html
@@ -0,0 +1,318 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl links</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl links
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='OfficialFiclPages'>
+Official Ficl Pages
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<p><dt>
+<a href="http://ficl.sourceforge.net">http://ficl.sourceforge.net</a>
+<dd>
+
+
+The official web home of Ficl.
+
+<p><dt>
+<a href="http://sourceforge.net/project/showfiles.php?group_id=24441">http://sourceforge.net/project/showfiles.php?group_id=24441</a>
+<dd>
+
+
+The Ficl download page.
+
+
+</dl>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='ForthPrimersAndTutorials'>
+Forth Primers And Tutorials
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<p><dt>
+<a href="http://www.phys.virginia.edu/classes/551.jvn.fall01/primer.htm">http://www.phys.virginia.edu/classes/551.jvn.fall01/primer.htm</a>
+<dd>
+
+
+An excellent Forth primer, by Julian Nobel.
+
+<p><dt>
+<a href="http://ficl.sourceforge.net/pdf/Forth_Primer.pdf">http://ficl.sourceforge.net/pdf/Forth_Primer.pdf</a>
+<dd>
+
+
+Another excellent Forth primer, by Hans Bezemer.
+
+<p><dt>
+<a href="http://www.taygeta.com/forth_intro/stackflo.html">http://www.taygeta.com/forth_intro/stackflo.html</a>
+<dd>
+
+
+<i>An Introduction To Forth Using Stack Flow</i> by Gordon Charton.
+Mr. Charton's stack-flow diagrams make it easy to understand how
+to manipulate the FORTH stacks.
+
+<p><dt>
+<a href="http://www.softsynth.com/pforth/pf_tut.htm">http://www.softsynth.com/pforth/pf_tut.htm</a>
+<dd>
+
+
+Phil Burk's Forth Tutorial.
+
+</dl>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='TechnicalArticlesOnFiclAndForth'>
+Technical Articles On Ficl And Forth
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<p><dt>
+<a href="articles/ficlddj.pdf">articles/ficlddj.pdf</a>
+<dd>
+
+
+Manuscript of John Sadler's article on Ficl for January 1999 <a href=http://www.ddj.com>Dr. Dobb's Journal</a>.
+
+<p><dt>
+<a href="articles/jwsforml.pdf">articles/jwsforml.pdf</a>
+<dd>
+
+
+1998 FORML Conference paper: <i>OO Programming in Ficl,</i> written and presented by John Sadler.
+
+
+<p><dt>
+<a href="http://www.complang.tuwien.ac.at/forth/threaded-code.html">http://www.complang.tuwien.ac.at/forth/threaded-code.html</a>
+<dd>
+
+
+Anton Ertl's description of threaded code techniques. (The FORTH-related definition
+of "threaded code" is different from&mdash;and predates&mdash;the common modern
+usage dealing with light-weight processes.) Ficl 4 uses what Ertl calls
+"switch threading".
+
+<p><dt>
+<a href="http://ficl.sourceforge.net/dpans/dpans.htm">http://ficl.sourceforge.net/dpans/dpans.htm</a>
+<dd>
+
+
+1994 Draft Proposed American National Standard for Forth.
+And surprisingly readable, as language standards go.
+
+<p><dt>
+<a href="http://www.taygeta.com/forthlit.html">http://www.taygeta.com/forthlit.html</a>
+<dd>
+
+
+Forth literature index on Taygeta, a web clearinghouse of Forth links.
+
+</dl>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='OtherForthSitesOfInterest'>
+Other Forth Sites Of Interest
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<p><dt>
+<a href="http://www.forth.org">http://www.forth.org</a>
+<dd>
+
+
+The Forth Interest Group.
+
+<p><dt>
+<a href="http://www.forth.com">http://www.forth.com</a>
+<dd>
+
+
+FORTH, Incorporated. Thirty years old and going strong.
+You might be surprised to learn that they wrote software for
+the <a href=http://www.forth.com/Content/Stories/FedEx.htm>FedEx</a>
+"SuperTracker" bar code scanners / package trackers.
+
+</dl>
+
+<table width=100% bgcolor=#e0e0e0><tr><td width=160>
+<A href="http://t.webring.com/hub?sid=&ring=forth&list"><IMG src="graphics/4ring.gif" width="155" height="140" border="0" alt="Forth Webring Logo"></A>
+</td><td>
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='TheForthWebRing'>
+The Forth Web Ring
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&prev5">Previous 5 Sites</A><BR>
+<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&prev">Previous</A><BR>
+<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&next">Next</A><BR>
+<A href="http://t.webring.com/hub?sid=&ring=forth&id=47&next5">Next 5 Sites</A><BR>
+<A href="http://t.webring.com/hub?sid=&ring=forth&random">Random Site</A><BR>
+<A href="http://t.webring.com/hub?sid=&ring=forth&list">List Sites</A></FONT>
+</td></tr></table>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='SomeSoftwareThatUsesFicl'>
+Some Software That Uses Ficl
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+<li>
+The <a href="http://www.freebsd.org/">FreeBSD</a> boot loader
+(Daniel Sobral, Jordan Hubbard)
+
+<li>
+<a href="http://www.chipcenter.com/networking/images/prod/prod158a.pdf">
+SwitchCore
+</a>
+Gigabit Ethernet switches (&Ouml;rjan Gustavsson )
+
+<li>
+<a href="http://debuffer.sourceforge.net/">
+Palm Pilot Debuffer
+</a>
+(Eric Sessoms)
+Also see <a href=http://sonic-weasel.org/eric/ficlx/>FiclX</a>, a C++ interface to Ficl.
+
+<li>
+<a href="http://www.swcp.com/%7Ejchavez/osmond.html">
+Osmond PC Board Layout tool
+</a>
+
+<li>
+<a href="http://www.netcomsystems.com">
+NetCom Systems
+</a>
+ML7710
+
+<li>
+<a href="http://www.parview.com/ds/homepage.html">
+ParView
+</a>
+GPS system
+
+<li>
+<a href="http://www.thekompany.com/products/powerplant/software/Languages/Embedded.php3">
+PowerPlant Software
+</a>
+Development Environment for Linux
+
+<li>
+<a href="http://www.vyyo.com/products/architecture_v3000.html">
+Vyyo V3000 Broadband Wireless Hub
+</a>
+
+</ul>
+
+(Contact us if you'd like your name and product listed here.)
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/locals.html b/doc/locals.html
new file mode 100644
index 000000000000..c6c78d0206c6
--- /dev/null
+++ b/doc/locals.html
@@ -0,0 +1,253 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>local variables in Ficl</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+local variables in Ficl
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='AnOverviewAndAHistory'>
+An Overview And A History
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+
+Named, locally scoped variables came late to Forth. Purists feel that experienced
+Forth programmers can (and should) write supportable code using only anonymous
+stack variables and good factoring, and they complain that novices use
+global variables too frequently. But local variables cost little in terms of
+code size and execution speed, and are very convenient for OO programming
+(where stack effects are more complex).
+<p>
+
+Ficl provides excellent support
+for local variables, and the purists be damned&mdash;we use 'em all the time.
+<p>
+
+Local variables can only be declared inside a definition,
+and are only visible in that definition. Please refer to
+<a href="http://ficl.sourceforge.net/dpans/dpans13.htm">
+the ANS standard for FORTH
+</a> for more general information on local variables.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='John-HopkinsForthArgumentSyntax'>
+John-Hopkins Forth Argument Syntax
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+ANS Forth does not specify a complete local variable facility.
+Instead, it defines a foundation upon which to build one. Ficl comes with
+an adaptation of the Johns-Hopkins local variable syntax, as developed by John
+Hayes et al. However, Ficl extends this syntax with support for double-cell and
+floating-point numbers.
+
+<p>
+
+Here's the basic syntax of a JH-local variable declaration:
+<blockquote><code>
+<b>{</b> <i>arguments</i>
+<b>|</b> <i>locals</i>
+<b>--</b> <i>ignored</i>
+<b>}</b>
+</code></blockquote>
+(For experienced FORTH programmers: the declaration is designed to look like a stack comment,
+but it uses curly braces instead of parentheses.) Each section must list zero or more
+legal Ficl word names; comments and preprocessing are not allowed here.
+Here's what each section denotes:
+
+<ul>
+
+<li>
+The <i>arguments</i> section lists local variables which are initialized from the stack when the word executes.
+Each argument is set to the top value of the stack, starting at the rightmost argument name and moving left.
+You can have zero or more arguments.
+<p>
+
+<li>
+The <i>locals</i> section lists local variables which are set to zero when the word executes.
+You can have zero or more locals.
+<p>
+
+<li>
+Any characters between <code>--</code> and <code>}</code> are treated as a comment, and ignored.
+
+</ul>
+
+(The <code>|</code> and <code>--</code> sections are optional,
+but they must appear in the order shown if they appear at all.)
+<p>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='ArgumentTypes'>
+Argument Types
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Every time you specify a local variable (in either the <i>arguments</i> or the <i>locals</i> section),
+you can also specify the <i>type</i> of the local variable. By default, a local variable
+is a single-cell integer; you can specify that the local be a double-cell integer, and/or a
+floating-point number.
+<p>
+
+To specify the type of a local, specify one or more of the following single-character specifiers,
+followed by a colon (<code>:</code>).
+
+<table>
+
+<tr><td bgcolor=#e0e0e0>
+<b>1</b>
+</td><td bgcolor=#f0f0f0>
+single-cell
+</td></tr>
+
+
+
+<tr><td bgcolor=#e0e0e0>
+<b>2</b>
+</td><td bgcolor=#f0f0f0>
+double-cell
+</td></tr>
+
+
+
+<tr><td bgcolor=#e0e0e0>
+<b>d</b>
+</td><td bgcolor=#f0f0f0>
+double-cell
+</td></tr>
+
+
+
+<tr><td bgcolor=#e0e0e0>
+<b>f</b>
+</td><td bgcolor=#f0f0f0>
+floating-point (use floating stack)
+</td></tr>
+
+
+
+<tr><td bgcolor=#e0e0e0>
+<b>i</b>
+</td><td bgcolor=#f0f0f0>
+integer (use data stack)
+</td></tr>
+
+
+
+<tr><td bgcolor=#e0e0e0>
+<b>s</b>
+</td><td bgcolor=#f0f0f0>
+single-cell
+</td></tr>
+
+
+
+</table>
+
+For instance, the argument <code>f2:foo</code> would specify a double-width floating-point
+number.
+<p>
+
+The type specifiers are read right-to left, and when two specifiers conflict, the rightmost
+one takes priority. So <code>2is1f2:foo</code> would still specifiy a double-width floating-point
+number.
+<p>
+
+Note that this syntax <i>only works</i> for Ficl's JH-locals. Locals
+defined in some other way (say, with the FORTH standard word <code>LOCALS|</code>)
+will ignore this syntax, and the entire string will be used as the name of
+the local (type and all).
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='ASimpleExample'>
+A Simple Example
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<pre>
+: DEMONSTRATE-JH-LOCALS { c b a f:float -- a+b f:float*2 }
+ a b +
+ 2.0e float f*
+ ;
+</pre>
+
+
+</blockquote><p></td></tr></table></body></html>
+
diff --git a/doc/oop.html b/doc/oop.html
new file mode 100644
index 000000000000..ef0f7bfbdf9b
--- /dev/null
+++ b/doc/oop.html
@@ -0,0 +1,1640 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl oop</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl oop
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FiclObjectOrientedProgramming'>
+Ficl Object Oriented Programming
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+
+Ficl's object extensions provide the traditional OO benefits of associating
+data with the code that manipulates it, and reuse through single inheritance.
+Ficl also has some unusual capabilities that support interoperation with
+systems written in C.
+<p>
+
+Some design points of Ficl's OOP system:
+
+<ul>
+
+<li>
+Ficl objects are normally late bound for safety (late binding guarantees
+that the appropriate method will always be invoked for a particular object).
+Early binding is also available, provided you know the object's class at
+compile-time.
+
+<li>
+Ficl OOP supports single inheritance, aggregation, and arrays of objects.
+
+<li>
+Classes have independent name spaces for their methods: methods are only
+visible in the context of a class or object. Methods can be overridden
+or added in subclasses; there is no fixed limit on the number of methods
+of a class or subclass.
+
+<li>
+Ficl OOP syntax is regular and unified over classes and objects. In ficl,
+all classes are objects. Class methods include the ability to subclass
+and instantiate.
+
+<li>
+Ficl can adapt legacy data structures with object wrappers. You can model
+a structure in a Ficl class, and create an instance that refers to an address
+in memory that holds an instance of the structure. The <i>ref object</i>
+can then manipulate the structure directly. This lets you wrap data structures
+written and instantiated in C.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='Object-OrientedProgrammingconcepts'>
+Object-Oriented Programming concepts
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+If you're not familiar with object-oriented programming, you
+can click <a href="http://whatis.techtarget.com/definition/0,289893,sid9_gci212681,00.html">here</a>
+or <a href="http://www.softwaredesign.com/objects.html">here</a> for
+a general-purpose overview.
+Or click <a href="articles/oo_in_c.html#review">here</a> for a short review of object-oriented ideas,
+terms, and implementations in C.
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='Acknowledgements'>
+Acknowledgements
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Ficl is not the first Forth to include Object Oriented extensions. Ficl's
+OO syntax owes a debt to the work of John Hayes and Dick Pountain, among
+others. OO Ficl is different from other OO Forths in a few ways, though
+(some things never change). First, unlike several implementations, the
+syntax is documented (<a href="#ootutorial">below</a>) beyond the source
+code. In Ficl's spirit of working with C code, the OO syntax provides means
+to adapt existing data structures. I've tried to make Ficl's OO model simple
+and safe by unifying classes and objects, providing late binding by default,
+and separating namespaces so that methods and regular Forth words are not
+easily confused.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='FiclObjectModel'>
+Ficl Object Model
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+All classes in Ficl are derived from the common base class
+<code><a href="#objectgloss">OBJECT</a></code>
+as shown in the <a href="#figure1">figure</a> below. All classes are instances
+of <code><a href="#glossclass">METACLASS</a></code>. This means that classes
+are objects, too. <code>METACLASS</code> implements the methods for messages
+sent to classes. Class methods create instances and subclasses, and give
+information about the class. Each class is represented by a data stucture
+of three elements:
+
+<ol>
+
+<li>
+The address (named <code>.CLASS</code> ) of a parent class, or zero if it's
+a base class (only <code>OBJECT</code> and <code>METACLASS</code> have this property).
+
+<li>
+The size (named <code>.SIZE</code> ) in address units of an instance of the
+class.
+
+<li>
+A wordlist ID (named <code>.WID</code> ) for the methods of the class.
+
+</ol>
+
+In the figure below, <code>METACLASS</code> and <code>OBJECT</code> are real system-supplied
+classes. The others are contrived to illustrate the relationships among
+derived classes, instances, and the two system base classes. The dashed
+line with an arrow at the end indicates that the object/class at the arrow
+end is an instance of the class at the other end. The vertical line with
+a triangle denotes inheritance.
+<p>
+
+Note for the curious: <code>METACLASS</code> behaves like a class&mdash;it responds
+to class messages and has the same properties as any other class. If you
+want to twist your brain in knots, you can think of <code>METACLASS</code>
+as an instance of itself.
+<p>
+
+
+<a NAME="figure1"></a><img SRC="graphics/ficl_oop.jpg" VSPACE=10 height=442 width=652>
+<br>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='FiclObject-OrientedSyntaxTutorial'>
+Ficl Object-Oriented Syntax Tutorial
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<a NAME="ootutorial"></a>
+
+It's helpful to have some familiarity with Forth and the customary Forth
+stack notation to understand this tutorial. To get started, take a look
+at this <a href="http://www.taygeta.com/forth_intro/stackflo.html">web-based
+Forth tutorial</a>. If you're comfortable with both OO and Forth, you can
+<a href="#ootutorial-finally">jump ahead</a>.
+<p>
+
+A Ficl <a href="oo_in_c.html#object-def">object</a> associates a <a href="oo_in_c.html#class-def">class</a>
+with an <a href="oo_in_c.html#instance-def">instance</a> (the storage for
+one set of instance variables). This is done explicitly on Ficl's stack,
+in that any Ficl object is represented by a cell pair:
+<blockquote><code>( INSTANCE-address CLASS-address )</code></blockquote>
+
+The <code>INSTANCE-address</code> is the address of the object's storage, and the <code>CLASS-address</code>
+is the address of its class. Whenever a named Ficl object executes (e.g.
+when you type its name and press enter at the Ficl prompt), it leaves this
+"signature". All methods by convention expect a class and instance on the
+stack when they execute, too. In many other OO languages, including C++,
+instances contain information about their classes (a <a href="http://www.mvps.org/vbvision/vtable.htm">vtable</a>
+pointer, for example). By making this pairing explicit rather than implicit,
+Ficl can be OO about chunks of data that don't realize that they are objects,
+without sacrificing any robustness for native objects. That means that
+you can use Ficl to write object wrappers for data structures created in
+C or assembly language, as long as you can determine how they're laid out
+in memory.
+<p>
+
+Whenever you create an object in Ficl, you specify its class.
+After that, the object always pushes its class and the address of its
+<a href="http://www.aware.com/Glossary/main.htm#P">payload</a>
+(instance variable space) when invoked by name.
+<p>
+
+Classes are special kinds of objects that store the methods of their
+instances, the size of an instance's payload, and a parent class pointer.
+Classes themselves are instances of a special base class called <code>METACLASS</code>,
+and all classes inherit from class <code>OBJECT</code>. This is confusing at
+first, but it means that Ficl has a very simple syntax for constructing
+and using objects. Class methods include subclassing (<code>SUB</code>), creating
+initialized and uninitialized instances (<code>NEW</code> and <code>INSTANCE</code>),
+and creating reference instances (<code>REF</code>), described later. Classes
+also have methods for disassembling their methods (<code>SEE</code>), identifying
+themselves (<code>ID</code>), and listing their pedigree (<code>PEDIGREE</code>).
+All objects inherit (from <code>OBJECT</code>) methods for initializing instances
+and arrays of instances, for performing array operations, and for getting
+information about themselves.
+
+
+<p>
+</blockquote><table border=0 bgcolor=#d0d0d0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=3><b><i>
+<a name='MethodsAndMessages'>
+Methods And Messages
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Methods are the functions that objects execute in response to messages.
+A message is a request to an object for a behavior that the object supports.
+When it receives a message, the target object looks up a method that performs
+the behavior for its class, and executes it. Any specific message may be
+bound to different methods in different objects, according to class. This
+separation of messages and methods allows objects to behave <a href="http://www.whatis.com/polymorp.htm">polymorphically</a>.
+(In Ficl, methods are words defined in the context of a class, and messages
+are the names of those words.) Ficl classes associate messages with methods
+for their instances (a fancy way of saying that each class owns a wordlist).
+Ficl provides a late-binding operator <code>--></code> that sends messages
+to objects at run-time, and an early-binding operator <code>=></code>
+that compiles a specific class's method. These operators are the only supported
+way to invoke methods. Regular Forth words are not visible to the method-binding
+operators, so there's no chance of confusing a message with a regular
+word of the same name.
+
+<a NAME="ootutorial-finally"></a>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='Tutorial'>
+Tutorial
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+(Finally!)
+<p>
+
+This is a tutorial. It works best if you follow along by pasting the examples
+into <b>ficlWin</b>, the Win32 version of Ficl included with the release sources
+(or some other build that includes the OO part of <code>softcore.c</code>). If you're
+not familiar with Forth, please see one of these <a href="#links">references</a>.
+Ficl's OOP words are in vocabulary <code>OOP</code>. To put <code>OOP</code> in
+the search order and make it the compilation wordlist, type:
+<pre>
+ONLY
+ALSO OOP DEFINITIONS
+</pre>
+
+<b>Note for beginners:</b> To see the effect of the commands above, type
+<code>ORDER</code>
+after each line. You can repeat the sequence above if you like.
+<p>
+
+To start, we'll work with the two base classes <code>OBJECT</code> and <code>METACLASS</code>.
+Try this:
+<pre>
+METACLASS --> METHODS
+</pre>
+
+The line above contains three words. The first is the name of a class,
+so it pushes its signature on the stack. Since all classes are instances
+of <code>METACLASS</code>, <code>METACLASS</code> behaves as if it is an instance
+of itself (this is the only class with this property). It pushes the same
+address twice: once for the class and once for the payload, since they
+are the same. The next word finds a method in the context of a class and
+executes it. In this case, the name of the method is <code>METHODS</code>.
+Its job is to list all the methods that a class knows. What you get when
+you execute this line is a list of all the class methods Ficl provides.
+<pre>
+OBJECT --> SUB C-LED
+</pre>
+Causes the base-class <code>OBJECT</code> to derive from itself a new class
+called <code>C-LED</code>. Now we'll add some instance variables and methods to the new class.
+<p>
+
+<b>Note:</b> I like to prefix the names of classes with <code>c-</code> and the
+names of member variables with a period, but this is just a convention.
+If you don't like it, pick your own.
+<pre>
+C-BYTE OBJ: .STATE
+: INIT { 2:THIS -- }
+ THIS --> SUPER --> INIT
+ ." Initializing an instance of "
+ THIS --> CLASS --> ID TYPE CR ;
+: ON { LED# 2:THIS -- }
+ THIS --> .STATE --> GET
+ 1 LED# LSHIFT OR DUP !OREG
+ THIS --> .STATE --> SET ;
+: OFF { LED# 2:THIS -- }
+ THIS --> .STATE --> GET
+ 1 LED# LSHIFT INVERT AND DUP !OREG
+ THIS --> .STATE --> SET&NBSP; ;
+END-CLASS
+</pre>
+The first line adds an instance variable called <code>.STATE</code> to the
+class. This particular instance variable is an object&mdash;it will be an instance
+of <code>C-BYTE</code>, one of Ficl's stock classes (the source for which can be found
+in the distribution in <code>softcore/classes.fr</code>).
+<p>
+
+Next we've defined a method called <code>INIT</code>. This line also declares
+a <a href="locals.html">local variable</a> called <code>THIS</code>
+(the 2 in front tells Ficl that this is a double-cell local). All methods
+by convention expect the address of the class and instance on top of the
+stack when called. The next three lines define the behavior of <code>INIT</code> when it's called.
+It first calls its superclass's version of <code>INIT</code> (which in this
+case is "<code>OBJECT => INIT</code>"&mdash;this default implementation clears all
+instance variables). The rest displays some text and causes the instance
+to print its class name (<code>THIS --> CLASS --> ID</code>).
+<p>
+
+The <code>INIT</code>> method is special for Ficl objects: whenever
+you create an initialized instance using <code>NEW</code> or <code>NEW-ARRAY</code>,
+Ficl calls the class's <code>INIT</code> method for you on that instance. The
+default <code>INIT</code> method supplied by <code>OBJECT</code> clears the instance,
+so we didn't really need to override it in this case (see the source code
+in <code>softcore/oo.fr</code>).
+<p>
+
+The <code>ON</code> and <code>OFF</code> methods defined above hide the details
+of turning LEDs on and off. The interface to FiclWin's simulated hardware
+is handled by <code>!OREG</code>. The class keeps the LED state in a shadow
+variable (<code>.STATE</code>) so that <code>ON</code> and <code>OFF</code> can work
+in terms of LED number rather than a bitmask.
+<p>
+
+Now make an instance of the new class:
+<pre>
+C-LED --> NEW LED
+</pre>
+
+And try a few things...
+<pre>
+LED --> METHODS
+LED --> PEDIGREE
+1 LED --> ON
+1 LED --> OFF
+</pre>
+
+Or you could type this with the same effect:
+<pre>
+LED 2DUP --> METHODS --> PEDIGREE
+</pre>
+
+Notice (from the output of <code>METHODS</code>) that we've overridden the
+<code>INIT</code> method supplied by object, and added two more methods for the member
+variables. If you type <code>WORDS</code>, you'll see that these methods are
+not visible outside the context of the class that contains them. The method
+finder <code>--></code> uses the class to look up methods. You can use
+this word in a definition, as we did in <code>INIT</code>, and it performs
+late binding, meaning that the mapping from message (method name) to method
+(the code) is deferred until run-time. To see this, you can decompile the
+init method like this:
+<pre>
+C-LED --> SEE INIT
+</pre>
+
+or
+<pre>
+LED --> CLASS --> SEE INIT
+</pre>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='EarlyBinding'>
+Early Binding
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Ficl also provides early binding if you ask for it. Early binding is not
+as safe as late binding, but it produces code that is more compact and
+efficient because it compiles method addresses rather then their names.
+In the preferred uses of early binding, the class is assumed to be the
+one you're defining. This kind of early binding can only be used inside
+a class definition. Early bound methods still expect to find a class and
+instance cell-pair on top of the stack when they run.
+<p>
+
+Here's an example that illustrates a potential problem:
+<pre>
+OBJECT --> SUB C1
+: M1 { 2:THIS -- } ." C1'S M1" CR ;
+: M2 { 2:THIS -- } ." Running " THIS MY=> M1 ; ( early )
+: M3 { 2:THIS -- } ." Running " THIS --> M1 ( late )
+END-CLASS
+C1 --> SUB C2
+: M1 { 2:THIS -- } ." C2'S M1" CR ;
+END-CLASS
+C2 --> NEW I2
+I2 --> M1 ( runs the M1 defined in C2 )
+I2 --> M2 ( Is this what you wanted? )
+I2 --> M3 { runs the overridden M1)
+</pre>
+
+Even though we overrode method <code>M1</code> in class <code>C2</code>, the definition of <code>M2</code> with
+early binding forced the use of <code>M1</code> as defined in <code>C1</code>. If that's what you
+want, great, but more often you'll want the flexibility of overriding parent
+class behaviors appropriately.
+
+<ol>
+
+<li>
+<code>MY=></code> binds early to a method in the class being defined,
+as in the example above.
+
+<li>
+<code>MY=[ ]</code> binds a sequence of methods in the current class.
+Useful when the class has object members. Lines like
+<code>THIS --> STATE --> SET</code> in the definition of <code>C-LED</code> above can be replaced with
+<code>THIS MY=[ STATE SET ]</code> to use early binding.
+
+<li>
+<code>=></code> (dangerous) pops a class off the stack and compiles
+the method in that class. Since you have to specify the class explicitly,
+there is a real danger that this will be out of sync with the class you
+really wanted. I recommend you use <code>MY=></code> or <code>MY=[ ]</code> instead.
+
+</ol>
+
+Early binding using <code>=></code> is dangerous because it partially
+defeats the data-to-code matching mechanism object oriented languages were
+created to provide, but it does increase run-time speed by binding the
+method at compile time. In many cases, such as the <code>INIT</code> method,
+you can be reasonably certain of the class of thing you're working on.
+This is also true when invoking class methods, since all classes are instances
+of <code>METACLASS</code>. Here's an example from the definition of <code>METACLASS</code>
+in oo.fr (don't paste this into ficlWin&mdash;it's already there):
+<pre>
+: NEW \ ( class metaclass "name" -- )
+ METACLASS => INSTANCE --> INIT ;
+</pre>
+
+Try this:
+<pre>
+METACLASS --> SEE NEW
+</pre>
+
+Decompiling the method with <code>SEE</code> shows the difference between the
+two strategies. The early bound method is compiled inline, while the late-binding
+operator compiles the method name and code to find and execute it in the
+context of whatever class is supplied on the stack at run-time.
+<p>
+
+Notice that the primitive early-binding operator <code>=></code> requires
+a class at compile time. For this reason, classes are <code>IMMEDIATE</code>,
+meaning that they push their signature at compile time or run time. I'd
+recommend that you avoid early binding until you're very comfortable with
+Forth, object-oriented programming, and Ficl's OOP syntax.
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='MoreAboutInstanceVariables'>
+More About Instance Variables
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<i>Untyped</i> instance variable methods (created by <code>CELL: CELLS: CHAR:</code>
+and <code>CHARS:</code>) just push the address of the corresponding instance
+variable when invoked on an instance of the class. It's up to you to remember
+the size of the instance variable and manipulate it with the usual Forth
+words for fetching and storing.
+<p>
+
+As advertised earlier, Ficl provides ways to objectify existing data
+structures without changing them. Instead, you can create a Ficl class
+that models the structure, and instantiate a <i>ref</i> from this class,
+supplying the address of the structure. After that, the <i>ref instance</i>
+behaves as a Ficl object, but its instance variables take on the values
+in the existing structure. Example (from <code>softcore/ficlclass.fr</code>):
+<pre>
+OBJECT SUBCLASS C-WORDLIST
+ C-WORDLIST REF: .PARENT
+ C-PTR OBJ: .NAME
+ C-CELL OBJ: .SIZE
+ C-WORD REF: .HASH ( first entry in hash table )
+
+ : ?
+ --> GET-NAME ." ficl wordlist " TYPE CR ;
+ : PUSH DROP >SEARCH ;
+ : POP 2DROP PREVIOUS ;
+ : SET-CURRENT DROP SET-CURRENT ;
+ : GET-NAME DROP WID-GET-NAME ;
+ : WORDS { 2:THIS -- }
+ THIS MY=[ .SIZE GET ] 0 DO
+ I THIS MY=[ .HASH INDEX ] ( 2list-head )
+ BEGIN
+ 2DUP --> GET-NAME TYPE SPACE
+ --> NEXT OVER
+ 0= UNTIL 2DROP CR
+ LOOP
+ ;
+END-CLASS
+</pre>
+
+In this case, <code>C-WORDLIST</code> describes Ficl's wordlist structure;
+<code>NAMED-WID</code> creates a wordlist and binds it to a ref instance of
+<code>C-WORDLIST</code>.
+The fancy footwork with <code>POSTPONE</code> and early binding is required
+because classes are immediate. An equivalent way to define <code>NAMED-WID</code> with
+late binding is:
+<pre>
+: NAMED-WID ( c-address u -- )
+ WORDLIST POSTPONE C-WORDLIST --> REF
+ ;
+</pre>
+
+To do the same thing at run-time (and call it <code>MY-WORDLIST</code>):
+
+<pre>wordlist c-wordlist --> ref my-wordlist</pre>
+
+Now you can deal with the wordlist through the ref instance:
+<pre>
+MY-WORDLIST --> PUSH
+MY-WORDLIST --> SET-CURRENT
+ORDER
+</pre>
+
+Ficl can also model linked lists and other structures that contain pointers
+to structures of the same or different types. The class constructor word
+<a href="#exampleref:"><code>REF:</code></a>
+makes an aggregate reference to a particular class. See the <a href="#glossinstance">instance
+variable glossary</a> for an <a href="#exampleref:">example</a>.
+<p>
+
+Ficl can make arrays of instances, and aggregate arrays into class descripions.
+The <a href="#glossclass">class methods</a> <code>ARRAY</code> and <code>NEW-ARRAY</code>
+create uninitialized and initialized arrays, respectively, of a class.
+In order to initialize an array, the class must define (or inherit) a reasonable
+<code>INIT</code> method. <code>NEW-ARRAY</code> invokes it on each member of the array
+in sequence from lowest to highest. Array instances and array members use
+the object methods <code>INDEX</CODE>, <CODE>NEXT</CODE>, and <CODE>PREV</code>
+to navigate. Aggregate a member array of objects using <a href="#arraycolon"><code>ARRAY:</code></a>.
+The objects are not automatically initialized in this case&mdash;your class
+initializer has to call <code>ARRAY-INIT</code> explicitly if you want
+this behavior.
+<p>
+
+For further examples of OOP in Ficl, please see the source file <code>softcore/ficlclass.fr</code>.
+This file wraps several Ficl internal data structures in objects and gives
+use examples.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='FiclStringClasses'>
+Ficl String Classes
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<a NAME="cstring"></a>
+
+<code>C-STRING</code> is a reasonably useful dynamic string class.
+Source code for the class is located in <code>softcore/string.fr</code>.
+Features:
+dynamic creation and resizing; deletion, char cout, concatenation, output,
+comparison; creation from quoted string constant (<code>S"</code>).
+<p>
+Examples of use:
+<pre>
+C-STRING --> NEW HOMER
+S" In this house, " HOMER --> SET
+S" we obey the laws of thermodynamics!" HOMER --> CAT
+HOMER --> TYPE
+</pre>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='OOPGlossary'>
+OOP Glossary
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<a NAME="oopgloss"></a>
+
+<b>Note:</b> With the exception of the binding operators (the first two definitions
+here), all of the words in this section are internal factors that you don't
+need to worry about. These words provide method binding for all classes
+and instances. Also described are supporting words and execution factors.
+All are defined in <code>softcore/oo.fr</code>.
+
+<dl>
+
+<dt><code>--> <i>( instance class "method-name" -- xn )</i></code><dd>
+
+
+
+Late binding: looks up and executes the given method in the context of
+the class on top of the stack.
+
+<dt><code>C-> <i>( instance class "method-name" -- xn exc )</i></code><dd>
+
+
+
+Late binding with <code>CATCH</code>: looks up and <code>CATCH</code>es the given
+method in the context of the class on top of the stack, pushes zero or
+exception code upon return.
+
+<dt><code>MY=> <i>compilation: ( "method-name" -- ) execution: ( instance class -- xn )</i></code><dd>
+
+
+
+Early binding: compiles code to execute the method of the class being defined.
+Only visible and valid in the scope of a <code>--> SUB</CODE> .. <CODE>END-CLASS</code>
+class definition.
+
+<dt><code>MY=[ <i>compilation: ( "obj1 obj2 .. method ]" -- ) execution: ( instance class -- xn )</i></code><dd>
+
+
+
+Early binding: compiles code to execute a chain of methods of the class
+being defined. Only visible and valid in the scope of a <code>--> SUB</CODE>
+.. <CODE>END-CLASS</code> class definition.
+
+<dt><code>=> <i>compilation: ( class metaclass "method-name" -- ) execution: ( instance class -- xn )</i></code><dd>
+
+
+
+Early binding: compiles code to execute the method of the class specified
+at compile time.
+
+<dt><code>do-do-instance <i></i></code><dd>
+
+
+
+When executed, causes the instance to push its <code>( INSTANCE CLASS )</code> stack
+signature. Implementation factor of <code>METACLASS --> SUB</code></b> .
+Compiles <code>.DO-INSTANCE</code> in the context of a class; <code>.DO-INSTANCE</code>
+implements the <code>DOES></code> part of a named instance.
+
+<dt><code>exec-method <i>( instance class c-address u -- xn )</i></code><dd>
+
+
+
+Given the address and length of a method name on the stack, finds
+the method in the context of the specified class and invokes it. Upon entry
+to the method, the instance and class are on top of the stack, as usual.
+If unable to find the method, prints an error message and aborts.
+
+<dt><code>find-method-xt <i>( class "method-name" -- class xt )</i></code><dd>
+
+
+
+Attempts to map the message to a method in the specified class. If successful,
+leaves the class and the execution token of the method on the stack. Otherwise
+prints an error message and aborts.
+
+<dt><code>lookup-method <i>( class c-address u -- class xt )</i></code><dd>
+
+
+
+Given the address and length of a method name on the stack, finds
+the method in the context of the specified class. If unable to find the
+method, prints an error message and aborts.
+
+<dt><code>parse-method <i>compilation: ( "method-name" -- ) execution: ( -- c-address u )</i></code><dd>
+
+
+
+Parse <code>"method-name"</code> from the input stream and compile code to push its length
+and address when the enclosing definition runs.
+</dl>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#d0d0d0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=3><b><i>
+<a name='InstanceVariableGlossary'>
+Instance Variable Glossary
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<a NAME="glossinstance"></a>
+
+<b>Note:</b>: These words are only visible when creating a subclass! To
+create a subclass, use the <code>SUB</code> method on <code>OBJECT</code> or any
+class derived from it (<i>not</i> <code>METACLASS</code>). Source code for
+Ficl OOP is in <code>softcore/oo.fr</code>.
+<p>
+
+Instance variable words do two things: they create methods that do
+san action appropriate for the type of instance variable they represent,
+and they reserve space in the class template for the instance variable.
+We'll use the term <i>instance variable</i> to refer both to the method
+that gives access to a particular field of an object, and to the field
+itself. Rather than give esentially the same example over and over, here's
+one example that shows several of the instance variable construction words
+in use:
+
+<pre>
+OBJECT SUBCLASS C-EXAMPLE
+ CELL: .CELL0
+ C-4BYTE OBJ: .NCELLS
+ 4 C-4BYTE ARRAY: .QUAD
+ CHAR: .LENGTH
+ 79 CHARS: .NAME
+END-CLASS
+</pre>
+
+This class only defines instance variables, and it inherits some methods
+from <code>OBJECT</code>. Each untyped instance variable (<code>.CELL0</code>, <code>.LENGTH</code>,
+<code>.NAME</code>) pushes its address when executed. Each object instance variable
+pushes the address and class of the aggregate object. Similar to C, an
+array instance variable leaves its base address (and its class) when executed.
+The word <code>SUBCLASS</code> is shorthand for <code>--> sub</code> .
+
+<dl>
+
+<dt><code>CELL: <i>compilation: ( offset "name" -- offset ) execution: ( -- cell-address )</i></code><dd>
+
+
+
+Create an untyped instance variable one cell wide. The instance variable
+leaves its payload's address when executed.
+
+<dt><code>CELLS: <i>compilation: ( offset nCells "name" -- offset' ) execution: ( -- cell-address )</i></code><dd>
+
+
+
+Create an untyped instance variable <code>nCells</code> cells wide.
+
+<dt><code>CHAR: <i>compilation: ( offset "name" -- offset' ) execution: ( -- cell-address )</i></code><dd>
+
+
+
+Create an untyped member variable one character wide.
+
+<dt><code>CHARS: <i>compilation: ( offset nChars "name" -- offset' ) execution: ( -- cell-address )</i></code><dd>
+
+
+
+Create an untyped member variable <code>nChars</code> characters wide.
+
+<dt><code>OBJ: <i>compilation: ( offset class metaclass "name" -- offset' ) execution: ( -- instance class )</i></code><dd>
+
+
+
+Aggregate an uninitialized instance of <code>CLASS</code> as a member variable
+of the class under construction.
+
+<dt><code>ARRAY: <i>compilation: ( offset nObjects class metaclass "name" -- offset' ) execution: ( -- instance class )</i></code><dd>
+
+
+<a NAME="arraycolon"></a>
+
+Aggregate an uninitialized array of instances of the class specified as
+a member variable of the class under construction.
+
+<dt><code>EXAMPLEREF: <i>compilation: ( offset class metaclass "name" -- offset' ) execution: ( -- ref-instance ref-class )</i></code><dd>
+
+
+
+Aggregate a reference to a class instance. There is no way to set the value
+of an aggregated ref&mdash;it's meant as a way to manipulate existing data
+structures with a Ficl OO model. For example, if your system contains a
+linked list of 4 byte quantities, you can make a class that represents
+a list element like this:
+
+<pre>
+OBJECT SUBCLASS C-4LIST
+ C-4LIST REF: .LINK
+ C-4BYTE OBJ: .PAYLOAD
+END-CLASS
+
+ADDRESS-OF-EXISTING-LIST C-4LIST --> REF MYLIST
+</pre>
+
+<dd>
+The last line binds the existing structure to an instance of the class
+we just created. The link method pushes the link value and the class <code>C_4LIST</code>,
+so that the link looks like an object to Ficl and like a struct to C (it
+doesn't carry any extra baggage for the object model&mdash;the Ficl methods
+alone take care of storing the class information).
+<p>
+
+<b>Note:</b> Since a <code>REF:</code> aggregate can only support one class, it's good for
+modeling static structures, but not appropriate for polymorphism. If you
+want polymorphism, aggregate a <code>C_REF</code> (see <code>softcore/classes.fr</code> for source)
+into your class&mdash;it has methods to set and get an object.
+<p>
+
+By the way, it is also possible to construct a pair of classes that contain
+aggregate pointers to each other. Here's an example:
+
+<pre>
+OBJECT SUBCLASS AKBAR
+ SUSPEND-CLASS \ put akbar on hold while we define jeff
+
+OBJECT SUBCLASS JEFF
+ AKBAR REF: .SIGNIFICANT-OTHER
+ ( <i>... your additional methods here ...</i> )
+END-CLASS \ done with jeff
+
+AKBAR --> RESUME-CLASS \ resume defining akbar
+ JEFF REF: .SIGNIFICANT-OTHER
+ ( <i>... your additional methods here ...</i> )
+END-CLASS \ done with akbar
+</pre>
+
+</dl>
+
+<a NAME="glossclass"></a>
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='ClassMethodsGlossary'>
+Class Methods Glossary
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+These words are methods of <code>METACLASS</code>. They define the manipulations
+that can be performed on classes. Methods include various kinds of instantiation,
+programming tools, and access to member variables of classes. Source is
+in <code>softcore/oo.fr</code>.
+
+<dl>
+
+<dt><code>INSTANCE <i>( class metaclass "name" -- instance class )</i></code><dd>
+
+
+
+Create an uninitialized instance of the class, giving it the name specified.
+The method leaves the instance's signature on the stack (handy if you
+want to initialize). Example:
+
+<pre>
+C_REF --> INSTANCE UNINIT-REF 2DROP
+</pre>
+
+<dt><code>NEW <i>( class metaclass "name" -- )</i></code><dd>
+
+
+
+Create an initialized instance of class, giving it the name specified.
+This method calls <code>INIT</code> to perform initialization.
+
+<dt><code>ARRAY <i>( nObjects class metaclass "name" -- nObjects instance class )</i></code><dd>
+
+
+
+Create an array of <code>nObjects</code> instances of the specified class.
+Instances are not initialized. Example:
+
+<pre>
+10 C_4BYTE --> ARRAY 40-RAW-BYTES 2DROP DROP
+</pre>
+
+
+<dt><code>NEW-ARRAY <i>( nObjects class metaclass "name" -- )</i></code><dd>
+
+
+
+Creates an initialized array of <code>nObjects</code> instances of the class.
+Same syntax as <code>ARRAY</code>.
+
+<a NAME="alloc"></a>
+<dt><code>ALLOC <i>( class metaclass -- instance class )</i></code><dd>
+
+
+
+Creates an anonymous instance of <code>CLASS</code> from the heap (using a call
+to <code>ficlMalloc()</code> to get the memory). Leaves the payload and class addresses
+on the stack. Usage example:
+
+<pre>
+C-REF --> ALLOC 2CONSTANT INSTANCE-OF-REF
+</pre>
+<p>
+
+Creates a double-cell constant that pushes the payload and class address
+of a heap instance of <code>C-REF</code>.
+
+<a NAME="allocarray"></a>
+<dt><code>ALLOC-ARRAY <i>( nObjects class metaclass -- instance class )</i></code><dd>
+
+
+
+Same as <code>NEW-ARRAY</code>, but creates anonymous instances from the heap using
+a call to <code>ficlMalloc()</code>. Each instance is initialized using the class's
+<code>INIT</code> method.
+
+<a NAME="allot"></a>
+<dt><code>ALLOT <i>( class metaclass -- instance class )</i></code><dd>
+
+
+
+Creates an anonymous instance of <code>CLASS</code> from the dictionary. Leaves
+the payload and class addresses on the stack. Usage example:
+
+<pre>
+C-REF --> ALLOT 2CONSTANT INSTANCE-OF-REF
+</pre>
+
+<p>
+
+Creates a double-cell constant that pushes the payload and class address
+of a heap instance of <code>C-REF</code>.
+
+<a NAME="allotarray"></a>
+<dt><code>ALLOT-ARRAY <i>( nObjects class metaclass -- instance class )</i></code><dd>
+
+
+
+Same as <code>NEW-ARRAY</code>, but creates anonymous instances from the dictionary.
+Each instance is initialized using the class's <code>INIT</code> method.
+
+<dt><code>REF <i>( instance-address class metaclass "name" -- )</i></code><dd>
+
+
+
+Make a ref instance of the class that points to the supplied instance address.
+No new instance space is allotted. Instead, the instance refers to the
+address supplied on the stack forever afterward. For wrapping existing
+structures.
+
+
+<dt><code>SUB <i>( class metaclass -- old-wid address[size] size )</i></code><dd>
+
+
+
+Derive a subclass. You can add or override methods, and add instance variables.
+Alias: <code>SUBCLASS</code>. Examples:
+<p>
+
+<pre>
+C_4BYTE --> SUB C_SPECIAL4BYTE
+ ( <i>... your new methods and instance variables here ...</i> )
+END-CLASS
+</pre>
+
+or
+
+<pre>
+C_4BYTE SUBCLASS C_SPECIAL4BYTE
+ ( <i>... your new methods and instance variables here ...</i> )
+END-CLASS
+</pre>
+
+<dt><code>.SIZE <i>( class metaclass -- instance-size )</i></code><dd>
+
+
+
+Returns address of the class's instance size field, in address units. This
+is a metaclass member variable.
+
+<dt><code>.SUPER <i>( class metaclass -- superclass )</i></code><dd>
+
+
+
+Returns address of the class's superclass field. This is a metaclass member
+variable.
+
+<dt><code>.WID <i>( class metaclass -- wid )</i></code><dd>
+
+
+
+Returns the address of the class's wordlist ID field. This is a metaclass
+member variable.
+
+<dt><code>GET-SIZE <i>( -- instance-size )</i></code><dd>
+
+
+
+Returns the size of an instance of the class in address units. Imeplemented
+as follows:
+
+<pre>
+: GET-SIZE METACLASS => .SIZE @ ;
+</pre>
+
+<dt><code>GET-WID <i>( -- wid )</i></code><dd>
+
+
+
+Returns the wordlist ID of the class. Implemented as:
+
+<pre>
+: GET-WID METACLASS => .WID @ ;
+</pre>
+
+<dt><code>GET-SUPER <i>( -- superclass )</i></code><dd>
+
+
+
+Returns the class's superclass. Implemented as
+
+<pre>
+: GET-SUPER METACLASS => .super @ ;
+</pre>
+
+
+<dt><code>ID <i>( class metaclass -- c-address u )</i></code><dd>
+
+
+
+Returns the address and length of a string that names the class.
+
+
+<dt><code>METHODS <i>( class metaclass -- )</i></code><dd>
+
+
+
+Lists methods of the class and all its superclasses.
+
+
+<dt><code>OFFSET-OF <i>( class metaclass "name" -- offset )</i></code><dd>
+
+
+
+Pushes the offset from the instance base address of the named member variable.
+If the name is not that of an instance variable method, you get garbage.
+There is presently no way to detect this error. Example:
+
+<pre>
+metaclass --> offset-of .wid
+</pre>
+
+
+<dt><code>PEDIGREE <i>( class metaclass -- )</i></code><dd>
+
+
+
+
+Lists the pedigree of the class (inheritance trail).
+
+<dt><code>SEE <i>( class metaclass "name" -- )</i></code><dd>
+
+
+
+Decompiles the specified method&mdash;obect version of <code>SEE</code>, from the
+<code>TOOLS</code> wordset.
+
+</dl>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='codeOBJECT/codeBase-ClassMethodsGlossary'>
+<code>OBJECT</code> Base-Class Methods Glossary
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<a NAME="objectgloss"></a>
+
+These are methods that are defined for all instances by the base class
+<code>OBJECT</code>.
+The methods include default initialization, array manipulations, aliases
+of class methods, upcasting, and programming tools.
+
+<dl>
+
+<dt><code>INIT <i>( instance class -- )</i></code><dd>
+
+
+
+Default initializer, called automatically for all instances created with
+<code>NEW</code>
+or <code>NEW-ARRAY</code>. Zero-fills the instance. You do not normally need
+to invoke <code>INIT</code> explicitly.
+
+<dt><code>ARRAYINIT <i>( nObjects instance class -- )</i></code><dd>
+
+
+
+Applies <code>INIT</code> to an array of objects created by <code>NEW-ARRAY</code>.
+Note that <code>ARRAY:</code> does not cause aggregate arrays to be initialized
+automatically. You do not normally need to invoke <code>ARRAY-INIT</code> explicitly.
+
+<dt><code>FREE <i>( instance class -- )</i></code><dd>
+
+
+
+Releases memory used by an instance previously created with <code>ALLOC</code>
+or <code>ALLOC-ARRAY</code>. <b>Note:</b> This method is not presently protected
+against accidentally deleting something from the dictionary. If you do
+this, Bad Things are likely to happen. Be careful for the moment to apply
+free only to instances created with <code>ALLOC</code> or <code>ALLOC-ARRAY</code>.
+
+<dt><code>CLASS <i>( instance class -- class metaclass )</i></code><dd>
+
+
+
+Convert an object signature into that of its class. Useful for calling
+class methods that have no object aliases.
+
+<dt><code>SUPER <i>( instance class -- instance superclass )</i></code><dd>
+
+
+
+Upcast an object to its parent class. The parent class of <code>OBJECT</code>
+is zero. Useful for invoking an overridden parent class method.
+
+<dt><code>PEDIGREE <i>( instance class -- )</i></code><dd>
+
+
+
+Display an object's pedigree&mdash;its chain of inheritance. This is an alias
+for the corresponding class method.
+
+<dt><code>SIZE <i>( instance class -- instance-size )</i></code><dd>
+
+
+
+Returns the size, in address units, of one instance. Does not know about
+arrays! This is an alias for the class method <code>GET-SIZE</code>.
+
+<dt><code>METHODS <i>( instance class -- )</i></code><dd>
+
+
+
+Class method alias. Displays the list of methods of the class and all superclasses
+of the instance.
+
+<dt><code>INDEX <i>( n instance class -- instance[n] class )</i></code><dd>
+
+
+
+Convert array-of-objects base signature into signature for array element
+n. No check for bounds overflow. Index is zero-based, like C, so
+
+<pre>
+0 MY-OBJ --> INDEX
+</pre>
+
+is equivalent to
+
+<pre>
+MY-OBJ
+</pre>
+
+Check out the <a href="#minusrot">description of <code>-ROT</code></a> for
+help in dealing with indices on the stack.
+
+<dt><code>NEXT <i>( instance[n] class -- instance[n+1] )</i></code><dd>
+
+
+
+Convert an array-object signature into the signature of the next
+object in the array. No check for bounds overflow.
+
+<dt><code>PREV <i>( instance[n] class -- instance[n-1] class )</i></code><dd>
+
+
+
+Convert an object signature into the signature of the previous object
+in the array. No check for bounds underflow.
+
+</dl>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='SuppliedClasses'>
+Supplied Classes
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<a NAME="stockclasses"></a>
+
+For more information on theses classes, see <code>softcore/classes.fr</code>.
+
+<dl>
+
+<dt><code>METACLASS <i></i></code><dd>
+
+
+
+Describes all classes of Ficl. Contains class methods. Should never be
+directly instantiated or subclassed. Defined in <code>softcore/oo.fr</code>. Methods described
+above.
+
+<dt><code>OBJECT <i></i></code><dd>
+
+
+
+Mother of all Ficl objects. Defines default initialization and array indexing
+methods. Defined in <code>softcore/oo.fr</code>. Methods described above.
+
+<dt><code>C-REF <i></i></code><dd>
+
+
+
+Holds the signature of another object. Aggregate one of these into a data
+structure or container class to get polymorphic behavior. Methods and members:
+
+<dl>
+
+<dt><code>GET <i>( instance class -- ref-instance ref-class )</i></code><dd>
+
+
+Push the referenced object value on the stack.
+
+<dt><code>SET <i>( ref-instance ref-class instance class -- )</i></code><dd>
+
+
+Set the referenced object being held.
+
+<dt><code>.INSTANCE <i>( instance class -- a-address )</i></code><dd>
+
+
+Cell member that holds the instance.
+
+<dt><code>.CLASS <i>( instance class -- a-address )</i></code><dd>
+
+
+Cell member that holds the class.
+
+</dl>
+
+<dt><code>C-BYTE <i></i></code><dd>
+
+
+
+Primitive class derived from <code>OBJECT</code>, with a 1-byte payload. <code>SET</code>
+and <code>GET</code> methods perform correct width fetch and store. Methods and members:
+
+<dl>
+
+<dt><code>GET <i>( instance class -- byte )</i></code><dd>
+
+
+Push the object's value on the stack.
+
+<dt><code>SET <i>( byte instance class -- )</i></code><dd>
+
+
+Set the object's value from the stack.
+
+<dt><code>.PAYLOAD <i>( instance class -- address )</i></code><dd>
+
+
+Member holds instance's value.
+
+</dl>
+
+<dt><code>C-2BYTE <i></i></code><dd>
+
+
+
+Primitive class derived from <code>OBJECT</code>, with a 2-byte payload. <code>SET</code>
+and <code>GET</code> methods perform correct width fetch and store. Methods and members:
+
+<dl>
+
+<dt><code>GET <i>( instance class -- 2byte )</i></code><dd>
+
+
+Push the object's value on the stack.
+
+<dt><code>SET <i>( 2byte instance class -- )</i></code><dd>
+
+
+Set the object's value from the stack.
+
+<dt><code>.PAYLOAD <i>( instance class -- address )</i></code><dd>
+
+
+Member holds instance's value.
+
+</dl>
+
+<dt><code>C-4BYTE <i></i></code><dd>
+
+
+Primitive class derived from <code>object</code>, with a 4-byte payload. <code>SET</code>
+and <code>GET</code> methods perform correct width fetch and store. Methods and members:
+
+<dl>
+
+<dt><code>GET <i>( instance class -- 4byte )</i></code><dd>
+
+
+Push the object's value on the stack.
+
+<dt><code>SET <i>( 4byte instance class -- )</i></code><dd>
+
+
+Set the object's value from the stack.
+
+<dt><code>.PAYLOAD <i>( instance class -- address )</i></code><dd>
+
+
+Member holds instance's value.
+
+</dl>
+
+<dt><code>C-CELL <i></i></code><dd>
+
+
+
+Primitive class derived from <code>OBJECT</code>, with a cell payload (equivalent
+to <code>C-4BYTE</code> on 32 bit platforms, 64 bits wide on Alpha and other
+64-bit platforms). <code>SET</code>
+and <code>GET</code> methods perform correct width fetch and store. Methods and members:
+
+<dl>
+
+<dt><code>GET <i>( instance class -- 4byte )</i></code><dd>
+
+
+Push the object's value on the stack.
+
+<dt><code>SET <i>( 4byte instance class -- )</i></code><dd>
+
+
+Set the object's value from the stack.
+
+<dt><code>.PAYLOAD <i>( instance class -- address )</i></code><dd>
+
+
+Member holds instance's value.
+
+</dl>
+
+<dt><code>C-PTR <i></i></code><dd>
+
+
+
+Base class derived from <code>OBJECT</code> for pointers to non-object types.
+This class is not complete by itself: several methods depend on a derived
+class definition of <code>@SIZE</code>. Methods and members:
+
+<dl>
+
+<dt><code>.ADDR <i>( instance class -- a-address )</i></code><dd>
+
+
+Member variable, holds the pointer address.
+
+<dt><code>GET-PTR <i>( instance class -- pointer )</i></code><dd>
+
+
+Pushes the pointer address.
+
+<dt><code>SET-PTR <i>( pointer instance class -- )</i></code><dd>
+
+
+Sets the pointer address.
+
+<dt><code>INC-PTR <i>( instance class -- )</i></code><dd>
+
+
+Adds <code>@SIZE</code> to the pointer address.
+
+<dt><code>DEC-PTR <i>( instance class -- )</i></code><dd>
+
+
+Subtracts <code>@SIZE</code> to the pointer address.
+
+<dt><code>INDEX-PTR <i>( i instance class -- )</i></code><dd>
+
+
+Adds <code>i * @SIZE</code> to the pointer address.
+
+</dl>
+
+<dt><code>C-BYTEPTR <i></i></code><dd>
+
+
+
+Pointer to byte derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<dt><code>@SIZE <i>( instance class -- size )</i></code><dd>
+
+
+Push size of the pointed-to object.
+
+<dt><code>GET <i>( instance class -- byte )</i></code><dd>
+
+
+Pushes the pointer's referent byte.
+
+<dt><code>SET <i>( byte instance class -- )</i></code><dd>
+
+
+Stores <code>byte</code> at the pointer address.
+
+</dl>
+
+
+
+<dt><code>C-2BYTEPTR <i></i></code><dd>
+
+
+
+Pointer to 2byte derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<dt><code>@SIZE <i>( instance class -- size )</i></code><dd>
+
+
+Push size of the pointed-to object.
+
+<dt><code>GET <i>( instance class -- 2byte )</i></code><dd>
+
+
+Pushes the pointer's referent 2byte.
+
+<dt><code>SET <i>( 2byte instance class -- )</i></code><dd>
+
+
+Stores <code>2byte</code> at the pointer address.
+
+</dl>
+
+
+
+<dt><code>C-4BYTEPTR <i></i></code><dd>
+
+
+
+Pointer to 4byte derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<dt><code>@SIZE <i>( instance class -- size )</i></code><dd>
+
+
+Push size of the pointed-to object.
+
+<dt><code>GET <i>( instance class -- 4byte )</i></code><dd>
+
+
+Pushes the pointer's referent 4byte.
+
+<dt><code>SET <i>( 4byte instance class -- )</i></code><dd>
+
+
+Stores <code>4byte</code> at the pointer address.
+
+</dl>
+
+
+<dt><code>C-CELLPTR <i></i></code><dd>
+
+
+
+Pointer to cell derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<dt><code>@SIZE <i>( instance class -- size )</i></code><dd>
+
+
+Push size of the pointed-to object.
+
+<dt><code>GET <i>( instance class -- cell )</i></code><dd>
+
+
+Pushes the pointer's referent cell.
+
+<dt><code>SET <i>( cell instance class -- )</i></code><dd>
+
+
+Stores <code>cell</code> at the pointer address.
+
+</dl>
+
+
+
+<dt><code>C-STRING <i></i></code><dd>
+
+
+
+Dynamically allocated string, similar to MFC's <code>CString</code>.
+For more information, see <code>softcore/string.fr</code>.
+Partial list of methods and members:
+
+<dl>
+
+<dt><code>GET <i>( instance class -- c-address u )</i></code><dd>
+
+
+Pushes the string buffer's contents as a <code>C-ADDR U</code> style string.
+
+<dt><code>SET <i>( c-address u instance class -- )</i></code><dd>
+
+
+Sets the string buffer's contents to a new value.
+
+<dt><code>CAT <i>( c-address u instance class -- )</i></code><dd>
+
+
+Concatenates a string to the string buffer's contents.
+
+<dt><code>COMPARE <i>( c-address u instance class -- result )</i></code><dd>
+
+
+Lexical compiration of a string to the string buffer's contents.
+Return value is the same as the FORTH function <code>COMPARE</code>.
+
+<dt><code>TYPE <i>( instance class -- )</i></code><dd>
+
+
+Prints the contents of the string buffer to the output stream.
+
+<dt><code>HASHCODE <i>( instance class -- i )</i></code><dd>
+
+
+Returns a computed hash based on the contents of the string buffer.
+
+<dt><code>FREE <i>( instance class -- )</i></code><dd>
+
+
+Releases the internal buffer.
+
+</dl>
+
+
+<dt><code>C-HASHSTRING <i></i></code><dd>
+
+
+
+Subclass of <code>C-STRING</code>, which adds a member variable to store a hashcode.
+For more information, see <code>softcore/string.fr</code>.
+
+</dl>
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/parsesteps.html b/doc/parsesteps.html
new file mode 100644
index 000000000000..522ae656d638
--- /dev/null
+++ b/doc/parsesteps.html
@@ -0,0 +1,388 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl parse steps</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl parse steps
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='ParseSteps'>
+Parse Steps
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Unlike every other FORTH we know of, Ficl features an <i>extensible
+parser chain</i>. The Ficl parser is not a monolithic function; instead,
+it is comprised of a simple tokenizer and a series of <i>parse steps</i>.
+A parse step is a step in the parser chain that handles a particular kind
+of token, acting on the token as appropriate. Example parse steps, in
+terms of traditional FORTH lore, would be the "number runner" and the
+"colon compiler".
+<p>
+
+The Ficl parser works like this:
+<ol>
+
+<li>
+Read in a new <i>token</i> (string of text with no internal whitespace).
+
+<li>
+For each parse step in the chain, call the parse step, passing in the token.
+If the parse step returns <code>FICL_TRUE</code>, that parse step must have
+handled the token appropriately; move on to the next token.
+
+<li>
+If the parser tries all the parse steps and none of them return
+<code>FICL_TRUE</code>, the token is illegal&mdash;print an error
+and reset the virtual machine.
+
+</ol>
+
+Parse steps can be written as native functions, or as Ficl script functions.
+New parse steps can be appended to the chain at any time.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='TheDefaultFiclParseChain'>
+The Default Ficl Parse Chain
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+These is the default Ficl parser chain, shown in order.
+
+<dl>
+
+<dt>
+<code>?word</code>
+<dd>
+
+
+
+If compiling and local variable support is enabled, attempt to find the token in the local
+variable dictionary. If found, execute the token's compilation semantics and return <code>FICL_TRUE</code>.
+<p>
+
+Attempt to find the token in the system dictionary. If found, execute the token's semantics
+(may be different when compiling than when interpreting) and return <code>FICL_TRUE</code>.
+
+<dt>
+<code>?prefix</code>
+<dd>
+
+
+This parse step is only active if prefix support is enabled, setting <code>FICL_WANT_PREFIX</code>
+in <code>ficl.h</code> to a non-zero value.
+Attempt to match the beginning of the token to the list of known prefixes. If there's a match,
+execute the associated prefix method and return <code>FICL_TRUE</code>.
+
+<dt>
+<code>?number</code>
+<dd>
+
+
+Attempt to convert the token to a number in the present <code>BASE</code>. If successful, push the
+value onto the stack if interpreting, otherwise compile it, then return <code>FICL_TRUE</code>.
+
+<dt>
+<code>?float</code>
+<dd>
+
+
+This parse step is only active if floating-point number support is enabled,
+setting <code>FICL_WANT_FLOAT</code> in <code>ficl.h</code> to a non-zero value.
+Attempt to convert the token to a floating-point number. If successful, push the
+value onto the floating-point stack if interpreting, otherwise compile it,
+then return <code>FICL_TRUE</code>.
+
+</dl>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='AddingAParseStepFromWithinFicl'>
+Adding A Parse Step From Within Ficl
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<a name=ficlparsestep></a>
+
+You can add a parse step in two ways. The first is to write a Ficl word that
+has the correct stack signature for a parse step:
+<pre>
+<i>MY-PARSE-STEP</i> ( c-addr u -- x*i flag )
+</pre>
+where <code>c-addr u</code> are the address and length of the incoming token,
+and <code>flag</code> is <code>FICL_TRUE</code> if the parse step processed
+the token and <code>FICL_FALSE</code> otherwise.
+<p>
+
+Install the parse step using <code>add-parse-step</code>.
+A trivial example:
+<pre>
+: ?silly ( c-addr u -- flag )
+ ." Oh no! Not another " type cr true ;
+' ?silly add-parse-step
+parse-order
+</pre>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#b8b8b8 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=4><b><i>
+<a name='AddingANativeParseStep'>
+Adding A Native Parse Step
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+The other way to add a parse step is to write it in C and add it into the
+parse chain with the following function:
+
+<pre>
+void ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name, ficlParseStep step);
+</pre>
+
+<code>name</code> is the display name of the parse step in the parse chain
+(as displayed by the Ficl word <code>PARSE-ORDER</code>). <code>step</code>
+is a pointer to the code for the parse step itself,
+and must match the following declaration:
+<pre>
+typedef int (*ficlParseStep)(ficlVm *vm, ficlString s);
+</pre>
+<p>
+
+When a native parse step is run, <code>si</code> points to the incoming token.
+The parse step must return <code>FICL_TRUE</code> if it succeeds in handling the
+token, and <code>FICL_FALSE</code> otherwise.
+See <code>ficlVmParseNumber()</code> in <code>system.c</code> for an example.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Prefixes'>
+Prefixes
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+What's a prefix, anyway? A prefix (contributed by Larry Hastings) is a token that's
+recognized as the beginning of another token. Its presence modifies the semantics of
+the rest of the token. An example is <code>0x</code>, which causes digits following
+it to be converted to hex regardless of the current value of <code>BASE</code>.
+<p>
+
+Caveat: Prefixes are matched in sequence, so the more of them there are,
+the slower the interpreter gets. On the other hand, because the prefix
+parse step occurs immediately after the dictionary lookup step, if you
+have a prefix for a particular purpose, using it may save time since it
+stops the parse process. Also, the Ficl interpreter is wonderfully fast,
+and most interpretation only happens once, so it's likely you won't notice
+any change in interpreter speed even if you make heavy use of prefixes.
+<p>
+
+Each prefix is a Ficl word stored in a special wordlist called <code>&lt;PREFIXES&gt;</code>. When the
+prefix parse step (<code>?prefix</code>, implemented in C as <code>ficlVmParsePrefix()</code>) is
+executed, it searches each word in <code>&lt;PREFIXES&gt;</code> in turn, comparing it with the
+initial characters of the incoming token. If a prefix matches, the parse step returns the remainder
+of the token to the input stream and executes the code associated with the prefix. This code can be
+anything you like, but it would typically do something with the remainder of the token. If the prefix
+code does not consume the rest of the token, it will go through the parse process again (which may
+be what you want).
+<p>
+
+Prefixes are defined in <code>prefix.c</code> and in <code>softcore/prefix.fr</code>.
+The best way to add prefixes is by defining them in your own code, bracketed with the special
+words <code>START-PREFIXES</code> and <code>END-PREFIXES</code>. For example, the following
+code would make <code>.(</code> a prefix.
+
+<pre>
+start-prefixes
+: .( .( ;
+end-prefixes
+</pre>
+<p>
+
+The compile-time constant <code>FICL_EXTENDED_PREFIX</code> controls the inclusion of
+several additional prefixes. This is turned off in the default build, since several
+of these prefixes alter standard behavior, but you might like them.
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Notes'>
+Notes
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+
+<li>
+Prefixes and parser extensions are non-standard. However, with the exception of
+prefix support, Ficl's default parse order follows the standard.
+Inserting parse steps in some other order will almost certainly break standard behavior.
+<p>
+
+<li>
+The number of parse steps that can be added to the system is limited by the value of
+<code>FICL_MAX_PARSE_STEPS</code> (defined in <code>sysdep.h</code>). The default
+maximum number is 8.
+<p>
+
+<li>
+The compile-time constant <code>FICL_EXTENDED_PREFIX</code> controls the inclusion of
+several additional prefixes. This is turned off in the default build, since several
+of these prefixes alter standard behavior, but you might like them.
+<p>
+
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='ParserGlossary'>
+Parser Glossary
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<dl>
+
+<dt>
+<code>PARSE-ORDER ( -- )</code>
+<dd>
+
+
+
+Prints the list of parse steps, in the order in which they are called.
+
+<dt>
+<code>ADD-PARSE-STEP ( xt -- )</code>
+<dd>
+
+
+
+Appends a parse step to the parse chain. <code>xt</code> is the address
+(execution token) of a Ficl word to use as the parse step. The word must be a
+legal Ficl parse step (<a href=#ficlparsestep>see above</a>).
+
+<dt>
+<code>SHOW-PREFIXES ( -- )</code>
+<dd>
+
+
+
+Prints the list of all prefixes. Each prefix is a Ficl word that is executed if its name
+is found at the beginning of a token.
+
+<dt>
+<code>START-PREFIXES ( -- )</code>
+<dd>
+
+
+
+Declares the beginning of a series of prefix definitions.
+Should be followed, eventually, by <code>END-PREFIXES</code>.
+(All <code>START-PREFIXES</code> does is tell the Ficl virtual machine
+to compile into the <code>&lt;PREFIXES&gt;</code> wordlist.)
+
+<dt>
+<code>END-PREFIXES ( -- )</code>
+<dd>
+
+
+
+Declares the end of a series of prefix definitions.
+Should only be used after calling <code>START-PREFIXES</code>.
+(All <code>END-PREFIXES</code> does is tell the Ficl virtual machine
+to switch back to the wordlist that was in use before <code>START-PREFIXES</code> was called.)
+
+</dl>
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
diff --git a/doc/primer.txt b/doc/primer.txt
deleted file mode 100644
index 7de5214dd379..000000000000
--- a/doc/primer.txt
+++ /dev/null
@@ -1,1164 +0,0 @@
- A Beginner's Guide to Forth
-
- by
-
- J.V. Noble
-
- Contents
-
- 0. Preliminaries
-
-
- 1. Getting started
-
- The structure of Forth
-
- 2. Extending the dictionary
-
- 3. Stacks and reverse Polish notation (RPN)
- 3.1 Manipulating the parameter stack
- 3.2 The return stack and its uses
-
- 4. Fetching and storing
-
- 5. Comparing and branching
-
- 6. Documenting and commenting Forth code
-
- 7. Arithmetic operations
-
- 8. Looping and structured programming
-
- 9. CREATE ... DOES> (the pearl of Forth)
- 9.1 Defining "defining" words
- 9.2 Run-time vs. compile-time actions
- 9.3 Dimensioned data (intrinsic units)
- 9.4 Advanced uses of the compiler
-
- 10. Floating point arithmetic
-
-
-
- 0. Introduction
-
- Forth is an unusual computer language that has probably been applied
- to more varied projects than any other. It is the obvious choice when
- the project is exceptionally demanding in terms of completion sched-
- ule, speed of execution, compactness of code, or any combination of
- the above.
-
- It has also been called "...one of the best-kept secrets in the com-
- puting world." This is no exaggeration: large corporations have pur-
- chased professional Forth development systems from vendors such as
- Laboratory Microsystems, Inc., Forth, Inc. or MicroProcessor Engineer-
- ing, Ltd. and sworn them to secrecy.
-
- Some speculate (unkindly) that corporate giants prefer to hide their
- shame at using Forth; but I believe they are actually concealing a
- secret weapon from their rivals. Whenever Forth has competed directly
- with a more conventional language like C it has won hands down, pro-
- ducing smaller, faster, more reliable code in far less time. I have
- searched for examples with the opposite outcome, but have been unable
- to find a single instance.
-
-
-
- 1. Getting started
-
- We will use Win32Forth for these illustrations. Download the file
-
- w32for35.exe
-
- and double-click on it to install on any Windows 95-equipped machine.
-
-
- The compressed files will then decompress themselves. They should also
- install a program group on your desktop.
-
- Now start Win32Forth by opening the program group and clicking on the
- appropriate icon.
-
-
- It should respond by opening a window and writing something like
-
- 32bit Forth for Windows 95, and NT
- Compiled: July 23rd, 1997, 5:11pm
- Version: 3.5 Build: 0008 Release Build
- Platform: Windows 95 Version: 4.0 Build: 16384
- 491k bytes free
- 2,719 Words in Application dictionary
- 1,466 Words in System dictionary
- 4,185 Words total in dictionaries
- 8,293 Windows Constants available
-
- Loading Win32For.CFG
-
- *** DON'T PANIC, Press: F1 NOW! ***
-
-
- Win32Forth is case-insensitive.
-
-
- Now type
-
- BYE <cr>.
-
- The Win32Forth window immediately closes.
-
-
- What just happened? Forth is an interactive programming language con-
- sisting entirely of subroutines, called "words".
-
- A word is executed (interactively) by naming it. We have just seen
- this happen: BYE is a Forth subroutine meaning "exit to the operating
- system". So when we entered BYE it was executed, and the system re-
- turned control to Windows.
-
-
- Click on the Win32Forth icon again to re-start Forth.
- Now we will try something a little more complicated. Enter
-
- 2 17 + . <cr> 19 ok
-
- What happened? Forth is interpretive. An "outer interpreter" continu-
- ally loops, waiting for input from the keyboard or mass storage de-
- vice. The input is a sequence of text strings separated from each
- other by blank spaces --ASCII 32decimal = 20hex-- the standard Forth
- delimiter.
-
- When the outer interpreter encounters text it first looks for it in
- the "dictionary" (a linked list of previously defined subroutine
- names). If it finds the word, it executes the corresponding code.
-
- If no dictionary entry exists, the interpreter tries to read the input
- as a number.
-
- If the input text string satisfies the rules defining a number, it is
- converted to a number and stored in a special memory location called
- "the top of the stack" (TOS).
-
-
- In the above example, Forth interpreted 2 and 17 as numbers, and
- pushed them both onto the stack.
-
- "+" is a pre-defined word as is ".", so they were looked up and exe-
- cuted.
-
- "+" added 2 to 17 and left 19 on the stack.
-
- The word "." (called "emit") removed 19 from the stack and displayed
- it on the standard output device (in this case, CRT).
-
-
- We might also have said
-
- HEX 0A 14 * . <cr> C8 ok
-
- (Do you understand this? Hint: DECIMAL means "switch to decimal arith-
- metic", whereas HEX stands for "switch to hexadecimal arithmetic".)
-
- If the incoming text can neither be located in the dictionary nor in-
- terpreted as a number, Forth issues an error message. Try it: say X
- and see
-
- X
- Error: X is undefined
-
- or say THING and see
-
- THING
- Error: THING is undefined
-
-
-
- 2. Extending the dictionary
-
- The compiler is one of Forth's most endearing features. Unlike
- all other high-level languages, the Forth compiler is part of the
- language. (LISP and its dialects also make components of the com-
- pilation mechanism available to the programmer.) That is, its com-
- ponents are Forth words available to the programmer, that can be
- used to solve his problems.
-
- In this section we discuss how the compiler extends the
- dictionary.
-
- Forth uses special words to create new dictionary entries, i.e.,
- new words. The most important are ":" ("start a new definition")
- and ";" ("terminate the definition").
-
- Let's try this out: enter
-
- : *+ * + ; <cr> ok
-
- What happened? The word ":" was executed because it was already
- in the dictionary. The action of ":" is
-
- > Create a new dictionary entry named "*+" and switch from
- interpret to compile mode.
-
- > In compile mode, the interpreter looks up words and
- --rather than executing them-- installs pointers to
- their code. (If the text is a number, rather than
- pushing it on the stack, Forth builds the number
- into the dictionary space allotted for the new word,
- following special code that puts it on the stack
- when the word is executed.)
-
- > The action of "*+" will be to execute sequentially
- the previously-defined words "*" and "+".
-
- > The word ";" is special: when it was defined a bit
- was turned on in its dictionary entry to mark it as
- IMMEDIATE. Thus, rather than writing down its
- address, the compiler executes ";" immediately. The
- action of ";" is first, to install the code that
- returns control to the next outer level of the
- interpreter; and second, to switch back from compile
- mode to interpret mode.
-
- Now try out "*+" :
-
- DECIMAL 5 6 7 *+ . <cr> 47 ok
-
- This example illustrated two principles of Forth: adding a new word to
- the dictionary, and trying it out as soon as it was defined.
-
-
-
- 3. Stacks and reverse Polish notation (RPN)
-
- We now discuss the stack and the "reverse Polish" or "postfix" arith-
- metic based on it. (Anyone who has used a Hewlett-Packard calculator
- should be familiar with the concept.)
-
- Virtually all modern CPU's are designed around stacks. Forth effi-
- ciently uses its CPU by reflecting this underlying stack architecture
- in its syntax.
-
-
- But what is a stack? As the name implies, a stack is the machine ana-
- log of a pile of cards with numbers written on them. Numbers are
- always added to the top of the pile, and removed from the top of the
- pile. The Forth input line
-
- 2 5 73 -16 <cr> ok
-
- leaves the stack in the state
-
- cell # contents
-
-
- 0 -16 (TOS)
-
- 1 73 (NOS)
-
- 2 5
-
- 3 2
-
-
- where TOS stands for "top-of-stack", NOS for "next-on-stack", etc.
-
- We usually employ zero-based relative numbering in Forth data struct-
- ures (such as stacks, arrays, tables, etc.) so TOS is given relative
- #0, NOS #1, etc.
-
- Suppose we followed the above input line with the line
-
- + - * . <cr> xxx ok
-
- what would xxx be? The operations would produce the successive stacks
-
- cell# initial + - * .
-
- 0 -16 57 -52 -104
- 1 73 5 2
- 2 5 2
- 3 2 empty
- stack
-
- The operation "." (EMIT) displays -104 to the screen, leaving the
- stack empty. That is, xxx is -104.
-
-
- 3.1 Manipulating the parameter stack
-
- Forth systems incorporate (at least) two stacks: the parameter stack
- and the return stack.
-
- A stack-based system must provide ways to put numbers on the stack, to
- remove them, and to rearrange their order. Forth includes standard
- words for this purpose.
-
- Putting numbers on the stack is easy: simply type the number (or in-
- corporate it in the definition of a Forth word).
-
- The word DROP removes the number from TOS and moves up all the other
- numbers. (Since the stack usually grows downward in memory, DROP mere-
- ly increments the pointer to TOS by 1 cell.)
-
- SWAP exchanges the top 2 numbers.
-
- DUP duplicates the TOS into NOS.
-
- ROT rotates the top 3 numbers.
-
-
- These actions are shown below (we show what each word does to the ini-
- tial stack)
-
- cell | initial | DROP SWAP ROT DUP
-
- 0 | -16 | 73 73 5 -16
- 1 | 73 | 5 -16 -16 -16
- 2 | 5 | 2 5 73 73
- 3 | 2 | 2 2 5
- 4 | | 2
-
-
- Forth includes the words OVER, TUCK, PICK and ROLL that act as shown
- below (note PICK and ROLL must be preceded by an integer that says
- where on the stack an element gets PICK'ed or ROLL'ed):
-
- cell | initial | OVER TUCK 4 PICK 4 ROLL
-
- 0 | -16 | 73 -16 2 2
- 1 | 73 | -16 73 -16 -16
- 2 | 5 | 73 -16 73 73
- 3 | 2 | 5 5 5 5
- 4 | | 2 2 2
-
- Clearly, 1 PICK is the same as DUP, 2 PICK is a synonym for OVER, and
- 2 ROLL means SWAP.
-
-
- 3.2 The return stack and its uses
-
- We have remarked above that compilation establishes links from the
- calling word to the previously-defined word being invoked. The linkage
- mechanism --during execution-- uses the return stack (rstack): the
- address of the next word to be invoked is placed on the rstack, so
- that when the current word is done executing, the system knows to jump
- to the next word. (This is so in most, but not all Forth implement-
- ations. But all have a return stack, whether or not they use them for
- linking subroutines.)
-
- In addition to serving as a reservoir of return addresses (since words
- can be nested, the return addresses need a stack to be put on) the
- rstack is where the limits of a DO...LOOP construct are placed.
-
- The user can also store/retrieve to/from the rstack. This is an ex-
- ample of using a component for a purpose other than the one it was
- designed for. Such use is discouraged for novices since it adds the
- spice of danger to programming. See "Note of caution" below.
-
- To store to the rstack we say >R , and to retrieve we say R> . The
- word R@ copies the top of the rstack to the TOS.
-
-
- Why use the rstack when we have a perfectly good parameter stack to
- play with? Sometimes it becomes hard to read code that performs com-
- plex gymnastics on the stack. The rstack can reduce the complexity.
-
- Alternatively, VARIABLEs --named locations-- provide a place to store
- numbers --such as intermediate results in a calculation-- off the
- stack, again reducing the gymnastics. Try this:
-
- \ YOU DO THIS \ EXPLANATION
-
- VARIABLE X <cr> ok \ create a named storage location X;
- \ X executes by leaving its address
-
- 3 X ! <cr> ok \ ! ("store") expects a number and
- \ an address, and stores the number to
- \ that address
-
- X @ . <cr> 3 ok \ @ ("fetch") expects an address, and
- \ places its contents in TOS.
-
- However, Forth encourages using as few named variables as possible.
- The reason: since VARIABLEs are typically global --any subroutine can
- access them-- they can cause unwanted interactions among parts of a
- large program.
-
- Although Forth can make variables local to the subroutines that use
- them (see "headerless words" in FTR), the rstack can often replace
- local variables:
-
- > The rstack already exists, so it need not be defined anew.
-
- > When the numbers placed on it are removed, the rstack shrinks,
- reclaiming some memory.
-
-
- A note of caution: since the rstack is critical to execution we mess
- with it at our peril. If we use the rstack for temporary storage we
- must restore it to its initial state. A word that places a number on
- the rstack must remove it --using R> or RDROP (if it has been defined)
- -- before exiting that word. Since DO...LOOP also uses the rstack,
- for each >R folowing DO there must be a corresponding R> or RDROP
- preceding LOOP. Neglecting these precautions will probably crash
- the system.
-
-
-
-
- 4. Fetching and storing
-
- As we just saw, ordinary numbers are fetched from memory to
- the stack by @ ("fetch"), and stored by ! (store).
-
- @ expects an address on the stack and replaces that address by
- its contents using, e.g., the phrase X @
-
- ! expects a number (NOS) and an address (TOS) to store it in, and
- places the number in the memory location referred to by the address,
- consuming both arguments in the process, as in the phrase 3 X !
-
- Double length numbers can similarly be fetched and stored, by
- D@ and D!, if the system has these words.
-
- Positive numbers smaller than 255 can be placed in single bytes of
- memory using C@ and C!. This is convenient for operations with strings
- of ASCII text, for example screen and keyboard I/O.
-
-
-
- 5. Comparing and branching
-
- Forth lets you compare two numbers on the stack, using relational
- operators ">", "<", "=" . Ths, e.g., the phrase
-
- 2 3 > <cr> ok
-
- leaves 0 ("false") on the stack, because 2 (NOS) is not greater than 3
- (TOS). Conversely, the phrase
-
- 2 3 < <cr> ok
-
- leaves -1 ("true") because 2 is less than 3.
-
- Notes: In some Forths "true" is +1 rather than -1.
-
- Relational operators consume both arguments and leave a "flag"
- to show what happened.
-
- (Many Forths offer unary relational operators "0=", "0>" and "0<".
- These, as might be guessed, determine whether the TOS contains an
- integer that is 0, positive or negative.)
-
- The relational words are used for branching and control. For example,
-
- : TEST CR 0 = NOT IF ." Not zero!" THEN ;
-
- 0 TEST <cr> ok ( no action)
- -14 TEST <cr>
- Not zero! ok
-
- The word CR issues a carriage return (newline). Then TOS is compared
- with zero, and the logical NOT operator (this flips "true" and
- "false") applied to the resulting flag. Finally, if TOS is non-zero,
- IF swallows the flag and executes all the words between itself and the
- terminating THEN. If TOS is zero, execution jumps to the word
- following THEN.
-
- The word ELSE is used in the IF...ELSE...THEN statement: a nonzero
- value in TOS causes any words between IF and ELSE to be executed, and
- words between ELSE and THEN to be skipped. A zero value produces the
- opposite behavior. Thus, e.g.
-
-
- : TRUTH CR 0 = IF ." false" ELSE ." true" THEN ;
-
- 1 TRUTH <cr>
- true ok
-
- 0 TRUTH <cr>
- false ok
-
- Since THEN is used to terminate an IF statement rather than in its
- usual sense, some Forth writers prefer the name ENDIF.
-
- 6. Documenting and commenting Forth code
-
- Forth is sometimes accused of being a "write-only" language, i.e. some
- complain that Forth is cryptic. This is really a complaint against
- poor documentation and untelegraphic word names. Unreadability is
- equally a flaw of poorly written FORTRAN, PASCAL, C, etc.
-
- Forth offers programmers who take the trouble tools for producing ex-
- ceptionally clear code.
-
-
- 6.1 Parenthesized remarks
-
- The word ( -- a left parenthesis followed by a space -- says "disre-
- gard all following text until the next right parenthesis in the
- input stream". Thus we can intersperse explanatory remarks within
- colon definitions.
-
-
- 6.2 Stack comments
-
- A particular form of parenthesized remark describes the effect of a
- word on the stack. In the example of a recursive loop (GCD below),
- stack comments are really all the documentation necessary.
-
- Glossaries generally explain the action of a word with a
- stack-effect comment. For example,
-
- ( adr -- n)
-
- describes the word @ ("fetch"): it says @ expects to find an address
- (adr) on the stack, and to leave its contents (n) upon completion.
- The corresponding comment for ! would be
-
- ( n adr -- ) .
-
-
-
- 6.3 Drop line (\)
-
- The word "\" (back-slash followed by space) has recently gained favor
- as a method for including longer comments. It simply means "drop ev-
- erything in the input stream until the next carriage return". Instruc-
- tions to the user, clarifications or usage examples are most naturally
- expressed in a block of text with each line set off by "\" .
-
-
- 6.4 Self-documenting code
-
- By eliminating ungrammatical phrases like CALL or GOSUB, Forth pre-
- sents the opportunity --via telegraphic names for words-- to make code
- almost as self-documenting and transparent as a readable English or
- German sentence. Thus, for example, a robot control program could con-
- tain a phrase like
-
- 2 TIMES LEFT EYE WINK
-
- which is clear (although it sounds like a stage direction for Brun-
- hilde to vamp Siegfried). It would even be possible without much dif-
- ficulty to define the words in the program so that the sequence could
- be made English-like: WINK LEFT EYE 2 TIMES .
-
-
-
-
- 7. Arithmetic operations
-
- The 1979 or 1983 standards require that a conforming Forth system con-
- tain a certain minimum set of pre-defined words. These consist of
- arithmetic operators + - * / MOD /MOD */ for (usually) 16-bit signed-
- integer (-32767 to +32767) arithmetic, and equivalents for unsigned (0
- to 65535), double-length and mixed-mode (16- mixed with 32-bit) arith-
- metic. The list will be found in the glossary accompanying your
- system, as well as in SF and FTR.
-
- Try this example of a non-trivial program that uses arithmetic and
- branching to compute the greatest common divisor of two integers using
- Euclid's algorithm:
-
- : TUCK ( a b -- b a b) SWAP OVER ;
- : GCD ( a b -- gcd) ?DUP IF TUCK MOD GCD THEN ;
-
- The word ?DUP duplicates TOS if it is not zero, and leaves it alone
- otherwise. If the TOS is 0, therefore, GCD consumes it and does
- nothing else. However, if TOS is unequal to 0, then GCD TUCKs TOS
- under NOS (to save it); then divides NOS by TOS, keeping the remainder
- (MOD). There are now two numbers left on the stack, so we again take
- the GCD of them. That is, GCD calls itself. However, if you try the
- above code it will fail. A dictionary entry cannot be looked up and
- found until the terminating ";" has completed it. So in fact we must
- use the word RECURSE to achieve self-reference, as in
-
- : TUCK ( a b -- b a b) SWAP OVER ;
- : GCD ( a b -- gcd) ?DUP IF TUCK MOD RECURSE THEN ;
-
- Now try
-
- 784 48 GCD . 16 ok
-
-
- 8. Looping and structured programming
-
- Forth has several ways to loop, including the implicit method of re-
- cursion, illustrated above. Recursion has a bad name as a looping
- method because in most languages that permit recursion, it imposes
- unacceptable running time overhead on the program. Worse, recursion
- can --for reasons beyond the scope of this Introduction to Forth-- be
- an extremely inefficient method of expressing the problem. In Forth,
- there is virtually no excess overhead in recursive calls because Forth
- uses the stack directly. So there is no reason not to recurse if that
- is the best way to program the algorithm. But for those times when
- recursion simply isn't enough, here are some more standard methods.
-
- 8.1 Indefinite loops
-
- The construct
-
- BEGIN xxx ( -- flag) UNTIL
-
- executes the words represented by xxx, leaving TOS (flag) set to TRUE
- --at which point UNTIL terminates the loop-- or to FALSE --at which
- point UNTIL jumps back to BEGIN. Try:
-
- : COUNTDOWN ( n --)
- BEGIN CR DUP . 1 - DUP 0 = UNTIL DROP ;
-
- 5 COUNTDOWN
- 5
- 4
- 3
- 2
- 1 ok
-
- A variant of BEGIN...UNTIL is
-
- BEGIN xxx ( -- flag) WHILE yyy REPEAT
-
- Here xxx is executed, WHILE tests the flag and if it is FALSE
- leaves the loop; if the flag is TRUE, yyy is executed; REPEAT then
- branches back to BEGIN.
-
- These forms can be used to set up loops that repeat until some
- external event (pressing a key at the keyboard, e.g.) sets the
- flag to exit the loop. They can also used to make endless loops
- (like the outer interpreter of Forth) by forcing the flag
- to be FALSE in a definition like
-
-
- : ENDLESS BEGIN xxx FALSE UNTIL ;
-
-
- 8.2 Definite loops
-
- Most Forths allow indexed loops using DO...LOOP (or +LOOP or /LOOP).
- These are permitted only within definitions
-
- : BY-ONES ( n --) 0 TUCK DO CR DUP . 1 + LOOP DROP ;
-
- The words CR DUP . 1 + will be executed n times as the lower
- limit, 0, increases in unit steps to n-1.
-
- To step by 2's, we use the phrase 2 +LOOP to replace LOOP, as with
-
- : BY-TWOS ( n --) 0 TUCK
- DO CR DUP . 2 + 2 +LOOP DROP ;
-
-
- 8.4 Structured programming
-
- N. Wirth invented the Pascal language in reaction to program flow
- charts resembling a plate of spaghetti. Such flow diagrams were
- often seen in early languages like FORTRAN and assembler. Wirth
- intended to eliminate line labels and direct jumps (GOTOs), thereby
- forcing control flow to be clear and direct.
-
- The ideal was subroutines or functions that performed a single
- task, with unique entries and exits. Unfortunately, programmers
- insisted on GOTOs, so many Pascals and other modern languages now have
- them. Worse, the ideal of short subroutines that do one thing only is
- unreachable in such languages because the method for calling them and
- passing arguments imposes a large overhead. Thus execution speed re-
- quires minimizing calls, which in turn means longer, more complex sub-
- routines that perform several related tasks. Today structured program-
- ming seems to mean little more than writing code with nested IFs in-
- dented by a pretty-printer.
-
- Paradoxically, Forth is the only truly structured language in common
- use, although it was not designed with that as its goal. In Forth word
- definitions are subroutine calls. The language contains no GOTO's so
- it is impossible to write "spaghetti code". Forth also encourages
- structure through short definitions. The additional running time
- incurred in breaking a long procedure into many small ones (this is
- called "factoring") is typically rather small in Forth. Each Forth sub-
- routine (word) has one entry and one exit point, and can be written
- to perform a single job.
-
-
-
- 8.5 "Top-down" design
-
- "Top-down" programming is a doctrine that one should design the entire
- program from the general to the particular:
-
- > Make an outline, flow chart or whatever, taking a broad overview
- of the whole problem.
-
- > Break the problem into small pieces (decompose it).
-
- > Then code the individual components.
-
- The natural programming mode in Forth is "bottom-up" rather than "top-
- down" --the most general word appears last, whereas the definitions
- must progress from the primitive to the complex. This leads to a some-
- what different approach from more familiar languages:
-
- > In Forth, components are specified roughly, and then as they are
- coded they are immediately tested, debugged, redesigned and
- improved.
-
- > The evolution of the components guides the evolution of the outer
- levels of the program.
-
-
-
-
- 9. CREATE ... DOES> (the pearl of FORTH)
-
- Michael Ham has called the word pair CREATE...DOES>, the "pearl of
- Forth". CREATE is a component of the compiler, whose function is to
- make a new dictionary entry with a given name (the next name in the
- input stream) and nothing else. DOES> assigns a specific run-time ac-
- tion to a newly CREATEd word.
-
-
- 9.1 Defining "defining" words
-
- CREATE finds its most important use in extending the powerful class of
- Forth words called "defining" words. The colon compiler ":" is such
- a word, as are VARIABLE and CONSTANT.
-
- The definition of VARIABLE in high-level Forth is simple
-
- : VARIABLE CREATE 1 CELLS ALLOT ;
-
- We have already seen how VARIABLE is used in a program. (An altern-
- ative definition found in some Forths is
-
- : VARIABLE CREATE 0 , ;
-
- --these variables are initialized to 0.)
-
- Forth lets us define words initialized to contain specific values: for
- example, we might want to define the number 17 to be a word. CREATE
- and "," ("comma") can do this:
-
- 17 CREATE SEVENTEEN , <cr> ok
-
- Now test it via
-
- SEVENTEEN @ . <cr> 17 ok .
-
-
- Remarks:
-
- > The word , ("comma") puts TOS into the next cell of the dic-
- tionary and increments the dictionary pointer by that number of
- bytes.
-
- > A word "C," ("see-comma") exists also -- it puts a character into
- the next character-length slot of the dictionary and increments
- the pointer by 1 such slot. (If the character representation is
- ASCII the slots are 1 byte--Unicode requires 2 bytes.)
-
-
- 9.2 Run-time vs. compile-time actions
-
- In the preceding example, we were able to initialize the variable
- SEVENTEEN to 17 when we CREATEd it, but we still have to fetch it to
- the stack via SEVENTEEN @ whenever we want it. This is not quite what
- we had in mind: we would like to find 17 in TOS when SEVENTEEN is
- named. The word DOES> gives us the tool to do this.
-
- The function of DOES> is to specify a run-time action for the "child"
- words of a defining word. Consider the defining word CONSTANT , de-
- fined in high-level (of course CONSTANT is usually defined in machine
- code for speed) Forth by
-
- : CONSTANT CREATE , DOES> @ ;
-
- and used as
-
- 53 CONSTANT PRIME <cr> ok
-
- Now test it:
-
- PRIME . <cr> 53 ok .
-
-
- What is happening here?
-
- > CREATE (hidden in CONSTANT) makes an entry named PRIME (the
- first word in the input stream following CONSTANT). Then ","
- places the TOS (the number 53) in the next cell of the dic-
- tionary.
-
- > Then DOES> (inside CONSTANT) appends the actions of all words be-
- tween it and ";" (the end of the definition) --in this case, "@"--
- to the child word(s) defined by CONSTANT.
-
-
- 9.3 Dimensioned data (intrinsic units)
-
- Here is an example of the power of defining words and of the distinc-
- tion between compile-time and run-time behaviors.
-
- Physical problems generally involve quantities that have dimensions,
- usually expressed as mass (M), length (L) and time (T) or products of
- powers of these. Sometimes there is more than one system of units in
- common use to describe the same phenomena.
-
- For example, U.S. or English police reporting accidents might use
- inches, feet and yards; while Continental police would use centimeters
- and meters. Rather than write different versions of an accident ana-
- lysis program it is simpler to write one program and make unit conver-
- sions part of the grammar. This is easy in Forth.
-
- The simplest method is to keep all internal lengths in millimeters,
- say, and convert as follows:
-
- : INCHES 254 10 */ ;
- : FEET [ 254 12 * ] LITERAL 10 */ ;
- : YARDS [ 254 36 * ] LITERAL 10 */ ;
- : CENTIMETERS 10 * ;
- : METERS 1000 * ;
-
- Note: This example is based on integer arithmetic. The word */
- means "multiply the third number on the stack by NOS, keeping
- double precision, and divide by TOS". That is, the stack com-
- ment for */ is ( a b c -- a*b/c).
-
-
- The usage would be
-
- 10 FEET . <cr> 3048 ok
-
-
- The word "[" switches from compile mode to interpret mode while com-
- piling. (If the system is interpreting it changes nothing.) The word
- "]" switches from interpret to compile mode.
-
- Barring some error-checking, the "definition" of the colon compiler
- ":" is just
-
- : : CREATE ] DOES> doLIST ;
-
- and that of ";" is just
-
- : ; next [ ; IMMEDIATE
-
- Another use for these switches is to perform arithmetic at compile-
- time rather than at run-time, both for program clarity and for easy
- modification, as we did in the first try at dimensioned data (that is,
- phrases such as
-
- [ 254 12 * ] LITERAL
-
- and
-
- [ 254 36 * ] LITERAL
-
- which allowed us to incorporate in a clear manner the number of
- tenths of millimeters in a foot or a yard.
-
-
- The preceding method of dealing with units required unnecessarily many
- definitions and generated unnecessary code. A more compact approach
- uses a defining word, UNITS :
-
- : D, ( hi lo --) SWAP , , ;
- : D@ ( adr -- hi lo) DUP @ SWAP 2 + @ ;
- : UNITS CREATE D, DOES> D@ */ ;
-
- Then we could make the table
-
- 254 10 UNITS INCHES
- 254 12 * 10 UNITS FEET
- 254 36 * 10 UNITS YARDS
- 10 1 UNITS CENTIMETERS
- 1000 1 UNITS METERS
-
- \ Usage:
- 10 FEET . <cr> 3048 ok
- 3 METERS . <cr> 3000 ok
- \ .......................
- \ etc.
-
- This is an improvement, but Forth permits a simple extension that
- allows conversion back to the input units, for use in output:
-
- VARIABLE <AS> 0 <AS> !
- : AS TRUE <AS> ! ;
- : ~AS FALSE <AS> ! ;
- : UNITS CREATE D, DOES> D@ <AS> @
- IF SWAP THEN
- */ ~AS ;
-
- \ UNIT DEFINITIONS REMAIN THE SAME.
- \ Usage:
- 10 FEET . <cr> 3048 ok
- 3048 AS FEET . <cr> 10 ok
-
-
-
- 9.4 Advanced uses of the compiler
-
- Suppose we have a series of push-buttons numbered 0-3, and a word WHAT
- to read them. That is, WHAT waits for input from a keypad: when button
- #3 is pushed, for example, WHAT leaves 3 on the stack.
-
- We would like to define a word BUTTON to perform the action of pushing
- the n'th button, so we could just say:
-
- WHAT BUTTON
-
- In a conventional language BUTTON would look something like
-
- : BUTTON DUP 0 = IF RING DROP EXIT THEN
- DUP 1 = IF OPEN DROP EXIT THEN
- DUP 2 = IF LAUGH DROP EXIT THEN
- DUP 3 = IF CRY DROP EXIT THEN
- ABORT" WRONG BUTTON!" ;
-
- That is, we would have to go through two decisions on the average.
-
- Forth makes possible a much neater algorithm, involving a "jump
- table". The mechanism by which Forth executes a subroutine is to
- feed its "execution token" (often an address, but not necessarily)
- to the word EXECUTE. If we have a table of execution tokens we need
- only look up the one corresponding to an index (offset into the table)
- fetch it to the stack and say EXECUTE.
-
- One way to code this is
-
- CREATE BUTTONS ' RING , ' OPEN , ' LAUGH , ' CRY ,
- : BUTTON ( nth --) 0 MAX 3 MIN
- CELLS BUTTONS + @ EXECUTE ;
-
- Note how the phrase 0 MAX 3 MIN protects against an out-of-range
- index. Although the Forth philosophy is not to slow the code with un-
- necessary error checking (because words are checked as they are de-
- fined), when programming a user interface some form of error handling
- is vital. It is usually easier to prevent errors as we just did, than
- to provide for recovery after they are made.
-
- How does the action-table method work?
-
- > CREATE BUTTONS makes a dictionary entry BUTTONS.
-
- > The word ' ("tick") finds the execution token (xt) of the
- following word, and the word , ("comma") stores it in the
- data field of the new word BUTTONS. This is repeated until
- all the subroutines we want to select among have their xt's
- stored in the table.
-
- > The table BUTTONS now contains xt's of the various actions of
- BUTTON.
-
- > CELLS then multiplies the index by the appropriate number of
- bytes per cell, to get the offset into the table BUTTONS
- of the desired xt.
-
- > BUTTONS + then adds the base address of BUTTONS to get the abso-
- lute address where the xt is stored.
-
- > @ fetches the xt for EXECUTE to execute.
-
- > EXECUTE then executes the word corresponding to the button pushed.
- Simple!
-
- If a program needs but one action table the preceding method suffices.
- However, more complex programs may require many such. In that case
- it may pay to set up a system for defining action tables, including
- both error-preventing code and the code that executes the proper
- choice. One way to code this is
-
- : ;CASE ; \ do-nothing word
- : CASE:
- CREATE HERE -1 >R 0 , \ place for length
- BEGIN BL WORD FIND \ get next subroutine
- 0= IF CR COUNT TYPE ." not found" ABORT THEN
- R> 1+ >R
- DUP , ['] ;CASE =
- UNTIL R> 1- SWAP ! \ store length
- DOES> DUP @ ROT ( -- base_adr len n)
- MIN 0 MAX \ truncate index
- CELLS + CELL+ @ EXECUTE ;
-
- Note the two forms of error checking. At compile-time, CASE:
- aborts compilation of the new word if we ask it to point to an
- undefined subroutine:
-
- case: test1 DUP SWAP X ;case
- X not found
-
- and we count how many subroutines are in the table (including
- the do-nothing one, ;case) so that we can force the index to
- lie in the range [0,n].
-
- CASE: TEST * / + - ;CASE ok
- 15 3 0 TEST . 45 ok
- 15 3 1 TEST . 5 ok
- 15 3 2 TEST . 18 ok
- 15 3 3 TEST . 12 ok
- 15 3 4 TEST . . 3 15 ok
-
- Just for a change of pace, here is another way to do it:
-
- : jtab: ( Nmax --) \ starts compilation
- CREATE \ make a new dictionary entry
- 1- , \ store Nmax-1 in its body
- ; \ for bounds clipping
-
- : get_xt ( n base_adr -- xt_addr)
- DUP @ ( -- n base_adr Nmax-1)
- ROT ( -- base_adr Nmax-1 n)
- MIN 0 MAX \ bounds-clip for safety
- 1+ CELLS+ ( -- xt_addr = base + 1_cell + offset)
- ;
-
- : | ' , ; \ get an xt and store it in next cell
-
- : ;jtab DOES> ( n base_adr --) \ ends compilation
- get_xt @ EXECUTE \ get token and execute it
- ; \ appends table lookup & execute code
-
- \ Example:
- : Snickers ." It's a Snickers Bar!" ; \ stub for test
-
- \ more stubs
-
- 5 jtab: CandyMachine
- | Snickers
- | Payday
- | M&Ms
- | Hershey
- | AlmondJoy
- ;jtab
-
- 3 CandyMachine It's a Hershey Bar! ok
- 1 CandyMachine It's a Payday! ok
- 7 CandyMachine It's an Almond Joy! ok
- 0 CandyMachine It's a Snickers Bar! ok
- -1 CandyMachine It's a Snickers Bar! ok
-
-
-
- 10. Floating point arithmetic
-
- Although Forth at one time eschewed floating point arithmetic
- (because in the era before math co-processors integer arithmetic
- was 3x faster), in recent years a standard set of word names has
- been agreed upon. This permits the exchange of programs that will
- operate correctly on any computer, as well as the development of
- a Scientific Subroutine Library in Forth (FSL).
-
- Although the ANS Standard does not require a separate stack for
- floating point numbers, most programmers who use Forth for numer-
- ical analysis employ a separate floating point stack; and most of
- the routines in the FSL assume such. We shall do so here as well.
-
- The floating point operators have the following names and perform
- the actions indicated in the accompanying stack comments:
-
- F@ ( adr --) ( f: -- x)
- F! ( adr --) ( f: x --)
- F+ ( f: x y -- x+y)
- F- ( f: x y -- x-y)
- F* ( f: x y -- x*y)
- F/ ( f: x y -- x/y)
- FEXP ( f: x -- e^x)
- FLN ( f: x -- ln[x])
- FSQRT ( f: x -- x^0.5)
-
- Additional operators, functions, trigonometric functions, etc. can
- be found in the FLOATING and FLOATING EXT wordsets. (See dpANS6--
- available in HTML, PostScript and MS Word formats. The HTML version
- can be accessed from this homepage.)
-
- To aid in using floating point arithmetic I have created a simple
- FORTRAN-like interface for incorporating formulas into Forth words.
-
- The file ftest.f (included below) illustrates how ftran111.f
- should be used.
-
-\ Test for ANS FORmula TRANslator
-
-marker -test
-fvariable a
-fvariable b
-fvariable c
-fvariable d
-fvariable x
-fvariable w
-
-: test0 f" b+c" cr fe.
- f" b-c" cr fe.
- f" (b-c)/(b+c)" cr fe. ;
-
-3.e0 b f!
-4.e0 c f!
-see test0
-test0
-
-: test1 f" a=b*c-3.17e-5/tanh(w)+abs(x)" a f@ cr fe. ;
-1.e-3 w f!
--2.5e0 x f!
-cr cr
-see test1
-test1
-
-cr cr
-: test2 f" c^3.75" cr fe.
- f" b^4" cr fe. ;
-see test2
-test2
-
-\ Baden's test case
-
-: quadroot c f! b f! a f!
- f" d = sqrt(b^2-4*a*c) "
- f" (-b+d)/(2*a) " f" (-b-d)/(2*a) "
-;
-cr cr
-see quadroot
-
-: goldenratio f" max(quad root(1,-1,-1)) " ;
-cr cr
-see goldenratio
-cr cr
-goldenratio f.
-
-
-
-0 [IF]
-Output should look like:
-
-: test0
- c f@ b f@ f+ cr fe. c f@ fnegate b f@ f+ cr fe. c f@ fnegate b f@
- f+ c f@ b f@ f+ f/ cr fe. ;
-7.00000000000000E0
--1.00000000000000E0
--142.857142857143E-3
-
-
-: test1
- x f@ fabs 3.17000000000000E-5 w f@ ftanh f/ fnegate b f@ c f@ f* f+
- f+ a f! a f@ cr fe. ;
-14.4682999894333E0 ok
-
-: test2
- c f@ noop 3.75000000000000E0 f** cr fe. b f@ f^4 cr fe. ;
-181.019335983756E0
-81.0000000000000E0 ok
-
-: QUADROOT C F! B F! A F! B F@ F^2 flit 4.00000 A F@
- C F@ F* F* F- FSQRT D F! B F@ FNEGATE D
- F@ F+ flit 2.00000 A F@ F* F/ B F@ FNEGATE
- D F@ F- flit 2.00000 A F@ F* F/ ;
-
-
-: GOLDENRATIO flit 1.00000 flit -1.00000 flit -1.00000
- QUADROOT FMAX ;
-
-1.61803 ok
-
-with more or fewer places.
-
-[THEN]
-
-
-
-
diff --git a/doc/releases.html b/doc/releases.html
new file mode 100644
index 000000000000..e5291c3e54d8
--- /dev/null
+++ b/doc/releases.html
@@ -0,0 +1,1267 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META name='Description' content='Ficl - embedded scripting with object oriented programming'>
+<META name='Keywords' content='scripting prototyping tcl OOP Forth interpreter C'>
+<LINK rel='SHORTCUT ICON' href='ficl.ico'>
+<TITLE>ficl release history</TITLE>
+<style>
+
+blockquote { margin-left: 1em }
+
+</style>
+
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>
+
+
+<td width=112 bgcolor=#004968 colspan=3>
+<img src=graphics/ficl.4.96.jpg height=96 width=96>
+</td>
+
+<td bgcolor=#004968>
+<font face=arial,helvetica color=white size=7><b><i>
+ficl release history
+</i></b></font>
+</td></tr>
+
+
+<tr>
+<td bgcolor=#004968 width=10></td>
+<td bgcolor=#004968 valign=top>
+<br><p>
+<a href=index.html><font face=arial,helvetica color=white><b>Index</b></font></a><p>
+<p><br>
+<a href=dpans.html><font face=arial,helvetica color=white><b>ANS</b></font></a><br>
+<a href=api.html><font face=arial,helvetica color=white><b>API</b></font></a><br>
+<a href=debugger.html><font face=arial,helvetica color=white><b>Debugger</b></font></a><br>
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441><font face=arial,helvetica color=white><b>Download</b></font></a><br>
+<a href=license.html><font face=arial,helvetica color=white><b>Licensing</b></font></a><br>
+<a href=links.html><font face=arial,helvetica color=white><b>Links</b></font></a><br>
+<a href=locals.html><font face=arial,helvetica color=white><b>Locals</b></font></a><br>
+<a href=oop.html><font face=arial,helvetica color=white><b>OOP&nbsp;In&nbsp;Ficl</b></font></a><br>
+<a href=parsesteps.html><font face=arial,helvetica color=white><b>Parse&nbsp;Steps</b></font></a><br>
+<a href=releases.html><font face=arial,helvetica color=white><b>Release&nbsp;History</b></font></a><br>
+<a href=upgrading.html><font face=arial,helvetica color=white><b>Upgrading&nbsp;To&nbsp;4.0</b></font></a><br>
+</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4031'>
+Version 4.0.31
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+
+<li>
+First official release of new engine as Ficl 4! Hooray!
+
+<li>
+<code>ficlDictionarySee()</code> now takes a <code>ficlCallback</code>,
+so it knows where to print to. This is because <b>ficlWin</b> only
+sets a per-VM callback, which <i>should</i> work.
+
+<li>
+<code>ficlSystemCreate()</code> now passes in the system correctly
+into the dictionaries it creates, which lets dictionaries know what
+system they're a part of.
+
+<li>
+ficlCompatibility: Forgot to add the <code>errorTextOut</code> to the
+<code>ficl_system</code> structure (though I'd remembered to add it to
+the <code>ficl_vm</code> structure). This caused the <code>ficl_system</code>
+members after <code>textOut</code> to not line up with their equivalent
+<code>ficlSystem</code> members, which did bad things. (The bad thing
+in particular was calling <code>ficlDictionaryResetSearchOrder()</code>
+resulted in diddling the <code>vm->link</code> member, which strangely
+enough resulted in double-freeing the stacks.)
+
+<li>
+Added <code>ficlStackWalk()</code>, which walks a stack from top
+to bottom and calls your specified callback with each successive
+element. Cleaned up stack-printing functions as a result.
+
+<li>
+Changed <code>MULTICALL</code> so you can explicitly specify the vtable.
+
+<li>
+Changed XClasses so it explicitly specifies the vtable for
+non-virtual classes. This means you can now call a virtual
+method when you've <code>SUPER</code>ed an object and you'll
+get the method you wanted.
+
+<li>
+XClasses improvement: when removing a thunked method, remove
+the thunk variable too. Added <code>xClass.removeMember()</code>
+to support this.
+
+<li>
+XClasses now generates runtime stack-check code (<code>_DEBUG</code>
+only) for functions thunked from C to Ficl.
+
+<li>
+<code>FICL_WANT_PLATFORM</code> is now <code>0</code> by default.
+It is now set to <code>1</code> in the appropriate <code>ficlplatform/*.h</code>.
+
+<li>
+<code>softcore/win32.fr ENVIRONMENT? COMPARE<code> needed to be case-insensitive.
+
+<li>
+Whoops! Setting <code>FICL_PLATFORM_2INTEGER</code> to 0
+didn't compile. It now does, and works fine, as proved by
+the <code>ansi</code> platform.
+
+<li>
+Another whoops: contrib/xclasses/xclasses.py assumed that <code>"</code> (a prefix
+version of <code>S"</code>) defined. Switched to <code>S"</code>, which is safer.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4030'>
+Version 4.0.30
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+
+<li>
+Cleaned up some <code>FICL_</code> definitions. Now all <code>FICL_HAVE_*</code> constants
+(and some other odds and ends) have been moved to <code>FICL_PLATFORM_</code>.
+
+<li>
+Whoops! Setting <code>FICL_PLATFORM_2INTEGER</code> to 0 didn't
+compile. It now does, and works fine, as proved by
+the <code>"ansi"</code> platform.
+
+<li>
+Another whoops: <code>contrib/xclasses/xclasses.py</code> assumed that <code>"</code> (a prefix
+version of <code>S"</code>) defined. Switched to <code>S"</code>, which is safer.
+
+<li>
+Added <code>ficlDictionarySetConstantString()</code>. 'Cause I needed it for:
+
+<li>
+Removed the <code>"WIN32"</code> <code>ENVIRONMENT?</code> setting, and added <code>"FICL_PLATFORM_OS"</code>
+and <code>"FICL_PLATFORM_ARCHITECTURE"</code> in its place. These are both <i>strings</i>.
+Updated <code>softcore/win32.fr</code> to match.
+
+<li>
+Compatibility: improved <code>ficlTextOut()</code> behavior. It makes life slightly
+less convenient for some users, but should be an improvement overall.
+The change: <code>ficlTextOut()</code> is now a compatibility-layer function that
+calls straight through to <code>vmTextOut()</code>. Lots of old code calls <code>ficlTextOut()</code>
+(naughty!). It's now explicit that you must set the <code>textOut</code> function
+by hand if you use a custom one... which is a good habit to get in to anyway.
+
+<li>
+Improved the documentation regarding upgrading, <code>ficllocals.h</code>, and compile-time
+constants.
+
+<li>
+Fixed <code>doc/source/generate.py</code> so it gracefully fails to copy over read-only
+files.
+
+<li>
+Got rid of every <code>#ifdef</code> in the sources. We now consistently use <code>#if defined()</code>
+everywhere. Similarly, got rid of all platform-switched <code>#if</code> code (except for the
+compatibility layer, sigh).
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4029'>
+Version 4.0.29
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+
+<li>
+Documentation totally reworked and updated.
+
+<li>
+<code>oldnames</code> renamed to <code>compatibility</code>.
+And improved, so that now Ficl 4 is basically a drop-in
+replacement for Ficl 3.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4028'>
+Version 4.0.28
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+
+<li>
+Did backwards-compatibility testing. Ficl now drops in, more or less,
+with all the old Ficl-3.03-using projects I had handy.
+
+<li>
+Got Ficl compiling and running fine on Linux.
+
+<li>
+Weaned LZ77 code from needing htonl()/ntohl().
+
+<li>
+Moved all the primitives defined in "testmain.c" to their own file,
+"extras.c", and gave it its own global entry point.
+
+<li>
+Renamed "testmain.c" to just plain "main.c".
+
+<li>
+Renamed "softwords" directory to "softcore". More symmetrical.
+
+<li>
+Renamed "softcore\softcore.bat" to "make.bat". Added support for "CLEAN".
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4027'>
+Version 4.0.27
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+
+<li>
+Added runtime jump-to-jump peephole optimization in the new
+switch-threaded VM.
+
+<li>
+Fixed <code>INCLUDE-FILE</code> so it rethrows an exception in the
+subordinate evaluation.
+
+<li>
+Added a separate <code>errorOut</code> function to
+<code>ficlCallback()</code>,
+so under Windows you can have a jolly popup window to
+rub your nose in your failings.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4026'>
+Version 4.0.26
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+
+<li>
+Namespace policing complete. There are now <i>no</i> external symbols
+which do not start with the word <code>ficl</code>.
+
+<li>
+Removed <code>ficlVmExec()</code>, renamed <code>ficlVmExecC()</code> to
+<code>ficlVmExecuteString()</code>, changed it to take a <code>ficlString()</code>.
+This is deliberate subterfuge on my part; I suspect most
+people who currently call <code>ficlVmExec() / ficlVmExecC()</code>
+should be calling <code>ficlVmEvaluate()</code>.
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4025'>
+Version 4.0.25
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+
+<li>
+First pass at support for "oldnames", and namespace policing.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version4023'>
+Version 4.0.23
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+First alpha release of Ficl 4.0 rewrite. Coded, for better
+or for worse, by Larry Hastings.
+Ficl is <i>smaller</i>, <i>faster</i>, <i>more powerful</i>,
+and <i>easier to use</i> than ever before. (Or your money back!)
+<ul>
+<li>
+Rewrote Ficl's virtual machine; Ficl now runs nearly 3x faster out-of-the-box.
+The new virtual machine is of the "big switch statement" variety.
+
+<li>
+Renamed most (probably all) external Ficl functions and data structures.
+They now make sense and are (gasp!) consistent.
+
+<li>
+Retooled double-cell number support to take advantage of platforms
+which natively support double-cell-sized integers. (Like most modern
+32-bit platforms.)
+
+<li>
+Locals and VALUEs are now totally orthogonal; they can be single- or
+double-cell, and use the float or data stack. TO automatically supports all variants.
+
+<li>
+The "softcore" words can now be stored compressed, with a (current)
+savings of 11k. Decompression is nigh-instantaneous. You can choose
+whether or not you want softcore stored compressed at compile-time.
+
+<li>
+Reworked Win32 build process. Ficl now builds out-of-the-box on Win32
+as a static library, as a DLL, and as a command-line program,
+in each of the six possible runtime variants (Debug,Release x Singlethreaded,
+Multithreaded,Multithreaded DLL).
+
+<li>
+There's very likely other wonderful things that I've long forgotten
+about. If you notice them, feel free to remind me :)
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version303'>
+Version 3.03
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+<li>
+Bugfix for floating-point numbers. Floats in compiled code were simply broken.
+
+<li>
+New words: <code>random</code> and <code>seed-random</code>
+
+<li>
+Bugfix: <code>included</code> never closed its file.
+
+<li>
+Bugfix: <code>include</code> was not <code>IMMEDIATE</code>.
+
+<li>
+Un-hid the OO words <code>parse-method</code>, <code>lookup-method</code>, and <code>find-method-xt</code>, as there are perfectly legitimate reasons why you might want to use them.
+
+<li>
+Changed the prefix version of <code>.(</code> to be <code>IMMEDIATE</code> too.
+
+<li>
+Fixed comment in Python softcore builder.
+
+<li>
+Put the <b>doc</b> directory back in to the distribution. (It was missing from 3.02... where'd it go?)
+
+</ul>
+
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version302'>
+Version 3.02
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+<li>
+Added support for <code>nEnvCells</code> (number of environment cells) to <code>FICL_SYSTEM_INFO</code>.
+
+<li>
+Consolidated <code>context</code> and <code>pExtend</code> pointers of <code>FICL_SYSTEM</code>&#151;VM's <code>pExtend</code> pointer is initialized from the copy in <code>FICL_SYSTEM</code> upon VM creation.
+
+<li>
+Added <code>ficl-robust</code> environment variable.
+
+<li>
+Added <code>FW_ISOBJECT</code> word type.
+
+<li>
+Bugfix: <code>environment?</code> was ignoring the length of the supplied string.
+
+<li>
+Portability cleanup in fileaccess.c.
+
+<li>
+Bugfix in <code>ficlParsePrefix</code>: if the prefix dictionary isn't in the wordlist, the word being examined cannot be a prefix, so return failure.
+
+<li>
+<code>SEE</code> improvements: <code>SEE</code> (and consequently <code>DEBUG</code>) have improved source listings with instruction offsets.
+
+<li>
+It's turned off with the preprocessor, but we have the beginnings of a switch-threaded implementation of the inner loop.
+
+<li>
+Added <code>objectify</code> and <code>?object</code> for use by OO infrastructure.
+
+<li>
+<code>my=[</code> detects object members (using <code>?object</code>) and assumes all other members leave class unchanged.
+
+<li>
+Removed <code>MEMORY-EXT</code> environment variable (there is no such wordset).
+
+<li>
+Ficlwin changes:
+<ul>
+<li>
+Ficlwin character handling is more robust
+
+<li>
+Ficlwin uses multi-system constructs (see ficlthread.c)
+
+</ul>
+
+<li>
+Documentation changes:
+<ul>
+<li>
+Corrected various bugs in docs.
+
+<li>
+Added ficl-ized version of JV Noble's Forth Primer
+
+<li>
+Ficl OO tutorial expanded and revised. Thanks to David McNab for his demo and suggestions.
+
+</ul>
+
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version301'>
+Version 3.01
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+<li>
+Major contributionss by Larry Hastings (larry@hastings.org):
+<ul>
+<li>
+FILE wordset (fileaccess.c)
+
+<li>
+ficlEvaluate wrapper for ficlExec
+
+<li>
+ficlInitSystemEx makes it possible to bind selectable properties to VMs at create time
+
+<li>
+Python version of softcore builder ficl/softwords/softcore.py
+
+</ul>
+
+<li>
+Environment contains ficl-version (double)
+
+<li>
+?number handles trailing decimal point per DOUBLE wordset spec
+
+<li>
+Fixed broken .env (thanks to Leonid Rosin for spotting this goof)
+
+<li>
+Fixed broken floating point words that depended on evaluation order of stack pops.
+
+<li>
+env-constant
+
+<li>
+env-2constant
+
+<li>
+dictHashSummary is now commented out unless FICL_WANT_FLOAT (thanks to Leonid Rosin again)
+
+<li>
+Thanks to David McNab for pointing out that .( should be IMMEDIATE. Now it is.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version300a'>
+Version 3.00a
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+<li>
+Fixed broken oo.fr by commenting out vcall stuff using FICL_WANT_VCALL. Vcall is still broken.
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version300'>
+Version 3.00
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+<li>
+Added pSys parameter to most ficlXXXX functions for multiple system support. Affected functions:
+<ul>
+<li>dictLookupLoc renamed to ficlLookupLoc after addition of pSys param
+<li>ficlInitSystem returns a FICL_SYSTEM*
+<li>ficlTermSystem
+<li>ficlNewVM
+<li>ficlLookup
+<li>ficlGetDict
+<li>ficlGetEnv
+<li>ficlSetEnv
+<li>ficlSetEnvD
+<li>ficlGetLoc
+<li>ficlBuild
+</ul>
+
+
+<li>Fixed off-by-one bug in ficlParsePrefix
+<li>Ficl parse-steps now work correctly - mods to interpret()
+<li>Made tools.c:isAFiclWord more selective
+<li>Tweaked makefiles and code to make gcc happy under linux
+<li>Vetted all instances of LVALUEtoCELL to make sure they're working on CELL sized operands
+(for 64 bit compatibility)
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version206'>
+Version 2.06
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<ul>
+<li>Debugger changes:
+<ul>
+<li>New debugger command "x" to execute the rest of the command line as ficl
+<li>New debugger command "l" lists the source of the innermost word being debugged
+<li>If you attempt to debug a primitive, it gets executed rather than doing nothing
+<li><code>R.S</code> displays the stack contents symbolically
+<li>Debugger now operates correctly under ficlwin, although ficlwin's key handling leaves a lot to be desired.
+<li><code>SEE</code> listing enhanced for use with the debugger
+</ul>
+<li>Added Guy Carver's changes to oo.fr for VTABLE support
+<li><code>float.c</code> words f&gt; and &gt;f to move floats to and from the param stack, analogous to &gt;r and r&gt;
+<li><code>LOOKUP</code> - Surrogate precompiled parse step for ficlParseWord (this step is hard
+ coded in <code>INTERPRET</code>)
+<li>License text at top of source files changed from LGPL to BSD by request
+<li>Win32 console version now handles exceptions more gracefully rather than crashing - uses win32
+structured exception handling.
+<li>Fixed BASE bug from 2.05 (was returning the value rather than the address)
+<li>Fixed ALLOT bug - feeds address units to dictCheck, which expects Cells. Changed dictCheck
+to expect AU.
+<li>Float stack display word renamed to f.s from .f to be consistent with r.s and .s
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version205'>
+Version 2.05
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+<h3>General</h3>
+
+<ul>
+<li>HTML documentation extensively revised
+<li>Incorporated Alpha (64 bit) patches from the freeBSD team.
+<li>Split SEARCH and SEARCH EXT words from words.c to search.c
+<li><a href="ficl_loc.html">2LOCALS</a> defined in <a href="ficl_loc.html#jhlocal">Johns Hopkins local syntax</a> now lose the first '2:' in their names.
+<li>Simple step <a href="ficl_debug.html">debugger</a> (see tools.c)
+<li>The text interpreter is now extensible - this is accomplished through the use
+of <code>ficlAddParseStep()</code>. <code>FICL_MAX_PARSE_STEPS</code> limits the number of parse steps
+(default: 8). You can write a precompiled parse step (see <code>ficlParseNumber</code>) and
+append it to the chain, or you can write one in ficl and use <code>ADD-PARSE-STEP</code>
+to append it. Default parse steps are initialized in <code>ficlInitSystem</code>. You can list
+the parse steps with <code>parse-order ( -- )</code>.
+<li>There is now a FICL_SYSTEM structure. This is a transitional release - version 3.0
+will alter several API prototypes to take this as a parameter, allowing multiple
+systems per process (and therefore multiple dictionaries). For those who use ficl
+under a virtual memory O/S like Linux or Win NT, you can just create multiple ficl
+processes (not threads) instead and save youself the wait.
+<li>Fixes for improved command line operation in testmain.c (Larry Hastings)
+<li>Numerous extensions to OO facility, including a new allot methods, ability
+to catch method invocations (thanks to Daniel Sobral again)
+<li>Incorporated Alpha (64 bit) patches contributed by Daniel Sobral and the freeBSD team
+Ficl is now 64 bit friendly! UNS32 is now FICL_UNS.
+<li>Split SEARCH and SEARCH EXT words from words.c to search.c
+<li>ABORT" now complies with the ANS (-2 THROWs)
+<li>Floating point support contributed by Guy Carver (Enable FICL_WANT_FLOAT in sysdep.h).
+<li>Win32 vtable model for objects (Guy Carver)
+<li>Win32 dll load/call suport (Larry Hastings)
+<li>Prefix support (Larry Hastings) (prefix.c prefix.fr FICL_EXTENDED_PREFIX) makes it
+easy to extend the parser to recignize prefixes like 0x and act on them. Use show-prefixes
+to see what's defined.
+<li>Cleaned up initialization sequence so that it's all in ficlInitSystem, and so that
+a VM can be created successfully before the dictionary is created
+</ul>
+
+<h3>
+Bug fixes</h3>
+
+<ul>
+<li>
+<a href="http://www.taygeta.com/forth/dpans9.htm#9.6.2.0680">ABORT"</a>
+now works correctly (I promise!)
+
+<li>
+<a href="http://www.taygeta.com/forth/dpans6.htm#6.2.2125">REFILL</a> works
+better
+
+<li>
+<a href="http://www.taygeta.com/forth/dpans6.htm#6.1.0710">ALLOT</a>'s
+use of dictCheck corrected (finally)
+</ul>
+
+<h3>
+New words</h3>
+
+<ul>
+<li>
+<a href="http://www.taygeta.com/forth/dpans6.htm#6.2.0415">2r@</a> <a href="http://www.taygeta.com/forth/dpans6.htm#6.2.0410">2r></a> <a href="http://www.taygeta.com/forth/dpans6.htm#6.2.0340">2>r</a>
+(CORE EXT)
+
+<li>
+<a href="http://www.taygeta.com/forth/dpans8.htm#8.6.1.0440">2VARIABLE</a>
+(DOUBLE)
+
+<li>
+<a href="http://www.taygeta.com/forth/dpans16.htm#16.6.2.1985">ORDER</a>
+now lists wordlists by name
+
+<li>
+<a href="http://www.taygeta.com/forth/dpans15.htm#15.6.1.0220">.S</a> now
+displays all stack entries on one line, like a stack comment
+
+<li>
+<a href="ficl.html#wid-get-name"><tt>wid-get-name</tt>&nbsp;</a>&nbsp;
+given a wid, returns the address and count of its name. If no name, count
+is 0
+
+<li>
+<tt><a href="ficl.html#wid-set-name">wid-set-name</a></tt>&nbsp;
+set optional wid name pointer to the \0 terminated string address specified.
+
+<li>
+<tt><a href="ficl.html#ficlwordlist">ficl-named-wordlist</a></tt> creates
+a ficl-wordlist and names it. This is now used in <tt>vocabulary</tt> and
+<tt><a href="ficl.html#ficlvocabulary">ficl-vocabulary</a></tt>&nbsp;
+
+<li>
+<tt><a href="ficl.html#last-word">last-word</a></tt>&nbsp; returns the
+xt of the word being defined or most recently defined.
+
+<li>
+<tt><a href="ficl.html#qfetch">q@</a></tt> and <tt><a href="ficl.html#qbang">q!</a></tt>
+operate on quadbyte quantities for 64 bit friendliness
+</ul>
+
+<h3>
+New OO stuff</h3>
+
+<ul>
+<li>
+<tt>ALLOT (class method)</tt>
+
+<li>
+<tt>ALLOT-ARRAY (class method)</tt>
+
+<li>
+<tt>METHOD</tt> define method names globally
+
+<li>
+<tt>MY=></tt> early bind a method call to "this" class
+
+<li>
+<tt>MY=[ ]</tt> early bind a string of method calls to "this" class and
+obj members
+
+<li>
+<tt>C-></tt> late bind method invocation with CATCH
+
+<li>
+Metaclass method <tt>resume-class</tt> and instance word <tt>suspend-class</tt>
+create mutually referring classes. Example in string.fr
+
+<li>
+Early binding words are now in the instance-vars wordlist, not visible
+unless defining a class.
+
+<li>Support for refs to classes with VTABLE methods (contributed by Guy Carver). Guy writes:
+<p>
+My next favorite change is a set of VCALL words that allow me
+to call C++ class virtual methods from my forth classes. This
+is accomplished by interfacing with the VTABLE of the class. The
+class instance currently must be created on the C++ side.
+C++ places methods in the VTABLE in order of declaration in the
+header file. To use this in FICL one only needs to ensure
+that the VCALL: declerations occur in the same order. I use this
+quite a bit to interface with the C++ classes. When I need access
+to a method I make sure it is virtual (Even if it ultimately will
+not be). I use Visual C++ 6.0 and have not tested this under
+any other compiler but I believe VTABLE implementation is standard.
+</p><p>
+Here is an example of how to use VCALL:
+</p>
+<b>C++ class declaration</b>
+<pre>
+class myclass
+{
+public:
+ myclass();
+ virtual ~myclass();
+ virtual void Test( int iParam1 );
+ virtual int Test( int iParam1, char cParam2 );
+ virtual float Test();
+};
+</pre>
+<b>ficl class declaration</b>
+<pre>
+object subclass myfclass hasvtable \ hasvtable adds 4 to the offset to
+ \ accommodate for the VTABLE pointer.
+0 VCALL: Destructor() \ VCALL: ( ParamCount -<MethodName>- )
+1 VCALL: Test(int) \ Test takes 1 int parameter.
+2 VCALLR: iTest(int,char) \ iTest takes 2 parameters and returns an int.
+0 VCALLF: fTest() \ fTest takes no parameters and returns a float.
+end-class
+
+MyCAddress \ Primitive to return a pointer to a "myclass" instance.
+myfclass -> ref dude \ This makes the MyCAddress pointer a myfclass
+ \ instance with the name "dude".
+1234 dude -> Test(int) \ Calls the virtual method Test.
+1234 1 dude -> iTest(int,char) . \ Calls iTest and emits the returned int.
+dude -> fTest() f. \ Calls fTest and emits the returned float.
+</pre>
+
+</ul>
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version204'>
+Version 2.04
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<h3>ficlwin</h3>
+
+<ul>
+<li>
+Catches exceptions thrown by VM in ficlThread (0 @ for example) rather
+than passing them off to the OS.&nbsp;
+</ul>
+
+<h3>
+ficl bugs vanquished</h3>
+
+<ul>
+<li>
+Fixed leading delimiter bugs in s" ." .( and ( (reported by Reuben Thomas)
+
+<li>
+Makefile tabs restored (thanks to Michael Somos)
+
+<li>
+ABORT" now throws -2 per the DPANS (thanks to Daniel Sobral for sharp eyes
+again)&nbsp;
+
+<li>
+ficlExec does not print the prompt string unless (source-id == 0)
+
+<li>
+Various fixes contributed by the FreeBSD team.
+</ul>
+
+<h3>
+ficl enhancements</h3>
+
+<ul>
+<li>
+Words.c: modified ficlCatch to use vmExecute and vmInnerLoop (request of
+Daniel Sobral) Added vmPop and vmPush functions (by request of Lars Krueger
+) in vm.c These are shortcuts to the param stack. (Use LVALUEtoCELL to
+get things into CELL form)&nbsp;
+
+<li>
+Added function vmGetStringEx with a flag to specify whether or not to skip
+lead delimiters
+
+<li>
+Added non-std word: number?
+
+<li>
+Added CORE EXT word AGAIN (by request of Reuben Thomas)&nbsp;
+
+<li>
+Added double cell local (2local) support
+
+<li>
+Augmented Johns Hopkins local syntax so that locals whose names begin with
+char 2 are treated as 2locals (OK - it's goofy, but handy for OOP)
+
+<li>
+C-string class revised and enhanced - now dynamically sized
+
+<li>
+C-hashstring class derived from c-string computes hashcode too.
+</ul>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version203'>
+Version 2.03
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+This is the first version of Ficl that includes contributed code. Thanks
+especially to Daniel Sobral, Michael Gauland for contributions and bug
+finding.
+<p>
+New words:
+<ul>
+<li>
+<tt><a href="#clock">clock</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(FICL)</tt>
+
+<li>
+<tt><a href="#clockspersec">clocks/sec</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(FICL)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans8.htm#8.6.1.1230">dnegate</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(DOUBLE)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans10.htm#10.6.2.1905">ms</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(FACILITY EXT - replaces MSEC <i>ficlWin only</i>)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans9.htm#9.6.1.2275">throw</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(EXCEPTION)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans9.htm#9.6.1.0875">catch</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(EXCEPTION)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans14.htm#14.6.1.0707">allocate</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(MEMORY)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans14.htm#14.6.1.1605">free</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(MEMORY)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans14.htm#14.6.1.2145">resize</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(MEMORY)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans6.htm#6.2.2440">within</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(CORE EXT)</tt>
+
+<li>
+<tt><a href="#alloc">alloc</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(class method)</tt>
+
+<li>
+<tt><a href="#allocarray">alloc-array</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(class method)</tt>
+
+<li>
+<tt><a href="#oofree">free</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(class method)</tt>
+</ul>
+
+Bugs Fixed:
+<ul>
+<li>
+Bug fix in isNumber(): used to treat chars between 'Z' and 'a' as valid
+in base 10... (harmless, but weird)
+
+<li>
+ficlExec pushes the <i>ip</i> and <tt>interpret</tt>s at the right times
+so that nested calls to ficlExec behave the way you'd expect them to.
+
+<li>
+<tt>evaluate</tt> respects count parameter, and also passes exceptional
+return conditions back out to the calling instance of ficlExec.
+
+<li>
+VM_QUIT now clears the locals dictionary in ficlExec.
+</ul>
+Ficlwin Enhancements&nbsp;
+<ul>
+<li>
+File Menu: recent file list and Open now load files.
+
+<li>
+Text ouput function is now faster through use of string caching. Cache
+flushes at the end of each line and each time ficlExec returns.
+
+<li>
+Edit/paste now behaves more reasonably for text. File/open loads the specified
+file.
+
+<li>
+Registry entries specify dictionary and stack sizes, default window placement,
+and whether or not to create a splitter for multiple VMs. See HKEY_CURRENT_USER/Software/CodeLab/ficlwin/Settings
+</ul>
+Ficl Enhancements&nbsp;
+<ul>
+<li>
+This version includes changes to make it <b>64 bit friendly</b>. This unfortunately
+meant that I had to tweak some core data types and structures. I've tried
+to make this transparent to 32 bit code, but a couple of things got renamed.
+INT64 is now DPINT. UNS64 is now DPUNS. FICL_INT and FICL_UNS are synonyms
+for INT32 and UNS32 in 32 bit versions, but a are obsolescent. Please use
+the new data types instead. Typed stack operations on INT32 and UNS32 have
+been renamed because they operate on CELL scalar types, which are 64 bits
+wide on 64 bit systems. Added BITS_PER_CELL, which has legal values of
+32 or 64. Default is 32.
+
+<li>
+ficl.c: Added ficlExecXT() - executes an xt completely before returning,
+passing back any exception codes generated in the process. Normal exit
+code is VM_INNEREXIT.
+
+<li>
+ficl.c: Added ficlExecC() to operate on counted strings as opposed to zero
+terminated ones.
+
+<li>
+ficlExec pushes ip and executes interpret at the right times so that nested
+calls to ficlExec behave the way you'd expect them to.
+
+<li>
+ficlSetStackSize() allows specification of stack size at run-time (affects
+subsequent invocations of ficlNewVM()).
+
+<li>
+vm.c: vmThrow() checks for (pVM->pState != NULL) before longjmping it.
+vmCreate nulls this pointer initially.&nbsp;
+
+<li>
+EXCEPTION wordset contributed by Daniel Sobral of FreeBSD
+
+<li>
+MEMORY-ALLOC wordset contributed by Daniel Sobral, too. Added class methods
+<tt>alloc</tt>
+and <tt>alloc-array</tt> in softwords/oo.fr to allocate objects from the
+heap.
+
+<li>
+Control structure match check upgraded (thanks to Daniel Sobral for this
+suggestion). Control structure mismatches are now errors, not warnings,
+since the check accepts all syntactally legal constructs.
+
+<li>
+Added vmInnerLoop() to vm.h. This function/macro factors the inner&nbsp;
+interpreter out of ficlExec so it can be used in other places. Function/macro
+behavior is conditioned on INLINE_INNER_LOOP in sysdep.h. Default: 1 unless
+_DEBUG is set. In part, this is because VC++ 5 goes apoplectic when trying
+to compile it as a function. See&nbsp;
+
+<br>comments in vm.c
+<li>
+EVALUATE respects the count parameter, and also passes exceptional return
+conditions back out to the calling instance of ficlExec.
+
+<li>
+VM_QUIT clears locals dictionary in ficlExec()
+
+<li>
+Added Michael Gauland's ficlLongMul and ficlLongDiv and support routines
+to math64.c and .h. These routines are coded in C, and are compiled only
+if PORTABLE_LONGMULDIV == 1 (default is 0).
+
+<li>
+Added definition of ficlRealloc to sysdep.c (needed for memory allocation
+wordset). If your target OS supports realloc(), you'll probably want to
+redefine ficlRealloc in those terms. The default version does ficlFree
+followed by ficlMalloc.
+
+<li>
+testmain.c: Changed gets() in testmain to fgets() to appease the security
+gods.
+
+<li>
+testmain: <tt>msec</tt> renamed to <tt><a href="#ficlms">ms</a></tt> in
+line with the ANS
+
+<li>
+softcore.pl now removes comments &amp; spaces at the start and end of lines.
+As a result: sizeof (softWords) == 7663 bytes (used to be 20000)&nbsp;
+and consumes 11384 bytes of dictionary when compiled
+
+<li>
+Deleted license paste-o in readme.txt (oops).
+</ul>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version202'>
+Version 2.02
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+New words:
+<ul>
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans6.htm#6.2.1850">marker</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(CORE EXT)</tt>
+
+<li>
+<tt><a href="http://www.taygeta.com/forth/dpans15.htm#15.6.2.1580">forget</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(TOOLS EXT)</tt>
+
+<li>
+<tt><a href="#ficlforgetwid">forget-wid</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(FICL)</tt>
+
+<li>
+<tt><a href="#ficlwordlist">ficl-wordlist</a>&nbsp;&nbsp;&nbsp;&nbsp; (FICL)</tt>
+
+<li>
+<tt><a href="#ficlvocabulary">ficl-vocabulary</a>&nbsp;&nbsp; (FICL)</tt>
+
+<li>
+<tt><a href="#ficlhide">hide</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(FICL)</tt>
+
+<li>
+<tt><a href="#ficlhidden">hidden</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+(FICL)</tt>
+
+<li>
+<a href="#jhlocal">Johns Hopkins local variable syntax</a> (as best I can
+determine)
+</ul>
+Bugs Fixed&nbsp;
+<ul>
+<li>
+<tt>forget</tt> now adjusts the dictionary pointer to remove the name of
+the word being forgotten (name chars come before the word header in ficl's
+dictionary)
+
+<li>
+<tt>:noname</tt> used to push the colon control marker and its execution
+token in the wrong order
+
+<li>
+<tt>source-id</tt> now behaves correctly when loading a file.
+
+<li>
+<tt>refill</tt> returns zero at EOF (Win32 load). Win32 <tt><a href="#ficlload">load</a></tt>
+command continues to be misnamed. Really ought to be called <tt>included</tt>,
+but does not exactly conform to that spec either (because <tt>included</tt>
+expects a string signature on the stack, while Ficl's <tt><a href="#ficlload">load</a></tt>
+expects a filename upon invocation). The "real" <tt>LOAD</tt> is a <tt>BLOCK</tt>
+word.
+</ul>
+Enhancements (IMHO)&nbsp;
+<ul>
+<li>
+dictUnsmudge no longer links anonymous definitions into the dictionary
+
+<li>
+<tt>oop</tt> is no longer the default compile wordlist at startup, nor
+is it in the search order. Execute <b><tt>also oop definitions</tt></b>
+to use Ficl OOP.
+
+<li>
+Revised oo.fr extensively to make more use of early binding
+
+<li>
+Added <tt>meta</tt> - a constant that pushes the address of metaclass.
+See oo.fr for examples of use.
+
+<li>
+Added classes: <tt>c-ptr&nbsp; c-bytePtr&nbsp; c-2bytePtr&nbsp; c-cellPtr
+</tt>These
+classes model pointers to non-object data, but each knows the size of its
+referent.
+</ul>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version201'>
+Version 2.01
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+<li>
+Bug fix: <tt>(local)</tt> used to leave a value on the stack between the
+first and last locals declared. This value is now stored in a static.
+
+<li>
+Added new local syntax with parameter re-ordering. <a href="#newlocal">See
+description below</a>. (No longer compiled in version 2.02, in favor of
+the Johns Hopkins syntax)
+</ul>
+
+
+
+<p>
+</blockquote><table border=0 bgcolor=#a0a0a0 width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=#004968 size=5><b><i>
+<a name='Version20'>
+Version 2.0
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<ul>
+<li>
+New ANS Forth words: <tt>TOOLS</tt> and part of <tt>TOOLS EXT, SEARCH</tt>
+and <tt>SEARCH EXT, LOCALS</tt> and <tt>LOCALS EXT</tt> word sets, additional
+words from <tt>CORE EXT, DOUBLE</tt>, and <tt>STRING</tt>. (See the function
+ficlCompileCore in words.c for an alphabetical list by word set).
+
+<li>
+Simple <tt>USER</tt> variable support - a user variable is a virtual machine
+instance variable. User variables behave as <tt>VARIABLE</tt>s in all other
+respects.
+
+<li>
+Object oriented syntax extensions (see below)
+
+<li>
+Optional stack underflow and overflow checking in many CORE words (enabled
+when FICL_ROBUST >= 2)
+
+<li>
+Various bug fixes
+</ul>
+
+
+
+
+</blockquote><p></td></tr></table></body></html>
+
+
diff --git a/doc/skey.gif b/doc/skey.gif
deleted file mode 100644
index 7878ccc3431e..000000000000
--- a/doc/skey.gif
+++ /dev/null
Binary files differ
diff --git a/doc/source/api.ht b/doc/source/api.ht
new file mode 100644
index 000000000000..599ba9e16b14
--- /dev/null
+++ b/doc/source/api.ht
@@ -0,0 +1,250 @@
+<?
+ficlPageHeader("ficl api")
+
+ficlAddToNavBarAs("API")
+
+
+def entrypoint(prototype):
+ print "<p><dt>\n" + "<code>" + prototype + "</code>\n<dd>\n"
+?>
+
+
+
+<? ficlHeader1("Quick Ficl Programming Concepts Overview") ?>
+
+
+A Ficl <i>dictionary</i> is equivalent to the FORTH "dictionary"; it is where words are stored.
+A single dictionary has a single <code>HERE</code> pointer.
+<p>
+
+A Ficl <i>system information</i> structure is used to change default values used
+in initializing a Ficl <i>system</i>.
+<p>
+
+A Ficl <i>system</i> contains a single <i>dictionary</i>, and one or more <i>virtual machines</i>.
+<p>
+
+A Ficl <i>stack</i> is equivalent to a FORTH "stack". Ficl has three stacks:
+<ul>
+
+<li>
+The <i>data</i> stack, where integer arguments are stored.
+
+<li>
+The <i>return</i> stack, where locals and return addresses for subroutine returns are stored.
+
+<li>
+The <i>float</i> stack, where floating-point arguments are stored. (This stack
+is only enabled when <code>FICL_WANT_FLOAT</code> is nonzero.)
+</ul>
+
+<p>
+
+A Ficl <i>virtual machine</i> (or <i>vm</i>) represents a single running instance of the Ficl interpreter.
+All virtual machines in a single Ficl system see the same dictionary.
+<p>
+
+<? ficlHeader2("Quick Ficl Programming Tutorial") ?>
+
+Though Ficl's API offers a great deal of flexibility, most programs
+incorporating Ficl simply use it as follows:
+
+<ol>
+
+<li>
+Create a single <code>ficlSystem</code> using <code>ficlSystemCreate(NULL)</code>.
+
+<li>
+Add native functions as necessary with <code>ficlDictionarySetPrimitive()</code>.
+
+<li>
+Add constants as necessary with <code>ficlDictionarySetConstant()</code>.
+
+<li>
+Create one (or more) virtual machine(s) with <code>ficlSystemCreateVm()</code>.
+