home: hub: 9ficl

Download patch

ref: ec465f2985094bcb6c352ceb3866ac4e528fb317
parent: 4e44bee3f28371464c59f2b57c09823fea5e3ebb
author: asau <asau@ficl.sf.net>
date: Thu Aug 12 07:50:38 CDT 2010

*** empty log message ***

--- /dev/null
+++ b/Makefile.ansi
@@ -1,0 +1,55 @@
+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) $(TARGET)
+CC=gcc
+LIB = ar cr
+RANLIB = ranlib
+
+MAJOR = 4
+MINOR = 0.31
+
+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) -c ficlplatform/ansi.c
+
+#
+#       generic object code
+#
+.SUFFIXES: .cxx .cc .c .o
+
+.c.o:
+	$(CC) $(CFLAGS) -c $*.c
+
+.cxx.o:
+	$(CPP) $(CPFLAGS) -c $*.cxx
+
+.cc.o:
+	$(CPP) $(CPFLAGS) -c $*.cc
+#
+#       generic cleanup code
+#
+clean:
+	rm -f *.o *.a libficl.*
--- /dev/null
+++ b/bit.c
@@ -1,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]);
+}
--- /dev/null
+++ b/callback.c
@@ -1,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;
+}
+
+
--- /dev/null
+++ b/compatibility.c
@@ -1,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); }
+
+
--- /dev/null
+++ b/contrib/xclasses/readme.txt
@@ -1,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
--- /dev/null
+++ b/contrib/xclasses/xclasses.py
@@ -1,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()
+
+
+
--- /dev/null
+++ b/dictionary.c
@@ -1,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.1 2010/08/12 12:49:57 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), (int)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;
+}
+
+
--- /dev/null
+++ b/doc/api.html
@@ -1,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>
+
+
binary files /dev/null b/doc/articles/ficlddj.pdf differ
binary files /dev/null b/doc/articles/jwsforml.pdf differ
--- /dev/null
+++ b/doc/articles/oo_in_c.html
@@ -1,0 +1,223 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <title>Object Oriented Idioms in C</title>
+</head>
+<body>
+
+<h1>
+<b><font face="Arial"><font size=+1>Object Oriented Idioms in C</font></font></b></h1>
+<font face="Arial"><font size=-1>John Sadler</font></font>
+<br><font face="Arial"><font size=-1>10 Aug 98</font></font>
+<br>&nbsp;
+<br>&nbsp;
+<table COLS=1 WIDTH="675" >
+<tr>
+<td><a NAME="review"></a><b><font face="Arial"><font size=+1>Review of
+Key OO Characteristics</font></font></b>
+<h3>
+<b><i><font face="Arial">Object</font></i></b></h3>
+<a NAME="object-def"></a><font face="Times New Roman,Times"><b>"A package
+of information and descriptions of its manipulation"</b> [<a href="#robson">Robson</a>]</font>
+<p><font face="Times New Roman,Times">Objects separate interface from implementation,
+"what" is wanted (on the outside) from "how" it is accomplished (on the
+inside). This idea of hiding the data inside a package with a fixed set
+of allowed manipulations is called encapsulation. Why? If the object always
+selects how to perform a requested manipulation, you guarantee that the
+procedure and the data it operates on always match.</font>
+<p><font face="Times New Roman,Times">A <b>message</b> denotes an operation
+that can be performed on an <b>object</b>. The code that describes how
+to perform an operation on a specific object type is called a <b>method</b>.
+From the outside, objects receive messages. On the inside, these messages
+are mapped to methods that perform appropriate actions for the specific
+kind of object. An object�s <b>interface</b> is the set of messages to
+which it can respond. For example, several object types may have a "dump"
+method to cause the object to display its state. Each kind of object will
+need a unique method to accomplish this. So the message-method idea separates
+the interface from the implementation. The idea that different kinds of
+objects might invoke different methods to respond to the same message is
+called <b>polymorphism</b>. Methods can be bound to messages as soon as
+the type of the object receiving the message is known (called <b>early
+binding</b>), or this mapping can wait until run-time (<b>late binding</b>).</font>
+<p><font face="Times New Roman,Times">Some languages (notably C++) make
+a syntactic distinction between early and late binding of methods to messages
+(virtual functions are bound late, while all others are bound early � at
+link time). Smalltalk makes no such distinction. The C++ approach has potentially
+dangerous consequences when you manipulate an object through a pointer
+to its parent class. If a method of the superclass is virtual, you get
+late binding to the appropriate function for the object�s class. On the
+other hand, if that method is not virtual, you get early binding to the
+parent class�s definition even if the child class has overridden it. Smalltalk
+adheres rigorously to the idea that the object itself has sole ownership
+of the mapping from methods to messages.</font>
+<br>&nbsp;</td>
+</tr>
+
+<tr>
+<td>
+<h3>
+<b><i><font face="Arial">Class</font></i></b></h3>
+<a NAME="class-def"></a><b><font face="Times New Roman,Times">"A description
+of one or more similar objects"</font></b> [<a href="#robson">Robson</a>]
+<p><a NAME="instance-def"></a>A specific object described by a particular
+class is called an <b>instance</b> of the class.
+<br>(Example: Dog is a class; Poodle is a subclass of Dog; FiFi is an object,
+an instance of Poodle).
+<br>A class is a kind of object that describes the behaviors (methods)
+of its instances, and whose methods provide for creation, initialization,
+and destruction of an instance. All instances of a particular class use
+the same method to respond to a given message. Classes may define other
+members that are shared by all instances of the class. These are called
+class variables. (In C++, these would be static members.)
+<br>&nbsp;</td>
+</tr>
+
+<tr>
+<td>
+<h3>
+<b><i><font face="Arial">Inheritance</font></i></b></h3>
+<font face="Times New Roman,Times">A means for creating a new object or
+class using an existing one as a starting place and defining only what
+changes. C++ only supports class-based inheritance, but some systems also
+allow objects to inherit directly from other objects. At minimum, inheritance
+requires that the child class override its parent�s name. In addition,
+a child class can:</font>
+<ul>
+<li>
+<font face="Times New Roman,Times">add instance variables</font></li>
+
+<li>
+<font face="Times New Roman,Times">add class variables</font></li>
+
+<li>
+<font face="Times New Roman,Times">define methods for new messages</font></li>
+
+<li>
+<font face="Times New Roman,Times">provide methods for (<b>override</b>)
+messages already handled by the parent class</font></li>
+</ul>
+</td>
+</tr>
+
+<tr>
+<td>
+<h3>
+<b><font face="Arial"><font size=+1>What C++ Does for you�</font></font></b></h3>
+<b><i><font face="Arial">Name mangling � separation of name spaces</font></i></b>
+<p><font face="Times New Roman,Times">This mechanism � decorating symbol
+names with extra characters that uniquely identify their class and prototype
+� is the traditional C++ method for operator overloading, method overloading,
+and namespace separation. C provides a much smaller set of namespaces than
+C++ requires, so this strategy allowed C++ to be implemented as a preprocessor
+for C compilers originally.</font>
+<p><b><i><font face="Arial">Rigorous type checking</font></i></b>
+<p>Because of the function prototype requirement and name mangling, a C++
+compiler can provide strict type checking for method invocations.
+<p><b><i><font face="Arial">Automatic lifetime control</font></i></b>
+<p>Guarantees constructor call upon creation and destructor call upon deletion
+<p><b><i><font face="Arial">Multiple Storage classes (same as C)</font></i></b>
+<p>Automatic, static, dynamically allocated
+<p><b><i><font face="Arial">Typed dynamic memory management</font></i></b>
+<p><b><i><font face="Arial">Default constructor, destructor, copy constructor,
+and assignment operator</font></i></b>
+<p><b><i><font face="Arial">Explicit early and late binding support</font></i></b>
+<p><b><i><font face="Arial">And more�</font></i></b>
+<br>&nbsp;</td>
+</tr>
+
+<tr>
+<td>
+<h3>
+<b><font face="Arial"><font size=+1>What other OO languages do (or don�t
+do)</font></font></b></h3>
+Just to make sure we don�t get caught in a C++ centered view of the world,
+here are some ways other OO systems differ.
+<p><b><i><font face="Arial">Run-time type identification</font></i></b>
+<p>This is a Big Deal in C++, but it�s relatively trivial in an interpreted
+language to know the type of a reference at run-time.
+<p><b><i><font face="Arial">Metaclasses</font></i></b>
+<p>Classes are objects, too (Smalltalk, Java?)
+<p><b><i><font face="Arial">Garbage collection</font></i></b>
+<p>Java and smalltalk both manage memory for you, freeing objects when
+they go out of scope or are no longer referenced anywhere.
+<p><b><i><font face="Arial">Single Inheritance only</font></i></b>
+<p>Java, Smalltalk 80
+<p><b><i><font face="Arial">Everything is an object</font></i></b>
+<p>Smalltalk
+<p><b><i><font face="Arial">Operator overloading</font></i></b>
+<p>Smalltalk makes no distinction between operators and other kinds of
+messages. The message syntax is flexible enough that you can define operators
+in the same way as any other kind of message.
+<p><b><i><font face="Arial">Visibility control</font></i></b>
+<p>Smalltalk 80 does not appear to provide options for visibility control
+(based on my quick survey). Instance variables are always private, methods
+are always public as far as I can tell.
+<p><b><i><font face="Arial">Pointers</font></i></b>
+<p>Not in Smalltalk, Java: Both languages deal with objects through implicit
+references. It is still possible to create data structures, but the language
+hides much of the memory management work.
+<p><b><i><font face="Arial">No Casting</font></i></b>
+<p>As far as I can tell, smalltalk has no equivalent of a C/C++ cast.
+<p><b><i><font face="Arial">Late binding</font></i></b>
+<p>Smalltalk makes no syntactic distinction between late and early bound
+methods (unlike C++ "virtual" methods)
+<br>&nbsp;</td>
+</tr>
+
+<tr>
+<td>
+<h3>
+<b><font face="Arial"><font size=+1>OO-C framework options</font></font></b></h3>
+<font face="Times New Roman,Times">Covered: objects (encapsulation, explicit
+construct and destruct), classes, inheritance, polymorphism</font>
+<br><font face="Times New Roman,Times">Not covered: multiple inheritance,
+automatic initialization / destruction,</font>
+<h3>
+<b><font face="Arial"><font size=+1>Strategy 1: message maps and aggregation</font></font></b></h3>
+<font face="Times New Roman,Times">Class: a struct with a pointer to a
+method table (message map). Contructor and destuctor are really initializer
+and destructor, and are invoked manually at beginning and end of lifetime.</font>
+<p><font face="Times New Roman,Times">Messages and methods: mapping table
+(first cut: use macros like MFC to create a mapping between messages and
+methods). Alternative: message map can be built at run-time (hash, tree,
+linked list) � method resolution may be slower.</font>
+<p><font face="Times New Roman,Times">Inheritance: aggregate the parent
+struct (recursively) at the beginning of the derived one, link the child
+method table to the parent and search recursively to resolve messages to
+methods</font>
+<p><font face="Times New Roman,Times">Pros and cons:</font>
+<blockquote><font face="Times New Roman,Times">+ flexible and minimal manual
+steps required</font>
+<br><font face="Times New Roman,Times">+ relatively simple � no need to
+write a preprocessor!</font>
+<br><font face="Times New Roman,Times">- all methods are late bound, run-time
+penalty</font>
+<br><font face="Times New Roman,Times">&shy; defeats compile time type
+checking, may require a single prototype for all methods</font></blockquote>
+
+<p><br><b><font face="Arial"><font size=+1>Strategy 2: manual name mangling</font></font></b>
+<br><font face="Times New Roman,Times">This is how the <a href="#samek">Samek</a>
+article handles encapsulation</font>
+<p><b><font face="Arial"><font size=+1>Strategy 3: preprocessor</font></font></b>
+<br><font face="Times New Roman,Times">This is how C++ started out.</font>
+<br>&nbsp;</td>
+</tr>
+
+<tr>
+<td><b><font face="Arial"><font size=+1>References</font></font></b>
+<ul>
+<li>
+<a NAME="robson"></a><font size=-1>David Robson, <i>Object Oriented Software
+Systems</i>. Byte, August 1981</font></li>
+
+<li>
+<a NAME="samek"></a><font size=-1>Miro Samek, <i>Portable Inheritance and
+Polymorphism in C</i>. Embedded Systems Programming, December 1997</font></li>
+</ul>
+</td>
+</tr>
+</table>
+
+</body>
+</html>
binary files /dev/null b/doc/articles/sigplan9906.doc differ
--- /dev/null
+++ b/doc/debugger.html
@@ -1,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>
+
+
--- /dev/null
+++ b/doc/dpans.html
@@ -1,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>
+
+
binary files /dev/null b/doc/graphics/4ring.gif differ
binary files /dev/null b/doc/graphics/ficl.4.128.jpg differ
binary files /dev/null b/doc/graphics/ficl.4.64.jpg differ
binary files /dev/null b/doc/graphics/ficl.4.96.jpg differ
binary files /dev/null b/doc/graphics/ficl_oop.jpg differ
binary files /dev/null b/doc/graphics/ficl_top.jpg differ
binary files /dev/null b/doc/graphics/sourceforge.jpg differ
--- /dev/null
+++ b/doc/license.html
@@ -1,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>
+
+
--- /dev/null
+++ b/doc/links.html
@@ -1,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>
+
+
--- /dev/null
+++ b/doc/locals.html
@@ -1,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>
+
--- /dev/null
+++ b/doc/oop.html
@@ -1,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>
+
+
--- /dev/null
+++ b/doc/parsesteps.html
@@ -1,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>
+
--- /dev/null
+++ b/doc/releases.html
@@ -1,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>
+
+
--- /dev/null
+++ b/doc/source/api.ht
@@ -1,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>.
+
+<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>
+
+
+<? ficlHeader1("Ficl Application Programming Interface") ?>
+
+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>
+
+<? entrypoint("void ficlSystemInformationInitialize(ficlSystemInformation *fsi)") ?>
+
+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).
+
+<? entrypoint("ficlSystem *ficlSystemCreate(ficlSystemInformation *fsi)") ?>
+
+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.
+
+
+<? entrypoint("void ficlSystemDestroy(ficlSystem *system)") ?>
+
+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>).
+
+<? entrypoint("ficlWord *ficlDictionarySetPrimitive(ficlDictionary *dictionary, char *name,  ficlCode code, ficlUnsigned8 flags)") ?>
+
+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>.
+
+
+<? entrypoint("ficlVm *ficlSystemCreateVm(ficlSystem *system)") ?>
+
+Creates a new virtual machine in the specified system.
+
+
+<? entrypoint("int ficlVmEvaluate(ficlVm *vm, char *text)") ?>
+
+ 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). 
+
+
+<? entrypoint("int ficlVmExecuteXT(ficlVm *vm, ficlWord *pFW)") ?>
+
+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. 
+
+<? entrypoint("void ficlFreeVM(ficlVm *vm)") ?>
+
+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. 
+
+<? entrypoint("ficlVm *ficlNewVM(ficlSystem *system)") ?>
+
+Create, initialize, and return a VM from the heap using
+ficlMalloc. Links the VM into the system VM list for later reclamation
+by ficlTermSystem. 
+
+<? entrypoint("ficlWord *ficlSystemLookup(ficlSystem *system, char *name)") ?>
+
+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>. 
+
+<? entrypoint("ficlDictionary *ficlSystemGetDictionary(ficlSystem *system)<br>ficlDictionary *ficlVmGetDictionary(ficlVm *system)") ?>
+
+Returns a pointer to the main system dictionary. 
+
+
+<? entrypoint("ficlDictionary *ficlSystemGetEnvironment(ficlSystem *system)") ?>
+
+Returns a pointer to the environment dictionary. This dictionary
+stores information that describes this implementation as required by the
+Standard. 
+
+
+
+
+<? entrypoint("ficlDictionary *ficlSystemGetLocals(ficlSystem *system)") ?>
+
+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>
+
+
+<? ficlHeader1("Ficl Compile-Time Constants") ?>
+
+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>
+
+
+
+<? ficlHeader2("<code>ficllocal.h</code>") ?>
+
+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.
+
+
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/debugger.ht
@@ -1,0 +1,157 @@
+<?
+ficlPageHeader("ficl debugger")
+
+ficlAddToNavBarAs("Debugger")
+
+?>
+
+<p>Ficl includes a simple step debugger for colon definitions
+and <code>DOES></code> words.
+
+
+<? ficlHeader1("Using The Ficl Debugger") ?>
+
+
+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.
+
+
+<? ficlHeader2("The <code>ON-STEP</code> Event") ?>
+
+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).
+
+
+
+<? ficlHeader3("Other Useful Words For Debugging And <code>ON-STEP</code>") ?>
+
+<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>
+
+<? ficlHeader1("Debugger Internals") ?>
+
+<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.
+
+
+<? ficlHeader1("Future Enhancements") ?>
+
+<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>
+
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/dpans.ht
@@ -1,0 +1,589 @@
+<?
+ficlPageHeader("ficl standards compliance")
+
+ficlHeader1("ANS Required Information")
+
+ficlAddToNavBarAs("ANS")
+
+?>
+
+
+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>
+
+<? ficlHeader2("ANS Forth System") ?>
+
+<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>
+
+
+<?
+def entry(heading):
+	print "<dt><b>\n" + heading + "\n</b><dd>\n"
+
+?>
+
+
+<? ficlHeader2("Implementation-defined Options") ?>
+
+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>
+
+<? entry("aligned address requirements (3.1.3.3 Addresses)") ?>
+
+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>.
+
+
+<? entry("behavior of 6.1.1320 EMIT for non-graphic characters") ?>
+
+Depends on target system, C runtime library, and your
+implementation of <code>ficlTextOut()</code>.
+
+
+<? entry("character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT") ?>
+
+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.
+
+
+<? entry("character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750 KEY)") ?>
+
+Depends on target system and implementation of <code>ficlTextOut()</code>.
+
+
+<? entry("character-aligned address requirements (3.1.3.3 Addresses)") ?>
+
+Ficl characters are one byte each. There are no alignment requirements.
+
+
+<? entry("character-set-extensions matching characteristics (3.4.2 Finding definition names)") ?>
+
+No special processing is performed on characters beyond case-folding. Therefore,
+extended characters will not match their unaccented counterparts.
+
+
+<? entry("conditions under which control characters match a space delimiter (3.4.1.1 Delimiters)") ?>
+
+Ficl uses the Standard C function <code>isspace()</code> to distinguish space characters.
+
+
+<? entry("format of the control-flow stack (3.2.3.2 Control-flow stack)") ?>
+
+Uses the data stack.
+
+
+<? entry("conversion of digits larger than thirty-five (3.2.1.2 Digit conversion)") ?>
+
+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.
+
+
+<? entry("display after input terminates in 6.1.0695 ACCEPT and 6.2.1390 EXPECT") ?>
+
+Target system dependent.
+
+
+<? entry("exception abort sequence (as in 6.1.0680 ABORT\")") ?>
+
+Calls <tt>ABORT</tt> to exit.
+
+
+<? entry("input line terminator (3.2.4.1 User input device)") ?>
+
+Target system dependent (implementation of outer loop that calls <code>ficlEvaluate()</code>).
+
+
+<? entry("maximum size of a counted string, in characters (3.1.3.4 Counted strings, 6.1.2450 WORD)") ?>
+
+Counted strings are limited to 255 characters.
+
+
+<? entry("maximum size of a parsed string (3.4.1 Parsing)") ?>
+
+Limited by available memory and the maximum unsigned value that can fit in a cell (2<sup>32</sup>-1).
+
+
+<? entry("maximum size of a definition name, in characters (3.3.1.2 Definition names)") ?>
+
+Ficl stores the first 31 characters of a definition name.
+
+
+<? entry("maximum string length for 6.1.1345 ENVIRONMENT?, in characters") ?>
+
+Same as maximum definition name length.
+
+
+<? entry("method of selecting 3.2.4.1 User input device") ?>
+
+None supported.  This is up to the target system.
+
+
+<? entry("method of selecting 3.2.4.2 User output device") ?>
+
+None supported.  This is up to the target system.
+
+
+<? entry("methods of dictionary compilation (3.3 The Forth dictionary)") ?>
+
+Okay, we don't know what this means.  If you understand what they're asking for here,
+please call the home office.
+
+
+<? entry("number of bits in one address unit (3.1.3.3 Addresses)") ?>
+
+Target system dependent, either 32 or 64 bits.
+
+
+<? entry("number representation and arithmetic (3.2.1.1 Internal number representation)") ?>
+
+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.
+
+
+<? entry("ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types, 3.1.4 Cell-pair types)") ?>
+
+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].
+
+
+<? entry("read-only data-space regions (3.3.3 Data space)") ?>
+
+None.
+
+
+<? entry("size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient regions)") ?>
+
+Default is 255.  Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>.
+
+
+<? entry("size of one cell in address units (3.1.3 Single-cell types)") ?>
+
+System dependent, generally 4.
+
+
+<? entry("size of one character in address units (3.1.2 Character types)") ?>
+
+System dependent, generally 1.
+
+
+<? entry("size of the keyboard terminal input buffer (3.3.3.5 Input buffers)") ?>
+
+This buffer is supplied by the host program.  Ficl imposes no practical limit.
+
+
+<? entry("size of the pictured numeric output string buffer (3.3.3.6 Other transient regions)") ?>
+
+Default is 255.  Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>.
+
+
+<? entry("size of the scratch area whose address is returned by 6.2.2000 PAD (3.3.3.6 Other transient regions)") ?>
+
+Default is 255.  Depends on the setting of <code>FICL_PAD_SIZE</code> in <code>ficl.h</code>.
+
+
+<? entry("system case-sensitivity characteristics (3.4.2 Finding definition names)") ?>
+
+The Ficl dictionary is not case-sensitive.
+
+
+<? entry("system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)") ?>
+
+<code>ok&gt;</code>
+
+
+<? entry("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)") ?>
+
+Symmetric.
+
+
+<? entry("values of 6.1.2250 STATE when true") ?>
+
+1.
+
+
+<? entry("values returned after arithmetic overflow (3.2.2.2 Other integer operations)") ?>
+
+System dependent. Ficl makes no special checks for overflow.
+
+
+<? entry("whether the current definition can be found after 6.1.1250 DOES&gt; (6.1.0450 :)") ?>
+No.  Definitions are unsmudged after ; only, and only then if no control structure matching problems have been detected.
+
+</dl>
+
+
+<? ficlHeader2("Ambiguous Conditions") ?>
+
+<dl>
+
+<? entry("a name is neither a valid definition name nor a valid number during text interpretation (3.4 The Forth text interpreter)") ?>
+
+Ficl calls <code>ABORT</code> then prints the name followed by <code>not found</code>.
+
+
+<? entry("a definition name exceeded the maximum length allowed (3.3.1.2 Definition names)") ?>
+
+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.
+
+
+<? entry("addressing a region not listed in 3.3.3 Data Space") ?>
+
+No problem: all addresses in Ficl are absolute.  You can reach any 32 bit address in Ficl's address space.
+
+
+<? entry("argument type incompatible with specified input parameter, e.g., passing a flag to a word expecting an n (3.1 Data types)") ?>
+
+Ficl makes no check for argument type compatibility.  Effects of a mismatch vary widely depending on the specific problem and operands.
+
+
+<? entry("attempting to obtain the execution token, (e.g., with 6.1.0070 ', 6.1.1550 FIND, etc.) of a definition with undefined interpretation semantics") ?>
+
+Ficl returns a valid token, but the result of executing that token while interpreting may be undesirable.
+
+
+<? entry("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*/)") ?>
+
+Results are target procesor dependent. Generally, Ficl makes no check for divide-by-zero. The target processor will probably throw an exception.
+
+
+<? entry("insufficient data-stack space or return-stack space (stack overflow)") ?>
+
+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.
+
+
+<? entry("insufficient space for loop-control parameters") ?>
+
+This is not checked, and bad things will happen.
+
+
+<? entry("insufficient space in the dictionary") ?>
+
+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.
+
+
+<? entry("interpreting a word with undefined interpretation semantics") ?>
+
+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.
+
+
+<? entry("modifying the contents of the input buffer or a string literal (3.3.3.4 Text-literal regions, 3.3.3.5 Input buffers)") ?>
+
+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.
+
+
+<? entry("overflow of a pictured numeric output string") ?>
+
+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.
+
+
+<? entry("parsed string overflow") ?>
+
+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.
+
+
+<? entry("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*/)") ?>
+
+Value will be truncated.
+
+
+<? entry("reading from an empty data stack or return stack (stack underflow)") ?>
+
+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.
+
+
+<? entry("unexpected end of input buffer, resulting in an attempt to use a zero-length string as a name") ?>
+
+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>
+
+<? entry("&gt;IN greater than size of input buffer (3.4.1 Parsing)") ?>
+
+Memory corruption will occur&mdash;the exact behavior is unpredictable
+because the input buffer is supplied by the host program's outer loop.
+
+
+<? entry("6.1.2120 RECURSE appears after 6.1.1250 DOES&gt;") ?>
+
+It finds the address of the definition before <code>DOES&gt;</code>
+
+
+<? entry("argument input source different than current input source for 6.2.2148 RESTORE-INPUT") ?>
+
+Not implemented.
+
+
+<? entry("data space containing definitions is de-allocated (3.3.3.2 Contiguous regions)") ?>
+
+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.
+
+
+<? entry("data space read/write with incorrect alignment (3.3.3.1 Address alignment)") ?>
+
+Target processor dependent. Consequences include: none (Intel), address error exception (68K).
+
+
+<? entry("data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860 C,)") ?>
+
+See above on data space read/write alignment.
+
+<? entry("less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)") ?>
+
+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.
+
+
+<? entry("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)") ?>
+
+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.
+
+<? entry("most recent definition does not have a name (6.1.1710 IMMEDIATE)") ?>
+
+No problem.
+
+
+<? entry("name not defined by 6.2.2405 VALUE used by 6.2.2295 TO") ?>
+
+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.
+
+<? entry("name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['], 6.2.2530 [COMPILE])") ?>
+
+Ficl prints an error message and executes <code>ABORT</code>
+
+<? entry("parameters are not of the same type (6.1.1240 DO, 6.2.0620 ?DO, 6.2.2440 WITHIN)") ?>
+
+Not detected.  Results vary depending on the specific problem.
+
+
+<? entry("6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO") ?>
+
+The word is postponed correctly.
+
+
+<? entry("string longer than a counted string returned by 6.1.2450 WORD") ?>
+
+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.)
+
+<? entry("u greater than or equal to the number of bits in a cell (6.1.1805 LSHIFT, 6.1.2162 RSHIFT)") ?>
+
+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.
+
+<? entry("word not defined via 6.1.1000 CREATE (6.1.0550 &gt;BODY, 6.1.1250 DOES&gt;)") ?>
+
+<? entry("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)") ?>
+
+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>
+
+<? ficlHeader2("Locals Implementation-Defined Options") ?>
+
+<dl>
+
+<? entry("maximum number of locals in a definition (13.3.3 Processing locals, 13.6.2.1795 LOCALS|)") ?>
+
+Default is 64&mdash;unused locals are cheap.  Change by redefining <code>FICL_MAX_LOCALS</code> (defined in <code>ficl.h</code>).
+
+</dl>
+
+
+<? ficlHeader2("Locals Ambiguous conditions") ?>
+
+<dl>
+
+<? entry("executing a named local while in interpretation state (13.6.1.0086 (LOCAL))") ?>
+
+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.
+
+<? entry("name not defined by VALUE or LOCAL (13.6.1.2295 TO)") ?>
+
+See the CORE ambiguous conditions, above (no change).
+
+</dl>
+
+
+<? ficlHeader2("Programming Tools Implementation-Defined Options") ?>
+
+
+<dl>
+
+<? entry("source and format of display by 15.6.1.2194 SEE") ?>
+
+<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>
+
+
+<? ficlHeader2("Search Order Implementation-Defined Options") ?>
+
+
+<dl>
+
+<? entry("maximum number of word lists in the search order (16.3.3 Finding definition names, 16.6.1.2197 SET-ORDER)") ?>
+
+Defaults to 16.  Can be changed by redefining <code>FICL_MAX_WORDLISTS</code> (declared in <code>ficl.h</code>).
+
+
+<? entry("minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY)") ?>
+
+Equivalent to <code>FORTH-WORDLIST 1 SET-ORDER</code>
+
+</dl>
+
+
+
+<? ficlHeader2("Search Order Ambiguous Conditions") ?>
+
+
+<dl>
+<? entry("changing the compilation word list (16.3.3 Finding definition names)") ?>
+
+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.
+
+
+<? entry("search order empty (16.6.2.2037 PREVIOUS)") ?>
+
+Ficl prints an error message if the search order underflows, and resets the order to its default state.
+
+
+<? entry("too many word lists in search order (16.6.2.0715 ALSO)") ?>
+
+Ficl prints an error message if the search order overflows, and resets the order to its default state.
+
+</dl>
+
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/ficl.ht
@@ -1,0 +1,1257 @@
+<!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">
+ <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:
+<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>
+<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>
--- /dev/null
+++ b/doc/source/generate.py
@@ -1,0 +1,244 @@
+import cStringIO
+import os
+import re
+import shutil
+import string
+import sys
+
+
+outputStart = None
+navBarEntries = {}
+
+
+
+def ficlLinkEntry(file, title):
+  print("<a href=" + file + ".html><font color=white>" + title + "</font></a><p>\n")
+
+
+
+currentNavBarName = None
+
+def ficlAddToNavBarAs(name):
+	global currentNavBarName
+	currentNavBarName = name
+
+
+def ficlPageHeader(heading):
+  outputStart.write("""<!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>""" + heading + """</TITLE>
+<style>\n
+blockquote { margin-left: 1em }\n
+</style>\n
+</HEAD>
+<BODY>
+
+<table border=0 cellspacing=0 width=100%%><tr>\n
+
+<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>
+""" + heading + """
+</i></b></font>
+</td></tr>
+
+\n<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>
+""")
+  
+  print("</td><td bgcolor=#004968 width=5></td><td valign=top><blockquote><p>\n")
+
+
+
+def ficlPageFooter():
+  print("\n</blockquote><p></td></tr></table></body></html>\n")
+
+
+
+sizeArray = [7, 5, 4, 3, 2]
+indentLevel = 0
+sections = None
+
+def ficlHeader(level, color, bgcolor, heading):
+  global sizeArray
+  size = str(sizeArray[level])
+
+  global indentLevel
+  global sections
+  while (indentLevel < level):
+    indentLevel += 1
+#    sys.stderr.write("adding 1 to indentLevel, it's now " + str(indentLevel) + "\n\n")
+    sections.append([])
+  while (indentLevel > level):
+    indentLevel -= 1
+    subheadings = sections.pop()
+#    sys.stderr.write("indentLevel is " + str(indentLevel) + ", subheadings is " + str(subheadings) + ", len(sections) is " + str(len(sections)) + ", sections is " + str(sections) + "\n\n")
+    sections[indentLevel - 1][-1][1] = subheadings
+  entry = [heading, [] ]
+#  sys.stderr.write("indentLevel is " + str(indentLevel) + ", len(sections) is " + str(len(sections)) + ", sections is " + str(sections) + "\n\n")
+#  sys.stderr.flush()
+  sections[indentLevel - 1].append(entry)
+
+  print("""
+<p>
+</blockquote><table border=0 bgcolor=""" + bgcolor + """ width=100%><tr>
+
+<td width=1em></td>
+<td>
+<font face=arial,helvetica color=""" + color + " size=" + size + "><b><i>")
+  print("<a name='" + collapse(heading) + "'>")
+  print(heading)
+  print("</a></i></b></font></td></tr></table><p><blockquote>\n")
+
+
+def ficlHeader1(heading):
+  ficlHeader(1, "#004968", "#a0a0a0", heading)
+
+def ficlHeader2(heading):
+  ficlHeader(2, "#004968", "#b8b8b8", heading)
+
+def ficlHeader3(heading):
+  ficlHeader(3, "#004968", "#d0d0d0", heading)
+
+def ficlHeader4(heading):
+  ficlHeader(4, "#004968", "#e8e8e8", heading)
+
+
+def collapse(s):
+	return string.join(s.split(), "").replace("'", "").replace("&", "").replace('"', "").replace('<', "").replace('>', "").replace('.', "").replace('?', "")
+
+def dump(f, sections):
+	for section in sections:
+		sys.stderr.write("sections is " + str(section) + "\n")
+		name = section[0]
+		f.write("<li><a href=#" + collapse(name) + "><font color=white>" + name + "</font></a>\n")
+		if len(section[1]) != 0:
+			f.write("<ul>\n")
+			dump(f, section[1])
+			f.write("</ul>\n")
+
+def process(inputfilename, outputfilename):
+	print "generating " + inputfilename
+	global indentLevel
+	indentLevel = 0
+	global sections
+	sections = []
+	global currentNavBarName
+
+	input = open(inputfilename, "r")
+	data = input.read().replace("\r", "")
+	input.close()
+	chunks = data.split("<?")
+
+	output = cStringIO.StringIO()
+
+	global outputStart
+	outputStart = cStringIO.StringIO()
+
+	stdout = sys.stdout
+
+	fauxGlobals = { }
+	fauxGlobals.update(globals())
+	fauxGlobals['__name__'] = '__ficlDocs__'
+	fauxGlobals['__doc__'] = inputfilename
+	fauxGlobals['outputStart'] = outputStart
+
+	sys.stdout = output
+	if (chunks[0] != None):
+		output.write(chunks[0])
+	for chunk in chunks[1:]:
+		(code, verbatim) = chunk.split("?>")
+		code = code.lstrip()
+		if (code[0] == "="):
+			execution = "eval"
+			code = code[1:].lstrip()
+		else:
+			execution = "exec"
+		compiled = compile(code, "[unknown]", execution)
+		if (execution == "eval"):
+			output.write(str(eval(compiled)))
+		else:
+			exec compiled
+		output.write(verbatim)
+
+	sys.stdout = stdout
+  
+
+	f = open(outputfilename, "w")
+	f.write(outputStart.getvalue())
+	f.write("<p><br>\n")
+	keys = navBarEntries.keys()
+	keys.sort()
+	for name in keys:
+		filename = navBarEntries[name]
+		f.write("<a href=" + filename + ">")
+		name = name.replace(" ", "&nbsp;")
+		f.write("<font face=arial,helvetica color=white><b>" + name + "</b></font>")
+		f.write("</a><br>\n")
+# This doesn't look as pretty as I wanted, so I'm turning it off.  --lch
+#		if (name == currentNavBarName) and (len(sections) > 0):
+#			f.write("<ul>\n")
+#			dump(f, sections[0])
+#			f.write("</ul>\n")
+			
+	f.write(output.getvalue())
+	f.close()
+
+
+
+##
+## First, find all the documents in the current directory,
+## and look for their navBar entry.
+##
+
+for filename in os.listdir("."):
+	if filename[-3:] == ".ht":
+		file = open(filename, "rb")
+		for line in file.readlines():
+			navBar = "ficlAddToNavBarAs(\""
+			if line.strip().startswith(navBar):
+				(a, name, b) = line.split('"')
+				navBarEntries[name] = filename + "ml"
+				break
+		file.close()
+
+navBarEntries["Download"] = "http://sourceforge.net/project/showfiles.php?group_id=24441"
+
+ignored = re.compile("^((.*\.pyc?)|(.*\.zip)|\.|(\.\.))$")
+
+##
+## Second, build the doc tree (in ..), processing as necessary.
+##
+def visit(unused, directory, names):
+	for file in names:
+		if ignored.search(file):
+			continue
+		input = directory + "/" + file
+		output = "../" + input
+		if input[-3:].lower() == ".ht":
+			process(input, output + "ml")
+		elif os.path.isdir(input):
+			if not os.path.isdir(output):
+				os.mkdir(output)
+		else:
+			try:
+				shutil.copy2(input, output)
+			except IOError:
+				## Ignore file-copy errors. It's probably
+				## a read-only file that doesn't change.
+				## Lazy, I know.  --lch
+				None
+
+os.path.walk(".", visit, None)
+
+
--- /dev/null
+++ b/doc/source/index.ht
@@ -1,0 +1,244 @@
+<?
+ficlPageHeader("ficl")
+
+def feature(preamble, keyfeature, postscript = ""):
+	print "<p><dt>\n" + preamble + " <b><i>" + keyfeature + "</i></b> " + postscript + "\n<dd>\n"
+
+?>
+
+
+<? ficlHeader1("What is Ficl?") ?>
+
+
+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".
+
+
+<? ficlHeader1("Ficl Features") ?>
+
+<dl>
+
+
+<? feature("Ficl is", "easy to port.") ?>
+
+<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>
+
+
+
+<? feature("Ficl 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.
+
+
+
+<? feature("Ficl is ", "easy to integrate", "into your program.") ?>
+
+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.
+
+
+
+<? feature("Ficl is", "fast.") ?>
+
+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.
+
+
+
+<? feature("Ficl is a", "complete and powerful programming language.") ?>
+
+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>
+
+
+
+<? feature("Ficl is ", "standards-compliant.") ?>
+
+Ficl conforms to the 1994 ANSI Standard for FORTH (DPANS94).
+See <a href=dpans.html>ANS Required Information</a> for
+more detail.
+
+
+<? feature("Ficl is", "extensible.") ?>
+
+Ficl is extensible both at compile-time and at run-time.
+You can add new script functions, new native functions,
+even new control structures.
+
+
+
+
+<? feature("Ficl adds ", "object oriented programming features.") ?>
+
+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.)
+
+
+
+<? feature("Ficl is", "interactive.") ?>
+
+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.
+
+
+<? feature("Ficl is", "ROMable.") ?>
+
+Ficl is designed to work in RAM based and ROM code / RAM
+data environments.
+
+
+
+<? feature("Ficl is", "safe for multithreaded programs.") ?>
+
+Ficl is reentrant and thread-safe.  After initialization,
+it does not write to any global data.
+
+
+<? feature("Ficl is ", "open-source and free.") ?>
+
+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>
+<? ficlHeader1("What's New In Ficl 4.0?") ?>
+</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.
+
+
+<? ficlHeader1("Getting Ficl") ?>
+
+You can download Ficl from the
+<a href=http://sourceforge.net/project/showfiles.php?group_id=24441>
+Ficl download page at Sourceforge</a>.
+
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/license.ht
@@ -1,0 +1,47 @@
+<?
+ficlPageHeader("ficl licensing")
+
+ficlAddToNavBarAs("Licensing")
+
+ficlHeader1("Ficl License And Disclaimer")
+
+?>
+
+<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>
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/links.ht
@@ -1,0 +1,156 @@
+<?
+ficlPageHeader("ficl links")
+
+ficlAddToNavBarAs("Links")
+
+def linkto(href):
+	print "<p><dt>\n<a href=\"" + href + "\">" + href + "</a>\n<dd>\n"
+
+?>
+
+<? ficlHeader1("Official Ficl Pages") ?>
+
+<dl>
+
+<? linkto("http://ficl.sourceforge.net") ?>
+The official web home of Ficl.
+
+<? linkto("http://sourceforge.net/project/showfiles.php?group_id=24441") ?>
+The Ficl download page.
+
+
+</dl>
+
+
+
+<? ficlHeader1("Forth Primers And Tutorials") ?>
+
+<dl>
+
+<? linkto("http://www.phys.virginia.edu/classes/551.jvn.fall01/primer.htm") ?>
+An excellent Forth primer, by Julian Nobel.
+
+<? linkto("http://ficl.sourceforge.net/pdf/Forth_Primer.pdf") ?>
+Another excellent Forth primer, by Hans Bezemer.
+
+<? linkto("http://www.taygeta.com/forth_intro/stackflo.html") ?>
+<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.
+
+<? linkto("http://www.softsynth.com/pforth/pf_tut.htm") ?>
+Phil Burk's Forth Tutorial.
+
+</dl>
+
+
+
+<? ficlHeader1("Technical Articles On Ficl And Forth") ?>
+
+<dl>
+
+<? linkto("articles/ficlddj.pdf") ?>
+Manuscript of John Sadler's article on Ficl for January 1999 <a href=http://www.ddj.com>Dr. Dobb's Journal</a>.
+
+<? linkto("articles/jwsforml.pdf") ?>
+1998 FORML Conference paper: <i>OO Programming in Ficl,</i> written and presented by John Sadler.
+
+
+<? linkto("http://www.complang.tuwien.ac.at/forth/threaded-code.html") ?>
+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".
+
+<? linkto("http://ficl.sourceforge.net/dpans/dpans.htm") ?>
+1994 Draft Proposed American National Standard for Forth.
+And surprisingly readable, as language standards go.
+
+<? linkto("http://www.taygeta.com/forthlit.html") ?>
+Forth literature index on Taygeta, a web clearinghouse of Forth links.
+
+</dl>
+
+<? ficlHeader1("Other Forth Sites Of Interest") ?>
+
+<dl>
+
+<? linkto("http://www.forth.org") ?>
+The Forth Interest Group.
+
+<? linkto("http://www.forth.com") ?>
+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>
+<? ficlHeader1("The Forth Web Ring") ?>
+<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>
+
+
+
+<? ficlHeader1("Some Software That Uses Ficl") ?>
+
+<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.)
+
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/locals.ht
@@ -1,0 +1,133 @@
+<?
+
+ficlPageHeader("local variables in Ficl")
+
+ficlAddToNavBarAs("Locals")
+
+def entry(definition, description):
+	print "<tr><td bgcolor=#e0e0e0>\n<b>" + definition + "</b>\n</td><td bgcolor=#f0f0f0>\n" + description + "\n</td></tr>\n"
+
+?>
+
+
+<? ficlHeader1("An Overview And A History") ?>
+
+
+
+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.
+
+
+<? ficlHeader1("John-Hopkins Forth Argument Syntax") ?>
+
+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>
+
+
+<? ficlHeader2("Argument Types") ?>
+
+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>
+
+<? entry("1", "single-cell") ?>
+
+<? entry("2", "double-cell") ?>
+
+<? entry("d", "double-cell") ?>
+
+<? entry("f", "floating-point (use floating stack)") ?>
+
+<? entry("i", "integer (use data stack)") ?>
+
+<? entry("s", "single-cell") ?>
+
+</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).
+
+<? ficlHeader2("A Simple Example") ?>
+
+<pre>
+: DEMONSTRATE-JH-LOCALS { c b a  f:float -- a+b f:float*2 }
+	a b +
+	2.0e float f*
+	;
+</pre>
+
+<?
+ficlPageFooter()
+?>
\ No newline at end of file
--- /dev/null
+++ b/doc/source/oop.ht
@@ -1,0 +1,1224 @@
+<?
+
+ficlPageHeader("ficl oop")
+
+ficlAddToNavBarAs("OOP In Ficl")
+
+def glossaryEntry(name, description):
+	print "<dt><code>" + name + " <i>" + description + "</i></code><dd>\n"
+
+?>
+
+<? ficlHeader1("Ficl Object Oriented Programming") ?>
+
+
+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>
+
+<? ficlHeader2("Object-Oriented Programming concepts") ?>
+
+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.
+
+<? ficlHeader2("Acknowledgements") ?>
+
+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.
+
+
+<? ficlHeader2("Ficl Object Model") ?>
+
+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>
+
+<? ficlHeader2("Ficl Object-Oriented Syntax Tutorial") ?>
+<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.
+
+<? ficlHeader3("Methods And Messages") ?>
+
+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>
+
+<? ficlHeader2("Tutorial") ?>
+
+(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>
+
+<? ficlHeader2("Early Binding") ?>
+
+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.
+
+<? ficlHeader2("More About Instance Variables") ?>
+
+<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.
+
+
+<? ficlHeader1("Ficl String Classes") ?>
+<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>
+
+
+<? ficlHeader2("OOP Glossary") ?>
+
+<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>
+
+<? glossaryEntry("-->", "( instance class \"method-name\" -- xn )") ?>
+
+Late binding: looks up and executes the given method in the context of
+the class on top of the stack.
+
+<? glossaryEntry("C->", "( instance class \"method-name\" -- xn exc )") ?>
+
+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.
+
+<? glossaryEntry("MY=>", "compilation: ( \"method-name\" -- )  execution: ( instance class -- xn )") ?>
+
+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.
+
+<? glossaryEntry("MY=[", "compilation: ( \"obj1 obj2 .. method ]\" -- ) execution: ( instance class -- xn )") ?>
+
+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.
+
+<? glossaryEntry("=>", "compilation: ( class metaclass \"method-name\" -- ) execution: ( instance class -- xn )") ?>
+
+Early binding: compiles code to execute the method of the class specified
+at compile time.
+
+<? glossaryEntry("do-do-instance", "") ?>
+
+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.
+
+<? glossaryEntry("exec-method", "( instance class c-address u -- xn )") ?>
+
+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.
+
+<? glossaryEntry("find-method-xt", "( class \"method-name\" -- class xt )") ?>
+
+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.
+
+<? glossaryEntry("lookup-method", "( class c-address u -- class xt )") ?>
+
+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.
+
+<? glossaryEntry("parse-method", "compilation: ( \"method-name\" -- ) execution: ( -- c-address u )") ?>
+
+Parse <code>"method-name"</code> from the input stream and compile code to push its length
+and address when the enclosing definition runs.
+</dl>
+
+<? ficlHeader3("Instance Variable Glossary") ?>
+<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>
+
+<? glossaryEntry("CELL:", "compilation: ( offset \"name\" -- offset ) execution: ( -- cell-address )") ?>
+
+Create an untyped instance variable one cell wide. The instance variable
+leaves its payload's address when executed.
+
+<? glossaryEntry("CELLS:", "compilation: ( offset nCells \"name\" -- offset' ) execution: ( -- cell-address )") ?>
+
+Create an untyped instance variable <code>nCells</code> cells wide.
+
+<? glossaryEntry("CHAR:", "compilation: ( offset \"name\" -- offset' ) execution: ( -- cell-address )") ?>
+
+Create an untyped member variable one character wide.
+
+<? glossaryEntry("CHARS:", "compilation: ( offset nChars \"name\" -- offset' ) execution: ( -- cell-address )") ?>
+
+Create an untyped member variable <code>nChars</code> characters wide.
+
+<? glossaryEntry("OBJ:", "compilation: ( offset class metaclass \"name\" -- offset' ) execution: ( -- instance class )") ?>
+
+Aggregate an uninitialized instance of <code>CLASS</code> as a member variable
+of the class under construction.
+
+<? glossaryEntry("ARRAY:", "compilation: ( offset nObjects class metaclass \"name\" -- offset' ) execution: ( -- instance class )") ?>
+<a NAME="arraycolon"></a>
+
+Aggregate an uninitialized array of instances of the class specified as
+a member variable of the class under construction.
+
+<? glossaryEntry("EXAMPLEREF:", "compilation: ( offset class metaclass \"name\" -- offset' ) execution: ( -- ref-instance ref-class )") ?>
+
+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>
+<? ficlHeader1("Class Methods Glossary") ?>
+
+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>
+
+<? glossaryEntry("INSTANCE", "( class metaclass \"name\" -- instance class )") ?>
+
+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>
+
+<? glossaryEntry("NEW", "( class metaclass \"name\" -- )") ?>
+
+Create an initialized instance of class, giving it the name specified.
+This method calls <code>INIT</code> to perform initialization.
+
+<? glossaryEntry("ARRAY", "( nObjects class metaclass \"name\" -- nObjects instance class )") ?>
+
+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>
+
+
+<? glossaryEntry("NEW-ARRAY", "( nObjects class metaclass \"name\" -- )") ?>
+
+Creates an initialized array of <code>nObjects</code> instances of the class.
+Same syntax as <code>ARRAY</code>.
+
+<a NAME="alloc"></a>
+<? glossaryEntry("ALLOC", "( class metaclass -- instance class )") ?>
+
+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>
+<? glossaryEntry("ALLOC-ARRAY", "( nObjects class metaclass -- instance class )") ?>
+
+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>
+<? glossaryEntry("ALLOT", "( class metaclass -- instance class )") ?>
+
+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>
+<? glossaryEntry("ALLOT-ARRAY", "( nObjects class metaclass -- instance class )") ?>
+
+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.
+
+<? glossaryEntry("REF", "( instance-address class metaclass \"name\" -- )") ?>
+
+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.
+
+
+<? glossaryEntry("SUB", "( class metaclass -- old-wid address[size] size )") ?>
+
+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>
+
+<? glossaryEntry(".SIZE", "( class metaclass -- instance-size )") ?>
+
+Returns address of the class's instance size field, in address units. This
+is a metaclass member variable.
+
+<? glossaryEntry(".SUPER", "( class metaclass -- superclass )") ?>
+
+Returns address of the class's superclass field. This is a metaclass member
+variable.
+
+<? glossaryEntry(".WID", "( class metaclass -- wid )") ?>
+
+Returns the address of the class's wordlist ID field. This is a metaclass
+member variable.
+
+<? glossaryEntry("GET-SIZE", "( -- instance-size )") ?>
+
+Returns the size of an instance of the class in address units. Imeplemented
+as follows:
+
+<pre>
+: GET-SIZE   METACLASS => .SIZE @ ;
+</pre>
+
+<? glossaryEntry("GET-WID", "( -- wid )") ?>
+
+Returns the wordlist ID of the class. Implemented as:
+
+<pre>
+: GET-WID   METACLASS => .WID @ ;
+</pre>
+
+<? glossaryEntry("GET-SUPER", "( -- superclass )") ?>
+
+Returns the class's superclass. Implemented as
+
+<pre>
+: GET-SUPER   METACLASS => .super @ ;
+</pre>
+
+
+<? glossaryEntry("ID", "( class metaclass -- c-address u )") ?>
+
+Returns the address and length of a string that names the class.
+
+
+<? glossaryEntry("METHODS", "( class metaclass -- )") ?>
+
+Lists methods of the class and all its superclasses.
+
+
+<? glossaryEntry("OFFSET-OF", "( class metaclass \"name\" -- offset )") ?>
+
+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>
+
+
+<? glossaryEntry("PEDIGREE", "( class metaclass -- )") ?>
+
+
+Lists the pedigree of the class (inheritance trail).
+
+<? glossaryEntry("SEE", "( class metaclass \"name\" -- )") ?>
+
+Decompiles the specified method&mdash;obect version of <code>SEE</code>, from the
+<code>TOOLS</code> wordset.
+
+</dl>
+
+<? ficlHeader1("<code>OBJECT</code> Base-Class Methods Glossary") ?>
+<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>
+
+<? glossaryEntry("INIT", "( instance class -- )") ?>
+
+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.
+
+<? glossaryEntry("ARRAYINIT", "( nObjects instance class -- )") ?>
+
+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.
+
+<? glossaryEntry("FREE", "( instance class -- )") ?>
+
+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>.
+
+<? glossaryEntry("CLASS", "( instance class -- class metaclass )") ?>
+
+Convert an object signature into that of its class. Useful for calling
+class methods that have no object aliases.
+
+<? glossaryEntry("SUPER", "( instance class -- instance superclass )") ?>
+
+Upcast an object to its parent class. The parent class of <code>OBJECT</code>
+is zero. Useful for invoking an overridden parent class method.
+
+<? glossaryEntry("PEDIGREE", "( instance class -- )") ?>
+
+Display an object's pedigree&mdash;its chain of inheritance. This is an alias
+for the corresponding class method.
+
+<? glossaryEntry("SIZE", "( instance class -- instance-size )") ?>
+
+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>.
+
+<? glossaryEntry("METHODS", "( instance class -- )") ?>
+
+Class method alias. Displays the list of methods of the class and all superclasses
+of the instance.
+
+<? glossaryEntry("INDEX", "( n instance class -- instance[n] class )") ?>
+
+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.
+
+<? glossaryEntry("NEXT", "( instance[n] class -- instance[n+1] )") ?>
+
+Convert an array-object signature into the signature of the next
+object in the array. No check for bounds overflow.
+
+<? glossaryEntry("PREV", "( instance[n] class -- instance[n-1] class )") ?>
+
+Convert an object signature into the signature of the previous object
+in the array. No check for bounds underflow.
+
+</dl>
+
+
+<? ficlHeader2("Supplied Classes") ?>
+<a NAME="stockclasses"></a>
+
+For more information on theses classes, see <code>softcore/classes.fr</code>.
+
+<dl>
+
+<? glossaryEntry("METACLASS", "") ?>
+
+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.
+
+<? glossaryEntry("OBJECT", "") ?>
+
+Mother of all Ficl objects. Defines default initialization and array indexing
+methods. Defined in <code>softcore/oo.fr</code>. Methods described above.
+
+<? glossaryEntry("C-REF", "") ?>
+
+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>
+
+<? glossaryEntry("GET", "( instance class -- ref-instance ref-class )") ?>
+Push the referenced object value on the stack.
+
+<? glossaryEntry("SET", "( ref-instance ref-class instance class -- )") ?>
+Set the referenced object being held.
+
+<? glossaryEntry(".INSTANCE", "( instance class -- a-address )") ?>
+Cell member that holds the instance.
+
+<? glossaryEntry(".CLASS", "( instance class -- a-address )") ?>
+Cell member that holds the class.
+
+</dl>
+
+<? glossaryEntry("C-BYTE", "") ?>
+
+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>
+
+<? glossaryEntry("GET", "( instance class -- byte )") ?>
+Push the object's value on the stack.
+
+<? glossaryEntry("SET", "( byte instance class -- )") ?>
+Set the object's value from the stack.
+
+<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?>
+Member holds instance's value.
+
+</dl>
+
+<? glossaryEntry("C-2BYTE", "") ?>
+
+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>
+
+<? glossaryEntry("GET", "( instance class -- 2byte )") ?>
+Push the object's value on the stack.
+
+<? glossaryEntry("SET", "( 2byte instance class -- )") ?>
+Set the object's value from the stack.
+
+<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?>
+Member holds instance's value.
+
+</dl>
+
+<? glossaryEntry("C-4BYTE", "") ?>
+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>
+
+<? glossaryEntry("GET", "( instance class -- 4byte )") ?>
+Push the object's value on the stack.
+
+<? glossaryEntry("SET", "( 4byte instance class -- )") ?>
+Set the object's value from the stack.
+
+<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?>
+Member holds instance's value.
+
+</dl>
+
+<? glossaryEntry("C-CELL", "") ?>
+
+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>
+
+<? glossaryEntry("GET", "( instance class -- 4byte )") ?>
+Push the object's value on the stack.
+
+<? glossaryEntry("SET", "( 4byte instance class -- )") ?>
+Set the object's value from the stack.
+
+<? glossaryEntry(".PAYLOAD", "( instance class -- address )") ?>
+Member holds instance's value.
+
+</dl>
+
+<? glossaryEntry("C-PTR", "") ?>
+
+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>
+
+<? glossaryEntry(".ADDR", "( instance class -- a-address )") ?>
+Member variable, holds the pointer address.
+
+<? glossaryEntry("GET-PTR", "( instance class -- pointer )") ?>
+Pushes the pointer address.
+
+<? glossaryEntry("SET-PTR", "( pointer instance class -- )") ?>
+Sets the pointer address.
+
+<? glossaryEntry("INC-PTR", "( instance class -- )") ?>
+Adds <code>@SIZE</code> to the pointer address.
+
+<? glossaryEntry("DEC-PTR", "( instance class -- )") ?>
+Subtracts <code>@SIZE</code> to the pointer address.
+
+<? glossaryEntry("INDEX-PTR", "( i instance class -- )") ?>
+Adds <code>i * @SIZE</code> to the pointer address.
+
+</dl>
+
+<? glossaryEntry("C-BYTEPTR", "") ?>
+
+Pointer to byte derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<? glossaryEntry("@SIZE", "( instance class -- size )") ?>
+Push size of the pointed-to object.
+
+<? glossaryEntry("GET", "( instance class -- byte )") ?>
+Pushes the pointer's referent byte.
+
+<? glossaryEntry("SET", "( byte instance class -- )") ?>
+Stores <code>byte</code> at the pointer address.
+
+</dl>
+
+
+
+<? glossaryEntry("C-2BYTEPTR", "") ?>
+
+Pointer to 2byte derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<? glossaryEntry("@SIZE", "( instance class -- size )") ?>
+Push size of the pointed-to object.
+
+<? glossaryEntry("GET", "( instance class -- 2byte )") ?>
+Pushes the pointer's referent 2byte.
+
+<? glossaryEntry("SET", "( 2byte instance class -- )") ?>
+Stores <code>2byte</code> at the pointer address.
+
+</dl>
+
+
+
+<? glossaryEntry("C-4BYTEPTR", "") ?>
+
+Pointer to 4byte derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<? glossaryEntry("@SIZE", "( instance class -- size )") ?>
+Push size of the pointed-to object.
+
+<? glossaryEntry("GET", "( instance class -- 4byte )") ?>
+Pushes the pointer's referent 4byte.
+
+<? glossaryEntry("SET", "( 4byte instance class -- )") ?>
+Stores <code>4byte</code> at the pointer address.
+
+</dl>
+
+
+<? glossaryEntry("C-CELLPTR", "") ?>
+
+Pointer to cell derived from <code>C-PTR</code>. Methods and members:
+
+<dl>
+
+<? glossaryEntry("@SIZE", "( instance class -- size )") ?>
+Push size of the pointed-to object.
+
+<? glossaryEntry("GET", "( instance class -- cell )") ?>
+Pushes the pointer's referent cell.
+
+<? glossaryEntry("SET", "( cell instance class -- )") ?>
+Stores <code>cell</code> at the pointer address.
+
+</dl>
+
+
+
+<? glossaryEntry("C-STRING", "") ?>
+
+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>
+
+<? glossaryEntry("GET", "( instance class -- c-address u )") ?>
+Pushes the string buffer's contents as a <code>C-ADDR U</code> style string.
+
+<? glossaryEntry("SET", "( c-address u instance class -- )") ?>
+Sets the string buffer's contents to a new value.
+
+<? glossaryEntry("CAT", "( c-address u instance class -- )") ?>
+Concatenates a string to the string buffer's contents.
+
+<? glossaryEntry("COMPARE", "( c-address u instance class -- result )") ?>
+Lexical compiration of a string to the string buffer's contents.
+Return value is the same as the FORTH function <code>COMPARE</code>.
+
+<? glossaryEntry("TYPE", "( instance class -- )") ?>
+Prints the contents of the string buffer to the output stream.
+
+<? glossaryEntry("HASHCODE", "( instance class -- i )") ?>
+Returns a computed hash based on the contents of the string buffer.
+
+<? glossaryEntry("FREE", "( instance class -- )") ?>
+Releases the internal buffer.
+
+</dl>
+
+
+<? glossaryEntry("C-HASHSTRING", "") ?>
+
+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>
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/parsesteps.ht
@@ -1,0 +1,234 @@
+<?
+ficlPageHeader("ficl parse steps")
+
+ficlAddToNavBarAs("Parse Steps")
+
+def entry(definition):
+	print "<dt>\n<code>" + definition + "</code>\n<dd>\n"
+
+?>
+
+
+<? ficlHeader1("Parse Steps") ?>
+
+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.
+
+
+<? ficlHeader2("The Default Ficl Parse Chain") ?>
+
+These is the default Ficl parser chain, shown in order.
+
+<dl>
+
+<? entry("?word") ?>
+
+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>.
+
+<? entry("?prefix") ?>
+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>.
+
+<? entry("?number") ?>
+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>.
+
+<? entry("?float") ?>
+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>
+
+
+
+<? ficlHeader2("Adding A Parse Step From Within Ficl") ?>
+<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>
+
+<? ficlHeader2("Adding A Native Parse Step") ?>
+
+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.
+
+
+<? ficlHeader1("Prefixes") ?>
+
+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.
+
+
+<? ficlHeader1("Notes") ?>
+
+<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>
+
+<? ficlHeader1("Parser Glossary") ?>
+
+<dl>
+
+<? entry("PARSE-ORDER  ( -- )") ?>
+
+Prints the list of parse steps, in the order in which they are called.
+
+<? entry("ADD-PARSE-STEP  ( xt -- )") ?>
+
+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>).
+
+<? entry("SHOW-PREFIXES  ( -- )") ?>
+
+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.
+
+<? entry("START-PREFIXES  ( -- )") ?>
+
+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.)
+
+<? entry("END-PREFIXES  ( -- )") ?>
+
+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>
+
+
+<?
+ficlPageFooter()
+?>
\ No newline at end of file
--- /dev/null
+++ b/doc/source/releases.ht
@@ -1,0 +1,1003 @@
+<?
+ficlPageHeader("ficl release history")
+
+ficlAddToNavBarAs("Release History")
+
+def ficlVersion(s):
+	ficlHeader1(s)
+
+?>
+
+<? ficlVersion("Version 4.0.31") ?>
+<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>
+
+<? ficlVersion("Version 4.0.30") ?>
+
+<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>
+
+<? ficlVersion("Version 4.0.29") ?>
+
+<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>
+
+<? ficlVersion("Version 4.0.28") ?>
+
+<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>
+
+<? ficlVersion("Version 4.0.27") ?>
+<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>
+
+<? ficlVersion("Version 4.0.26") ?>
+<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>
+
+<? ficlVersion("Version 4.0.25") ?>
+<ul>
+
+<li>
+First pass at support for "oldnames", and namespace policing.
+
+</ul>
+
+<? ficlVersion("Version 4.0.23") ?>
+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>
+
+<? ficlVersion("Version 3.03") ?>
+<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>
+
+
+
+<? ficlVersion("Version 3.02") ?>
+<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>
+
+<? ficlVersion("Version 3.01") ?>
+<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>
+
+<? ficlVersion("Version 3.00a") ?>
+
+<ul>
+<li>
+Fixed broken oo.fr by commenting out vcall stuff using FICL_WANT_VCALL. Vcall is still broken.
+
+</ul>
+
+<? ficlVersion("Version 3.00") ?>
+
+<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>
+
+<? ficlVersion("Version 2.06") ?>
+<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>
+
+<? ficlVersion("Version 2.05") ?>
+<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>
+
+<? ficlVersion("Version 2.04") ?>
+
+<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>
+
+
+<? ficlVersion("Version 2.03") ?>
+
+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>
+
+
+<? ficlVersion("Version 2.02") ?>
+
+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>
+
+
+<? ficlVersion("Version 2.01") ?>
+
+<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>
+
+
+<? ficlVersion("Version 2.0") ?>
+
+<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>
+
+
+
+<? ficlPageFooter() ?>
--- /dev/null
+++ b/doc/source/upgrading.ht
@@ -1,0 +1,349 @@
+<?
+
+ficlPageHeader("upgrading ficl")
+
+ficlAddToNavBarAs("Upgrading To 4.0")
+
+def startoldvsnew(extra = None):
+	print "<table width=100%><tr>\n"
+	print "<td bgcolor=#d0d0f0><b>old name</b></td>\n"
+	print "<td bgcolor=#e0e0ff><b>new name</td>\n"
+	if extra != None:
+		print "<td bgcolor=#d0d0f0><b>" + extra + "</td>\n"
+	print "</tr>\n"
+
+def oldvsnew(old, new, extra = None):
+	print "<tr>\n"
+	print "<td bgcolor=#e0e0e0><code>" + old + "</code></td>\n"
+	print "<td bgcolor=#f0f0f0><code>" + new + "</code></td>\n"
+	if extra != None:
+		print "<td bgcolor=#e0e0e0><code>" + extra + "</code></td>\n"
+	print"</tr>\n\n"
+
+
+def endoldvsnew():
+	print "</table><p>\n"
+
+?>
+
+Ficl 4.0 is smaller, faster, and more capable than any previous
+version.  For more information on why Ficl 4.0 is so gosh-darned
+swell, see the <a href=index.html#WhatsNewInFicl4.0>What's New In Ficl 4.0?</a>
+section of the overview.
+<p>
+
+
+Since the Ficl API has changed so dramatically, you can't just drop
+the new Ficl source.  You have two basic choices:
+<a href=#compatibility>use the <code>FICL_WANT_COMPATIBILITY</code> support</a>, and
+<a href=#newapi>switching to the new API</a>.
+<p>
+
+Note that using <i>either</i> of these choices <i>requires</i>
+that you recompile your application.  You cannot build Ficl 4 into
+a shared library or DLL and use it with an application expecting
+Ficl 3.0.  Stated another way: Ficl 4 is <i>source</i> compatible
+but not <i>binary</i> compatible with Ficl 3.
+
+
+<a name=oldnames>
+<? ficlHeader1("Using <code>FICL_WANT_COMPATIBILITY</code>") ?>
+</a>
+
+
+If you want to get Ficl 4.0 up and running in your project as quickly
+as possible, <code>FICL_WANT_COMPATIBILITY</code> is what you'll want to use.
+There are two easy steps, one of which you might be able to skip:
+<p>
+
+<ol>
+
+<li>
+Set the C preprocessor constant <code>FICL_WANT_COMPATIBILITY</code> to 1.
+The best way is by adding the following line to <code>ficllocal.h</code>:
+<pre>
+	#define FICL_WANT_COMPATIBILITY (1)
+</pre>
+
+
+<li>
+
+<i>If</i> you use a custom <code>ficlTextOut()</code> function, you'll
+have to rename it, and explicitly specify it to Ficl.  Renaming it is
+necessary, because the Ficl compatibility layer also provides one for
+code that called <code>ficlTextOut()</code> directly (instead of calling
+<code>vmTextOut()</code> as it should have).
+We recommend renaming your function to <code>ficlTextOutLocal()</code>, as
+we have have provided a prototype for this function for you in <code>ficlcompatibility.h</code>.
+This will save you the trouble of defining your own prototype, ensuring you get
+correct name decoration / linkage, etc.
+
+<p>
+
+There are two methods you can use to specify your <code>ficlTextOut()</code>
+function:
+<ol>
+
+<li>
+Specify it in the <code>FICL_INIT_INFO</code> structure passed in to
+<code>ficlInitSystem()</code>.  This is the preferred method, as it ensures
+you will see the results of Ficl's initialization code, and it will be
+automatically passed in to every newly created VM.
+
+<li>
+Set it explicitly in every VM by calling <code>vmSetTextOut()</code> and
+passing it in.
+
+</ol>
+<p>
+
+<b>Note:</b>  Any other method, such as setting it by hand in the
+<code>FICL_SYSTEM</code> or <code>FICL_VM</code> structures,
+will <b>not</b> work.  There is a special compatibility layer for old-style
+<code>OUTFUNC</code> functions, but it is only invoked properly when you
+use one of the two methods mentioned above.
+
+
+</ol>
+
+<p>
+
+This <i>should</i> be sufficient for you to recompile-and-go
+with Ficl 4.  If it's not, please let us know, preferably including a
+suggested solution to the problem.
+
+
+<a name=newapi>
+<? ficlHeader1("Using The New API") ?>
+</a>
+
+Since most (all?) of the external symbols have changed names since the 3.0 series,
+here is a quick guide to get you started on renaming everything.  This is by no
+means an exhaustive list; this is meant to guide you towards figuring out what
+the new name <i>should</i> be.  (After all, part of the point of this massive
+renaming was to make all the external symbols consistent.)
+<p>
+
+
+
+
+<? ficlHeader2("Types") ?>
+
+Every external type has been renamed.  They all begin with the
+word <code>ficl</code>, and they use mixed case (instead of all upper-case,
+which is now reserved for macros).  Also, the confusingly-named
+string objects have been renamed:
+<code>FICL_STRING</code> is now <code>ficlCountedString</code>, as it
+represents a "counted string" in the language, and
+the more commonly-used <code>STRINGINFO</code> is now simply
+<code>ficlString</code>.
+
+<?
+
+startoldvsnew()
+
+oldvsnew("FICL_SYSTEM", "ficlSystem")
+oldvsnew("FICL_VM", "ficlVm")
+oldvsnew("FICL_SYSTEM_INFO", "ficlSystemInformation")
+oldvsnew("FICL_WORD", "ficlWord")
+oldvsnew("IPTYPE", "ficlIp")
+oldvsnew("FICL_CODE", "ficlPrimitive")
+oldvsnew("OUTFUNC", "ficlOutputFunction")
+oldvsnew("FICL_DICTIONARY", "ficlDictionary")
+oldvsnew("FICL_STACK", "ficlStack")
+oldvsnew("STRINGINFO", "ficlString")
+oldvsnew("FICL_STRING", "ficlCountedString")
+
+endoldvsnew()
+
+?>
+
+<? ficlHeader2("Structure Members") ?>
+
+In addition, many structure names have changed.  To help ease the heartache,
+we've also added some accessor macros.  So, in case they change in the future,
+your code might still compile (hooray!).
+<?
+
+startoldvsnew("accessor")
+
+oldvsnew("pExtend", "context", "ficlVmGetContext(), ficlSystemGetContext()")
+oldvsnew("pStack", "dataStack", "ficlVmGetDataStack()")
+oldvsnew("fStack", "floatStack", "ficlVmGetFloatStack()")
+oldvsnew("rStack", "returnStack", "ficlVmGetReturnStack()")
+
+endoldvsnew()
+
+?>
+
+<? ficlHeader2("Callback Functions") ?>
+
+Text output callbacks have changed in two major ways:
+
+<ul>
+
+<li>
+They no longer take a VM pointer; they now take a <code>ficlCallback</code> structure.
+This allows output to be printed before a VM is defined, or in circumstances where a
+VM may not be defined (such as an assertion failure in a <code>ficlSystem...()</code> function).
+
+<li>
+They no longer take a flag indicating whether or not to add a "newline".
+Instead, the function must output a newline whenever it encounters
+a <code>\n</code> character in the text.
+
+</ul>
+
+If you don't want to rewrite your output function yet, you can
+"thunk" the new-style call to the old-style.  Just pass in <code>ficlOldnamesCallbackTextOut</code>
+as the name of the output function for the system and VM, and then set 
+the <code>thunkedTextout</code> member of the <code>ficlSystem</code>
+or <code>ficlVm</code> to your old-style text output function.
+
+
+<? ficlHeader2("Renamed Macros") ?>
+
+<?
+
+startoldvsnew()
+
+oldvsnew("PUSHPTR(p)", "ficlStackPushPointer(vm->dataStack, p)")
+oldvsnew("POPUNS()", "ficlStackPopUnsigned(vm->dataStack)")
+oldvsnew("GETTOP()", "ficlStackGetTop(vm->dataStack)")
+
+oldvsnew("FW_IMMEDIATE", "FICL_WORD_IMMEDIATE")
+oldvsnew("FW_COMPILE", "FICL_WORD_COMPILE_ONLY")
+
+oldvsnew("VM_INNEREXIT", "FICL_VM_STATUS_INNER_EXIT")
+oldvsnew("VM_OUTOFTEXT", "FICL_VM_STATUS_OUT_OF_TEXT")
+oldvsnew("VM_RESTART", "FICL_VM_RESTART")
+
+
+endoldvsnew()
+
+?>
+
+<? ficlHeader2("<code>ficllocal.h</code>") ?>
+
+One more note about macros.  Ficl now ships with a standard place for
+you to tweak the Ficl compile-time preprocessor switches  such as
+<code>FICL_WANT_COMPATIBILITY</code> and <code>FICL_WANT_FLOAT</code>.
+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.
+
+
+<? ficlHeader2("Renamed Functions") ?>
+
+Every function that deals primarily with a particular structure
+is now named after that structure.  For instance, any function
+that takes a <code>ficlSystem</code> as its first argument is
+named <code>ficlSystem<i>Something</i>()</code>.  Any function
+that takes a <code>ficlVm</code> as its first argument is
+named <code>ficlVm<i>Something</i>()</code>.  And so on.
+<p>
+
+Also, functions that create a new object are always
+called <code>Create</code> (not <code>Alloc</code>, <code>Allot</code>, <code>Init</code>, or <code>New</code>).
+Functions that create a new object are always
+called <code>Destroy</code> (not <code>Free</code>, <code>Term</code>, or <code>Delete</code>).
+<p>
+
+
+<?
+
+startoldvsnew()
+
+oldvsnew("ficlInitSystem()", "ficlSystemCreate()")
+oldvsnew("ficlTermSystem()", "ficlSystemDestroy()")
+oldvsnew("ficlNewVM()", "ficlSystemCreateVm()")
+oldvsnew("ficlFreeVM()", "ficlVmDestroy()")
+oldvsnew("dictCreate()", "ficlDictionaryCreate()")
+oldvsnew("dictDelete()", "ficlDictionaryDestroy()")
+
+endoldvsnew()
+
+?>
+<p>
+
+All functions exported by Ficl now start with the word <code>ficl</code>.
+This is a <i>feature</i>, as it means the Ficl project will no longer
+pollute your namespace.
+
+<?
+
+startoldvsnew()
+
+oldvsnew("PUSHPTR(p)", "ficlStackPushPointer(vm->dataStack, p)")
+oldvsnew("POPUNS()", "ficlStackPopUnsigned(vm->dataStack)")
+oldvsnew("GETTOP()", "ficlStackGetTop(vm->dataStack)")
+oldvsnew("ltoa()", "ficlLtoa()")
+oldvsnew("strincmp()", "ficlStrincomp()")
+
+endoldvsnew()
+
+?>
+
+
+
+<? ficlHeader2("Removed Functions") ?>
+
+A few entry points have simply been removed.
+For instance, functions specifically managing a system's <code>ENVIRONMENT</code>
+settings have been removed, in favor of managing the system's
+<code>environment</code> dictionary directly:
+<?
+
+startoldvsnew()
+
+oldvsnew("ficlSystemSetEnvironment(system)", "ficlDictionarySetConstant(ficlSystemGetEnvironment(system), ...)")
+oldvsnew("ficlSystemSet2Environment(system)", "ficlDictionarySet2Constant(ficlSystemGetEnvironment(system), ...)")
+
+endoldvsnew()
+
+?>
+
+
+In a similar vein, <code>ficlSystemBuild()</code> has been removed in favor
+of using <code>ficlDictionarySetPrimitive()</code> directly:
+
+<?
+startoldvsnew()
+oldvsnew("ficlSystemBuild(system, ...)", "ficlDictionarySetPrimitive(ficlSystemGetDictionary(system), ...)")
+endoldvsnew()
+?>
+
+Finally, there is no <i>exact</i> replacement for <code>ficlExec()</code>.  99% of the code
+that called <code>ficlExec()</code> never bothered to manage <code>SOURCE-ID</code> properly.
+If you were calling <code>ficlExec()</code>, and you weren't changing <code>SOURCE-ID</code>
+(or <code>vm->sourceId</code>) to match, you should replace those calls with <code>ficlVmEvaluate()</code>,
+which will manage <code>SOURCE-ID</code> for you.
+<p>
+
+There <i>is</i> a function that takes the place of <code>ficlExec()</code> which doesn't change
+<code>SOURCE-ID</code>: <code>ficlVmExecuteString()</code>.  However, instead of taking a
+straight C string (a <code>char *</code>), it takes a <code>ficlString *</code> as its
+code argument.  (This is to discourage its use.)
+
+
+<?
+ficlHeader1("Internal Changes")
+?>
+
+<b>Note:</b> none of these changes should affect you.  If they do, there's probably
+a problem somewhere.  Either Ficl's API doesn't abstract away something enough, or
+you are approaching a problem the wrong way.  Food for thought.
+<p>
+
+There's only one internal change worth noting here.
+The top value on a Ficl stack used to be at (to use the modern structure names)
+<code>stack->top[-1]</code>.  It is now at <code>stack->top[0]</code>.
+In other words, the "stack top" pointer used to point <i>past</i> the top
+element; it now points <i>at</i> the top element.  (Pointing <i>at</i> the
+top element is not only less confusing, it is also faster.)
+
+</body>
+</html>
--- /dev/null
+++ b/doc/upgrading.html
@@ -1,0 +1,808 @@
+<!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>upgrading 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>
+upgrading 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>
+
+
+
+Ficl 4.0 is smaller, faster, and more capable than any previous
+version.  For more information on why Ficl 4.0 is so gosh-darned
+swell, see the <a href=index.html#WhatsNewInFicl4.0>What's New In Ficl 4.0?</a>
+section of the overview.
+<p>
+
+
+Since the Ficl API has changed so dramatically, you can't just drop
+the new Ficl source.  You have two basic choices:
+<a href=#compatibility>use the <code>FICL_WANT_COMPATIBILITY</code> support</a>, and
+<a href=#newapi>switching to the new API</a>.
+<p>
+
+Note that using <i>either</i> of these choices <i>requires</i>
+that you recompile your application.  You cannot build Ficl 4 into
+a shared library or DLL and use it with an application expecting
+Ficl 3.0.  Stated another way: Ficl 4 is <i>source</i> compatible
+but not <i>binary</i> compatible with Ficl 3.
+
+
+<a name=oldnames>
+
+<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='UsingcodeFICL_WANT_COMPATIBILITY/code'>
+Using <code>FICL_WANT_COMPATIBILITY</code>
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+</a>
+
+
+If you want to get Ficl 4.0 up and running in your project as quickly
+as possible, <code>FICL_WANT_COMPATIBILITY</code> is what you'll want to use.
+There are two easy steps, one of which you might be able to skip:
+<p>
+
+<ol>
+
+<li>
+Set the C preprocessor constant <code>FICL_WANT_COMPATIBILITY</code> to 1.
+The best way is by adding the following line to <code>ficllocal.h</code>:
+<pre>
+	#define FICL_WANT_COMPATIBILITY (1)
+</pre>
+
+
+<li>
+
+<i>If</i> you use a custom <code>ficlTextOut()</code> function, you'll
+have to rename it, and explicitly specify it to Ficl.  Renaming it is
+necessary, because the Ficl compatibility layer also provides one for
+code that called <code>ficlTextOut()</code> directly (instead of calling
+<code>vmTextOut()</code> as it should have).
+We recommend renaming your function to <code>ficlTextOutLocal()</code>, as
+we have have provided a prototype for this function for you in <code>ficlcompatibility.h</code>.
+This will save you the trouble of defining your own prototype, ensuring you get
+correct name decoration / linkage, etc.
+
+<p>
+
+There are two methods you can use to specify your <code>ficlTextOut()</code>
+function:
+<ol>
+
+<li>
+Specify it in the <code>FICL_INIT_INFO</code> structure passed in to
+<code>ficlInitSystem()</code>.  This is the preferred method, as it ensures
+you will see the results of Ficl's initialization code, and it will be
+automatically passed in to every newly created VM.
+
+<li>
+Set it explicitly in every VM by calling <code>vmSetTextOut()</code> and
+passing it in.
+
+</ol>
+<p>
+
+<b>Note:</b>  Any other method, such as setting it by hand in the
+<code>FICL_SYSTEM</code> or <code>FICL_VM</code> structures,
+will <b>not</b> work.  There is a special compatibility layer for old-style
+<code>OUTFUNC</code> functions, but it is only invoked properly when you
+use one of the two methods mentioned above.
+
+
+</ol>
+
+<p>
+
+This <i>should</i> be sufficient for you to recompile-and-go
+with Ficl 4.  If it's not, please let us know, preferably including a
+suggested solution to the problem.
+
+
+<a name=newapi>
+
+<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='UsingTheNewAPI'>
+Using The New API
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+</a>
+
+Since most (all?) of the external symbols have changed names since the 3.0 series,
+here is a quick guide to get you started on renaming everything.  This is by no
+means an exhaustive list; this is meant to guide you towards figuring out what
+the new name <i>should</i> be.  (After all, part of the point of this massive
+renaming was to make all the external symbols consistent.)
+<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='Types'>
+Types
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Every external type has been renamed.  They all begin with the
+word <code>ficl</code>, and they use mixed case (instead of all upper-case,
+which is now reserved for macros).  Also, the confusingly-named
+string objects have been renamed:
+<code>FICL_STRING</code> is now <code>ficlCountedString</code>, as it
+represents a "counted string" in the language, and
+the more commonly-used <code>STRINGINFO</code> is now simply
+<code>ficlString</code>.
+
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_SYSTEM</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlSystem</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_VM</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlVm</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_SYSTEM_INFO</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlSystemInformation</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_WORD</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlWord</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>IPTYPE</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlIp</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_CODE</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlPrimitive</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>OUTFUNC</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlOutputFunction</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_DICTIONARY</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlDictionary</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_STACK</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStack</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>STRINGINFO</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlString</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FICL_STRING</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlCountedString</code></td>
+
+</tr>
+
+
+</table><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='StructureMembers'>
+Structure Members
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+In addition, many structure names have changed.  To help ease the heartache,
+we've also added some accessor macros.  So, in case they change in the future,
+your code might still compile (hooray!).
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+<td bgcolor=#d0d0f0><b>accessor</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>pExtend</code></td>
+
+<td bgcolor=#f0f0f0><code>context</code></td>
+
+<td bgcolor=#e0e0e0><code>ficlVmGetContext(), ficlSystemGetContext()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>pStack</code></td>
+
+<td bgcolor=#f0f0f0><code>dataStack</code></td>
+
+<td bgcolor=#e0e0e0><code>ficlVmGetDataStack()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>fStack</code></td>
+
+<td bgcolor=#f0f0f0><code>floatStack</code></td>
+
+<td bgcolor=#e0e0e0><code>ficlVmGetFloatStack()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>rStack</code></td>
+
+<td bgcolor=#f0f0f0><code>returnStack</code></td>
+
+<td bgcolor=#e0e0e0><code>ficlVmGetReturnStack()</code></td>
+
+</tr>
+
+
+</table><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='CallbackFunctions'>
+Callback Functions
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Text output callbacks have changed in two major ways:
+
+<ul>
+
+<li>
+They no longer take a VM pointer; they now take a <code>ficlCallback</code> structure.
+This allows output to be printed before a VM is defined, or in circumstances where a
+VM may not be defined (such as an assertion failure in a <code>ficlSystem...()</code> function).
+
+<li>
+They no longer take a flag indicating whether or not to add a "newline".
+Instead, the function must output a newline whenever it encounters
+a <code>\n</code> character in the text.
+
+</ul>
+
+If you don't want to rewrite your output function yet, you can
+"thunk" the new-style call to the old-style.  Just pass in <code>ficlOldnamesCallbackTextOut</code>
+as the name of the output function for the system and VM, and then set 
+the <code>thunkedTextout</code> member of the <code>ficlSystem</code>
+or <code>ficlVm</code> to your old-style text output function.
+
+
+
+<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='RenamedMacros'>
+Renamed Macros
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>PUSHPTR(p)</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStackPushPointer(vm->dataStack, p)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>POPUNS()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStackPopUnsigned(vm->dataStack)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>GETTOP()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStackGetTop(vm->dataStack)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FW_IMMEDIATE</code></td>
+
+<td bgcolor=#f0f0f0><code>FICL_WORD_IMMEDIATE</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>FW_COMPILE</code></td>
+
+<td bgcolor=#f0f0f0><code>FICL_WORD_COMPILE_ONLY</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>VM_INNEREXIT</code></td>
+
+<td bgcolor=#f0f0f0><code>FICL_VM_STATUS_INNER_EXIT</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>VM_OUTOFTEXT</code></td>
+
+<td bgcolor=#f0f0f0><code>FICL_VM_STATUS_OUT_OF_TEXT</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>VM_RESTART</code></td>
+
+<td bgcolor=#f0f0f0><code>FICL_VM_RESTART</code></td>
+
+</tr>
+
+
+</table><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 macros.  Ficl now ships with a standard place for
+you to tweak the Ficl compile-time preprocessor switches  such as
+<code>FICL_WANT_COMPATIBILITY</code> and <code>FICL_WANT_FLOAT</code>.
+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.
+
+
+
+<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='RenamedFunctions'>
+Renamed Functions
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+Every function that deals primarily with a particular structure
+is now named after that structure.  For instance, any function
+that takes a <code>ficlSystem</code> as its first argument is
+named <code>ficlSystem<i>Something</i>()</code>.  Any function
+that takes a <code>ficlVm</code> as its first argument is
+named <code>ficlVm<i>Something</i>()</code>.  And so on.
+<p>
+
+Also, functions that create a new object are always
+called <code>Create</code> (not <code>Alloc</code>, <code>Allot</code>, <code>Init</code>, or <code>New</code>).
+Functions that create a new object are always
+called <code>Destroy</code> (not <code>Free</code>, <code>Term</code>, or <code>Delete</code>).
+<p>
+
+
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlInitSystem()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlSystemCreate()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlTermSystem()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlSystemDestroy()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlNewVM()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlSystemCreateVm()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlFreeVM()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlVmDestroy()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>dictCreate()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlDictionaryCreate()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>dictDelete()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlDictionaryDestroy()</code></td>
+
+</tr>
+
+
+</table><p>
+
+
+<p>
+
+All functions exported by Ficl now start with the word <code>ficl</code>.
+This is a <i>feature</i>, as it means the Ficl project will no longer
+pollute your namespace.
+
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>PUSHPTR(p)</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStackPushPointer(vm->dataStack, p)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>POPUNS()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStackPopUnsigned(vm->dataStack)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>GETTOP()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStackGetTop(vm->dataStack)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ltoa()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlLtoa()</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>strincmp()</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlStrincomp()</code></td>
+
+</tr>
+
+
+</table><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='RemovedFunctions'>
+Removed Functions
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+A few entry points have simply been removed.
+For instance, functions specifically managing a system's <code>ENVIRONMENT</code>
+settings have been removed, in favor of managing the system's
+<code>environment</code> dictionary directly:
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlSystemSetEnvironment(system)</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlDictionarySetConstant(ficlSystemGetEnvironment(system), ...)</code></td>
+
+</tr>
+
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlSystemSet2Environment(system)</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlDictionarySet2Constant(ficlSystemGetEnvironment(system), ...)</code></td>
+
+</tr>
+
+
+</table><p>
+
+
+
+
+In a similar vein, <code>ficlSystemBuild()</code> has been removed in favor
+of using <code>ficlDictionarySetPrimitive()</code> directly:
+
+<table width=100%><tr>
+
+<td bgcolor=#d0d0f0><b>old name</b></td>
+
+<td bgcolor=#e0e0ff><b>new name</td>
+
+</tr>
+
+<tr>
+
+<td bgcolor=#e0e0e0><code>ficlSystemBuild(system, ...)</code></td>
+
+<td bgcolor=#f0f0f0><code>ficlDictionarySetPrimitive(ficlSystemGetDictionary(system), ...)</code></td>
+
+</tr>
+
+
+</table><p>
+
+
+
+Finally, there is no <i>exact</i> replacement for <code>ficlExec()</code>.  99% of the code
+that called <code>ficlExec()</code> never bothered to manage <code>SOURCE-ID</code> properly.
+If you were calling <code>ficlExec()</code>, and you weren't changing <code>SOURCE-ID</code>
+(or <code>vm->sourceId</code>) to match, you should replace those calls with <code>ficlVmEvaluate()</code>,
+which will manage <code>SOURCE-ID</code> for you.
+<p>
+
+There <i>is</i> a function that takes the place of <code>ficlExec()</code> which doesn't change
+<code>SOURCE-ID</code>: <code>ficlVmExecuteString()</code>.  However, instead of taking a
+straight C string (a <code>char *</code>), it takes a <code>ficlString *</code> as its
+code argument.  (This is to discourage its use.)
+
+
+
+<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='InternalChanges'>
+Internal Changes
+</a></i></b></font></td></tr></table><p><blockquote>
+
+
+
+<b>Note:</b> none of these changes should affect you.  If they do, there's probably
+a problem somewhere.  Either Ficl's API doesn't abstract away something enough, or
+you are approaching a problem the wrong way.  Food for thought.
+<p>
+
+There's only one internal change worth noting here.
+The top value on a Ficl stack used to be at (to use the modern structure names)
+<code>stack->top[-1]</code>.  It is now at <code>stack->top[0]</code>.
+In other words, the "stack top" pointer used to point <i>past</i> the top
+element; it now points <i>at</i> the top element.  (Pointing <i>at</i> the
+top element is not only less confusing, it is also faster.)
+
+</body>
+</html>
--- /dev/null
+++ b/double.c
@@ -1,0 +1,477 @@
+/*******************************************************************
+** m a t h 6 4 . c
+** Forth Inspired Command Language - 64 bit math support routines
+** Authors: Michael A. Gauland (gaulandm@mdhost.cse.tek.com)
+**          Larry Hastings (larry@hastings.org)
+**          John Sadler (john_sadler@alum.mit.edu)
+** Created: 25 January 1998
+** Rev 2.03: Support for 128 bit DP math. This file really ouught to
+** be renamed!
+** $Id: double.c,v 1.1 2010/08/12 12:49:57 asau Exp $
+*******************************************************************/
+/*
+** 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 "ficl.h"
+
+
+#if FICL_PLATFORM_HAS_2INTEGER
+
+
+
+ficl2UnsignedQR ficl2UnsignedDivide(ficl2Unsigned q, ficlUnsigned y)
+{
+    ficl2UnsignedQR result;
+
+    result.quotient = q / y;
+	/*
+	** Once we have the quotient, it's cheaper to calculate the
+	** remainder this way than with % (mod).  --lch
+	*/
+    result.remainder  = (ficlInteger)(q - (result.quotient * y));
+
+    return result;
+}
+
+
+#else  /* FICL_PLATFORM_HAS_2INTEGER */
+
+
+#define FICL_CELL_HIGH_BIT  (1L << (FICL_BITS_PER_CELL-1))
+#define UMOD_SHIFT (FICL_BITS_PER_CELL / 2)
+#define UMOD_MASK ((1L << (FICL_BITS_PER_CELL / 2)) - 1)
+
+
+/**************************************************************************
+                        ficl2IntegerIsNegative
+** Returns TRUE if the specified ficl2Unsigned has its sign bit set.
+**************************************************************************/
+int ficl2IntegerIsNegative(ficl2Integer x)
+{
+    return (x.high < 0);
+}
+
+
+/**************************************************************************
+                        ficl2IntegerNegate
+** Negates an ficl2Unsigned by complementing and incrementing.
+**************************************************************************/
+ficl2Integer ficl2IntegerNegate(ficl2Integer x)
+{
+    x.high = ~x.high;
+    x.low = ~x.low;
+    x.low ++;
+    if (x.low == 0)
+        x.high++;
+
+    return x;
+}
+
+/**************************************************************************
+                        ficl2UnsignedMultiplyAccumulate
+** Mixed precision multiply and accumulate primitive for number building.
+** Multiplies ficl2Unsigned u by ficlUnsigned mul and adds ficlUnsigned add. Mul is typically
+** the numeric base, and add represents a digit to be appended to the 
+** growing number. 
+** Returns the result of the operation
+**************************************************************************/
+ficl2Unsigned ficl2UnsignedMultiplyAccumulate(ficl2Unsigned u, ficlUnsigned mul, ficlUnsigned add)
+{
+    ficl2Unsigned resultLo = ficl2UnsignedMultiply(u.low, mul);
+    ficl2Unsigned resultHi = ficl2UnsignedMultiply(u.high, mul);
+    resultLo.high += resultHi.low;
+    resultHi.low = resultLo.low + add;
+
+    if (resultHi.low < resultLo.low)
+        resultLo.high++;
+
+    resultLo.low = resultHi.low;
+
+    return resultLo;
+}
+
+
+/**************************************************************************
+                        ficl2IntegerMultiply
+** Multiplies a pair of ficlIntegers and returns an ficl2Integer result.
+**************************************************************************/
+ficl2Integer ficl2IntegerMultiply(ficlInteger x, ficlInteger y)
+{
+    ficl2Unsigned prod;
+    int sign = 1;
+
+    if (x < 0)
+    {
+        sign = -sign;
+        x = -x;
+    }
+
+    if (y < 0)
+    {
+        sign = -sign;
+        y = -y;
+    }
+
+    prod = ficl2UnsignedMultiply(x, y);
+    if (sign > 0)
+        return FICL_2UNSIGNED_TO_2INTEGER(prod);
+    else
+        return ficl2IntegerNegate(FICL_2UNSIGNED_TO_2INTEGER(prod));
+}
+
+
+
+ficl2Integer ficl2IntegerDecrement(ficl2Integer x)
+{
+	if (x.low == INT_MIN)
+		x.high--;
+	x.low--;
+
+	return x;
+}
+
+
+ficl2Unsigned ficl2UnsignedAdd(ficl2Unsigned x, ficl2Unsigned y)
+{
+    ficl2Unsigned result;
+    int carry;
+    
+    result.high = x.high + y.high;
+    result.low = x.low + y.low;
+
+
+    carry  = ((x.low | y.low) & FICL_CELL_HIGH_BIT) && !(result.low & FICL_CELL_HIGH_BIT);
+    carry |= ((x.low & y.low) & FICL_CELL_HIGH_BIT);
+
+    if (carry)
+    {
+        result.high++;
+    }
+
+    return result;
+}
+
+/**************************************************************************
+                        ficl2UnsignedMultiply
+** Contributed by:
+** Michael A. Gauland   gaulandm@mdhost.cse.tek.com  
+**************************************************************************/
+ficl2Unsigned ficl2UnsignedMultiply(ficlUnsigned x, ficlUnsigned y)
+{
+    ficl2Unsigned result = { 0, 0 };
+    ficl2Unsigned addend;
+    
+    addend.low = y;
+    addend.high = 0; /* No sign extension--arguments are unsigned */
+    
+    while (x != 0) 
+    {
+        if ( x & 1) 
+        {
+            result = ficl2UnsignedAdd(result, addend);
+        }
+        x >>= 1;
+        addend = ficl2UnsignedArithmeticShiftLeft(addend);
+    }
+    return result;
+}
+
+
+
+/**************************************************************************
+                        ficl2UnsignedSubtract
+** 
+**************************************************************************/
+ficl2Unsigned ficl2UnsignedSubtract(ficl2Unsigned x, ficl2Unsigned y)
+{
+    ficl2Unsigned result;
+    
+    result.high = x.high - y.high;
+    result.low = x.low - y.low;
+
+    if (x.low < y.low) 
+    {
+        result.high--;
+    }
+
+    return result;
+}
+
+
+/**************************************************************************
+                        ficl2UnsignedArithmeticShiftLeft
+** 64 bit left shift
+**************************************************************************/
+ficl2Unsigned ficl2UnsignedArithmeticShiftLeft( ficl2Unsigned x )
+{
+    ficl2Unsigned result;
+    
+    result.high = x.high << 1;
+    if (x.low & FICL_CELL_HIGH_BIT) 
+    {
+        result.high++;
+    }
+
+    result.low = x.low << 1;
+
+    return result;
+}
+
+
+/**************************************************************************
+                        ficl2UnsignedArithmeticShiftRight
+** 64 bit right shift (unsigned - no sign extend)
+**************************************************************************/
+ficl2Unsigned ficl2UnsignedArithmeticShiftRight( ficl2Unsigned x )
+{
+    ficl2Unsigned result;
+    
+    result.low = x.low >> 1;
+    if (x.high & 1) 
+    {
+        result.low |= FICL_CELL_HIGH_BIT;
+    }
+
+    result.high = x.high >> 1;
+    return result;
+}
+
+
+/**************************************************************************
+                        ficl2UnsignedOr
+** 64 bit bitwise OR
+**************************************************************************/
+ficl2Unsigned ficl2UnsignedOr( ficl2Unsigned x, ficl2Unsigned y )
+{
+    ficl2Unsigned result;
+    
+    result.high = x.high | y.high;
+    result.low = x.low | y.low;
+    
+    return result;
+}
+
+
+/**************************************************************************
+                        ficl2UnsignedCompare
+** Return -1 if x < y; 0 if x==y, and 1 if x > y.
+**************************************************************************/
+int ficl2UnsignedCompare(ficl2Unsigned x, ficl2Unsigned y)
+{
+    if (x.high > y.high) 
+        return 1;
+    if (x.high < y.high) 
+        return -1;
+
+	/* High parts are equal */
+
+    if (x.low > y.low) 
+        return 1;
+    else if (x.low < y.low) 
+        return -1;
+    
+    return 0;
+}
+
+
+
+/**************************************************************************
+                        ficl2UnsignedDivide
+** Portable versions of ficl2Multiply and ficl2Divide in C
+** Contributed by:
+** Michael A. Gauland   gaulandm@mdhost.cse.tek.com  
+**************************************************************************/
+ficl2UnsignedQR ficl2UnsignedDivide(ficl2Unsigned q, ficlUnsigned y)
+{
+    ficl2UnsignedQR result;
+    ficl2Unsigned quotient;
+    ficl2Unsigned subtrahend;
+    ficl2Unsigned mask;
+
+    quotient.low = 0;
+    quotient.high = 0;
+    
+    subtrahend.low = y;
+    subtrahend.high = 0;
+    
+    mask.low = 1;
+    mask.high = 0;
+    
+    while ((ficl2UnsignedCompare(subtrahend, q) < 0) &&
+           (subtrahend.high & FICL_CELL_HIGH_BIT) == 0)
+    {
+        mask = ficl2UnsignedArithmeticShiftLeft(mask);
+        subtrahend = ficl2UnsignedArithmeticShiftLeft(subtrahend);
+    }
+    
+    while (mask.low != 0 || mask.high != 0) 
+    {
+        if (ficl2UnsignedCompare(subtrahend, q) <= 0) 
+        {
+            q = ficl2UnsignedSubtract( q, subtrahend);
+            quotient = ficl2UnsignedOr(quotient, mask);
+        }
+        mask = ficl2UnsignedArithmeticShiftRight(mask);
+        subtrahend = ficl2UnsignedArithmeticShiftRight(subtrahend);
+    }
+    
+    result.quotient = quotient;
+    result.remainder = q.low;
+    return result;
+}
+
+#endif /* !FICL_PLATFORM_HAS_2INTEGER */
+
+
+
+/**************************************************************************
+                        ficl2IntegerAbsoluteValue
+** Returns the absolute value of an ficl2Unsigned
+**************************************************************************/
+ficl2Integer ficl2IntegerAbsoluteValue(ficl2Integer x)
+{
+    if (ficl2IntegerIsNegative(x))
+        return ficl2IntegerNegate(x);
+    return x;
+}
+
+
+/**************************************************************************
+                        ficl2IntegerDivideFloored
+** 
+** FROM THE FORTH ANS...
+** Floored division is integer division in which the remainder carries
+** the sign of the divisor or is zero, and the quotient is rounded to
+** its arithmetic floor. Symmetric division is integer division in which
+** the remainder carries the sign of the dividend or is zero and the
+** quotient is the mathematical quotient rounded towards zero or
+** truncated. Examples of each are shown in tables 3.3 and 3.4. 
+** 
+** Table 3.3 - Floored Division Example
+** Dividend        Divisor Remainder       Quotient
+** --------        ------- ---------       --------
+**  10                7       3                1
+** -10                7       4               -2
+**  10               -7      -4               -2
+** -10               -7      -3                1
+** 
+** 
+** Table 3.4 - Symmetric Division Example
+** Dividend        Divisor Remainder       Quotient
+** --------        ------- ---------       --------
+**  10                7       3                1
+** -10                7      -3               -1
+**  10               -7       3               -1
+** -10               -7      -3                1
+**************************************************************************/
+ficl2IntegerQR ficl2IntegerDivideFloored(ficl2Integer num, ficlInteger den)
+{
+    ficl2IntegerQR qr;
+    ficl2UnsignedQR uqr;
+    int signRem = 1;
+    int signQuot = 1;
+
+    if (ficl2IntegerIsNegative(num))
+    {
+        num = ficl2IntegerNegate(num);
+        signQuot = -signQuot;
+    }
+
+    if (den < 0)
+    {
+        den      = -den;
+        signRem  = -signRem;
+        signQuot = -signQuot;
+    }
+
+    uqr = ficl2UnsignedDivide(FICL_2INTEGER_TO_2UNSIGNED(num), (ficlUnsigned)den);
+    qr = FICL_2UNSIGNEDQR_TO_2INTEGERQR(uqr);
+    if (signQuot < 0)
+    {
+        qr.quotient = ficl2IntegerNegate(qr.quotient);
+        if (qr.remainder != 0)
+        {
+            qr.quotient = ficl2IntegerDecrement(qr.quotient);
+            qr.remainder = den - qr.remainder;
+        }
+    }
+
+    if (signRem < 0)
+        qr.remainder = -qr.remainder;
+
+    return qr;
+}
+
+
+
+/**************************************************************************
+                        ficl2IntegerDivideSymmetric
+** Divide an ficl2Unsigned by a ficlInteger and return a ficlInteger quotient and a
+** ficlInteger remainder. The absolute values of quotient and remainder are not
+** affected by the signs of the numerator and denominator (the operation
+** is symmetric on the number line)
+**************************************************************************/
+ficl2IntegerQR ficl2IntegerDivideSymmetric(ficl2Integer num, ficlInteger den)
+{
+    ficl2IntegerQR qr;
+    ficl2UnsignedQR uqr;
+    int signRem = 1;
+    int signQuot = 1;
+
+    if (ficl2IntegerIsNegative(num))
+    {
+        num = ficl2IntegerNegate(num);
+        signRem  = -signRem;
+        signQuot = -signQuot;
+    }
+
+    if (den < 0)
+    {
+        den      = -den;
+        signQuot = -signQuot;
+    }
+
+    uqr = ficl2UnsignedDivide(FICL_2INTEGER_TO_2UNSIGNED(num), (ficlUnsigned)den);
+    qr = FICL_2UNSIGNEDQR_TO_2INTEGERQR(uqr);
+    if (signRem < 0)
+        qr.remainder = -qr.remainder;
+
+    if (signQuot < 0)
+        qr.quotient = ficl2IntegerNegate(qr.quotient);
+
+    return qr;
+}
+
+
--- /dev/null
+++ b/extras.c
@@ -1,0 +1,266 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "ficl.h"
+
+
+#ifndef FICL_ANSI
+
+/*
+** Ficl interface to _getcwd (Win32)
+** Prints the current working directory using the VM's 
+** textOut method...
+*/
+static void ficlPrimitiveGetCwd(ficlVm *vm)
+{
+    char *directory;
+
+    directory = getcwd(NULL, 80);
+    ficlVmTextOut(vm, directory);
+    ficlVmTextOut(vm, "\n");
+    free(directory);
+    return;
+}
+
+
+
+/*
+** Ficl interface to _chdir (Win32)
+** Gets a newline (or NULL) delimited string from the input
+** and feeds it to the Win32 chdir function...
+** Example:
+**    cd c:\tmp
+*/
+static void ficlPrimitiveChDir(ficlVm *vm)
+{
+    ficlCountedString *counted = (ficlCountedString *)vm->pad;
+    ficlVmGetString(vm, counted, '\n');
+    if (counted->length > 0)
+    {
+       int err = chdir(counted->text);
+       if (err)
+        {
+            ficlVmTextOut(vm, "Error: path not found\n");
+            ficlVmThrow(vm, FICL_VM_STATUS_QUIT);
+        }
+    }
+    else
+    {
+        ficlVmTextOut(vm, "Warning (chdir): nothing happened\n");
+    }
+    return;
+}
+
+
+
+static void ficlPrimitiveClock(ficlVm *vm)
+{
+    clock_t now = clock();
+    ficlStackPushUnsigned(vm->dataStack, (ficlUnsigned)now);
+    return;
+}
+
+#endif /* FICL_ANSI */
+
+
+/*
+** Ficl interface to system (ANSI)
+** Gets a newline (or NULL) delimited string from the input
+** and feeds it to the ANSI system function...
+** Example:
+**    system del *.*
+**    \ ouch!
+*/
+static void ficlPrimitiveSystem(ficlVm *vm)
+{
+    ficlCountedString *counted = (ficlCountedString *)vm->pad;
+
+    ficlVmGetString(vm, counted, '\n');
+    if (FICL_COUNTED_STRING_GET_LENGTH(*counted) > 0)
+    {
+        int returnValue = system(FICL_COUNTED_STRING_GET_POINTER(*counted));
+        if (returnValue)
+        {
+            sprintf(vm->pad, "System call returned %d\n", returnValue);
+            ficlVmTextOut(vm, vm->pad);
+            ficlVmThrow(vm, FICL_VM_STATUS_QUIT);
+        }
+    }
+    else
+    {
+        ficlVmTextOut(vm, "Warning (system): nothing happened\n");
+    }
+    return;
+}
+
+
+
+/*
+** Ficl add-in to load a text file and execute it...
+** Cheesy, but illustrative.
+** Line oriented... filename is newline (or NULL) delimited.
+** Example:
+**    load test.f
+*/
+#define BUFFER_SIZE 256
+static void ficlPrimitiveLoad(ficlVm *vm)
+{
+    char    buffer[BUFFER_SIZE];
+    char    filename[BUFFER_SIZE];
+    ficlCountedString *counted = (ficlCountedString *)filename;
+    int     line = 0;
+    FILE   *f;
+    int     result = 0;
+    ficlCell    oldSourceId;
+	ficlString s;
+
+    ficlVmGetString(vm, counted, '\n');
+
+    if (FICL_COUNTED_STRING_GET_LENGTH(*counted) <= 0)
+    {
+        ficlVmTextOut(vm, "Warning (load): nothing happened\n");
+        return;
+    }
+
+    /*
+    ** get the file's size and make sure it exists 
+    */
+
+    f = fopen(FICL_COUNTED_STRING_GET_POINTER(*counted), "r");
+    if (!f)
+    {
+        ficlVmTextOut(vm, "Unable to open file ");
+        ficlVmTextOut(vm, FICL_COUNTED_STRING_GET_POINTER(*counted));
+        ficlVmTextOut(vm, "\n");
+        ficlVmThrow(vm, FICL_VM_STATUS_QUIT);
+    }
+
+    oldSourceId = vm->sourceId;
+    vm->sourceId.p = (void *)f;
+
+    /* feed each line to ficlExec */
+    while (fgets(buffer, BUFFER_SIZE, f))
+    {
+        int length = strlen(buffer) - 1;
+
+        line++;
+        if (length <= 0)
+            continue;
+
+        if (buffer[length] == '\n')
+            buffer[length--] = '\0';
+
+		FICL_STRING_SET_POINTER(s, buffer);
+		FICL_STRING_SET_LENGTH(s, length + 1);
+        result = ficlVmExecuteString(vm, s);
+        /* handle "bye" in loaded files. --lch */
+        switch (result)
+        {
+            case FICL_VM_STATUS_OUT_OF_TEXT:
+            case FICL_VM_STATUS_USER_EXIT:
+                break;
+
+            default:
+                vm->sourceId = oldSourceId;
+                fclose(f);
+                ficlVmThrowError(vm, "Error loading file <%s> line %d", FICL_COUNTED_STRING_GET_POINTER(*counted), line);
+                break; 
+        }
+    }
+    /*
+    ** Pass an empty line with SOURCE-ID == -1 to flush
+    ** any pending REFILLs (as required by FILE wordset)
+    */
+    vm->sourceId.i = -1;
+	FICL_STRING_SET_FROM_CSTRING(s, "");
+    ficlVmExecuteString(vm, s);
+
+    vm->sourceId = oldSourceId;
+    fclose(f);
+
+    /* handle "bye" in loaded files. --lch */
+    if (result == FICL_VM_STATUS_USER_EXIT)
+        ficlVmThrow(vm, FICL_VM_STATUS_USER_EXIT);
+    return;
+}
+
+
+
+/*
+** Dump a tab delimited file that summarizes the contents of the
+** dictionary hash table by hashcode...
+*/
+static void ficlPrimitiveSpewHash(ficlVm *vm)
+{
+    ficlHash *hash = ficlVmGetDictionary(vm)->forthWordlist;
+    ficlWord *word;
+    FILE *f;
+    unsigned i;
+    unsigned hashSize = hash->size;
+
+    if (!ficlVmGetWordToPad(vm))
+        ficlVmThrow(vm, FICL_VM_STATUS_OUT_OF_TEXT);
+
+    f = fopen(vm->pad, "w");
+    if (!f)
+    {
+        ficlVmTextOut(vm, "unable to open file\n");
+        return;
+    }
+
+    for (i = 0; i < hashSize; i++)
+    {
+        int n = 0;
+
+        word = hash->table[i];
+        while (word)
+        {
+            n++;
+            word = word->link;
+        }
+
+        fprintf(f, "%d\t%d", i, n);
+
+        word = hash->table[i];
+        while (word)
+        {
+            fprintf(f, "\t%s", word->name);
+            word = word->link;
+        }
+
+        fprintf(f, "\n");
+    }
+
+    fclose(f);
+    return;
+}
+
+static void ficlPrimitiveBreak(ficlVm *vm)
+{
+    vm->state = vm->state;
+    return;
+}
+
+
+
+void ficlSystemCompileExtras(ficlSystem *system)
+{
+    ficlDictionary *dictionary = ficlSystemGetDictionary(system);
+
+    ficlDictionarySetPrimitive(dictionary, "break",    ficlPrimitiveBreak,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "load",     ficlPrimitiveLoad,     FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "spewhash", ficlPrimitiveSpewHash, FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "system",   ficlPrimitiveSystem,   FICL_WORD_DEFAULT);
+
+#ifndef FICL_ANSI
+    ficlDictionarySetPrimitive(dictionary, "clock",    ficlPrimitiveClock,    FICL_WORD_DEFAULT);
+    ficlDictionarySetConstant(dictionary, "clocks/sec", CLOCKS_PER_SEC);
+    ficlDictionarySetPrimitive(dictionary, "pwd",      ficlPrimitiveGetCwd,   FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "cd",       ficlPrimitiveChDir,    FICL_WORD_DEFAULT);
+#endif /* FICL_ANSI */
+
+    return;
+}
+
--- /dev/null
+++ b/ficlcompatibility.h
@@ -1,0 +1,463 @@
+#ifndef FICL_FORCE_COMPATIBILITY
+
+struct ficl_word;
+typedef struct ficl_word FICL_WORD;
+struct vm;
+typedef struct vm FICL_VM;
+struct ficl_dict;
+typedef struct ficl_dict FICL_DICT;
+struct ficl_system;
+typedef struct ficl_system FICL_SYSTEM;
+struct ficl_system_info;
+typedef struct ficl_system_info FICL_SYSTEM_INFO;
+#define ficlFILE ficlFile
+
+typedef ficlUnsigned FICL_UNS;
+typedef ficlInteger FICL_INT;
+typedef ficlFloat FICL_FLOAT;
+typedef ficlUnsigned16 UNS16;
+typedef ficlUnsigned8 UNS8;
+
+#define _cell ficlCell
+#define CELL ficlCell
+
+#define LVALUEtoCELL(v) (*(ficlCell *)&v)
+#define PTRtoCELL (ficlCell *)(void *)
+#define PTRtoSTRING (ficlCountedString *)(void *)
+
+typedef unsigned char FICL_COUNT;
+#define FICL_STRING_MAX UCHAR_MAX
+typedef struct _ficl_string
+{
+    ficlUnsigned8 count;
+    char text[1];
+} FICL_STRING;
+
+typedef struct 
+{
+    ficlUnsigned count;
+    char *cp;
+} STRINGINFO;
+
+#define SI_COUNT(si) (si.count)
+#define SI_PTR(si)   (si.cp)
+#define SI_SETLEN(si, len) (si.count = (FICL_UNS)(len))
+#define SI_SETPTR(si, ptr) (si.cp = (char *)(ptr))
+#define SI_PSZ(si, psz) \
+            {si.cp = psz; si.count = (FICL_COUNT)strlen(psz);}
+#define SI_PFS(si, pfs) \
+            {si.cp = pfs->text; si.count = pfs->count;}
+
+typedef struct
+{
+    ficlInteger index;
+    char *end;
+    char *cp;
+} TIB;
+
+
+typedef struct _ficlStack
+{
+    ficlUnsigned nCells;    /* size of the stack */
+    CELL *pFrame;       /* link reg for stack frame */
+    CELL *sp;           /* stack pointer */
+	ficlVm *vm;
+	char *name;
+    CELL base[1];       /* Top of stack */
+} FICL_STACK;
+
+FICL_STACK *stackCreate   (unsigned nCells);
+void        stackDelete   (FICL_STACK *pStack);
+int         stackDepth    (FICL_STACK *pStack);
+void        stackDrop     (FICL_STACK *pStack, int n);
+CELL        stackFetch    (FICL_STACK *pStack, int n);
+CELL        stackGetTop   (FICL_STACK *pStack);
+void        stackLink     (FICL_STACK *pStack, int nCells);
+void        stackPick     (FICL_STACK *pStack, int n);
+CELL        stackPop      (FICL_STACK *pStack);
+void       *stackPopPtr   (FICL_STACK *pStack);
+FICL_UNS    stackPopUNS   (FICL_STACK *pStack);
+FICL_INT    stackPopINT   (FICL_STACK *pStack);
+void        stackPush     (FICL_STACK *pStack, CELL c);
+void        stackPushPtr  (FICL_STACK *pStack, void *ptr);
+void        stackPushUNS  (FICL_STACK *pStack, FICL_UNS u);
+void        stackPushINT  (FICL_STACK *pStack, FICL_INT i);
+void        stackReset    (FICL_STACK *pStack);
+void        stackRoll     (FICL_STACK *pStack, int n);
+void        stackSetTop   (FICL_STACK *pStack, CELL c);
+void        stackStore    (FICL_STACK *pStack, int n, CELL c);
+void        stackUnlink   (FICL_STACK *pStack);
+
+#if (FICL_WANT_FLOAT)
+float       stackPopFloat (FICL_STACK *pStack);
+void        stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f);
+#endif
+
+#define PUSHPTR(p)   stackPushPtr(pVM->pStack,p)
+#define PUSHUNS(u)   stackPushUNS(pVM->pStack,u)
+#define PUSHINT(i)   stackPushINT(pVM->pStack,i)
+#define PUSHFLOAT(f) stackPushFloat(pVM->fStack,f)
+#define PUSH(c)      stackPush(pVM->pStack,c)
+#define POPPTR()     stackPopPtr(pVM->pStack)
+#define POPUNS()     stackPopUNS(pVM->pStack)
+#define POPINT()     stackPopINT(pVM->pStack)
+#define POPFLOAT()   stackPopFloat(pVM->fStack)
+#define POP()        stackPop(pVM->pStack)
+#define GETTOP()     stackGetTop(pVM->pStack)
+#define SETTOP(c)    stackSetTop(pVM->pStack,LVALUEtoCELL(c))
+#define GETTOPF()    stackGetTop(pVM->fStack)
+#define SETTOPF(c)   stackSetTop(pVM->fStack,LVALUEtoCELL(c))
+#define STORE(n,c)   stackStore(pVM->pStack,n,LVALUEtoCELL(c))
+#define DEPTH()      stackDepth(pVM->pStack)
+#define DROP(n)      stackDrop(pVM->pStack,n)
+#define DROPF(n)     stackDrop(pVM->fStack,n)
+#define FETCH(n)     stackFetch(pVM->pStack,n)
+#define PICK(n)      stackPick(pVM->pStack,n)
+#define PICKF(n)     stackPick(pVM->fStack,n)
+#define ROLL(n)      stackRoll(pVM->pStack,n)
+#define ROLLF(n)     stackRoll(pVM->fStack,n)
+
+typedef FICL_WORD ** IPTYPE; /* the VM's instruction pointer */
+typedef void (*OUTFUNC)(FICL_VM *pVM, char *text, int fNewline);
+
+/* values of STATE */
+#define INTERPRET FICL_STATE_INTERPRET
+#define COMPILE   FICL_STATE_COMPILE
+
+#if !defined nPAD
+#define nPAD FICL_PAD_SIZE
+#endif
+
+#if !defined nFICLNAME
+#define nFICLNAME       FICL_NAME_LENGTH
+#endif
+
+#define FICL_DEFAULT_STACK FICL_DEFAULT_STACK_SIZE
+#define FICL_DEFAULT_DICT FICL_DEFAULT_DICTIONARY_SIZE
+#define FICL_DEFAULT_ENV FICL_DEFAULT_ENVIRONMENT_SIZE
+#define FICL_DEFAULT_VOCS FICL_MAX_WORDLISTS
+
+
+
+
+
+struct vm
+{
+	void *pExtend;
+	ficlOutputFunction textOut;
+	ficlOutputFunction errorOut;
+	ficlSystem *pSys;
+	ficlVm *pVM;
+    FICL_VM        *link;       /* Ficl keeps a VM list for simple teardown */
+    jmp_buf        *pState;     /* crude exception mechanism...     */
+    short           fRestart;   /* Set TRUE to restart runningWord  */
+    IPTYPE          ip;         /* instruction pointer              */
+    FICL_WORD      *runningWord;/* address of currently running word (often just *(ip-1) ) */
+    FICL_UNS        state;      /* compiling or interpreting        */
+    FICL_UNS        base;       /* number conversion base           */
+    FICL_STACK     *pStack;     /* param stack                      */
+    FICL_STACK     *rStack;     /* return stack                     */
+#if FICL_WANT_FLOAT
+    FICL_STACK     *fStack;     /* float stack (optional)           */
+#endif
+    CELL            sourceID;   /* -1 if EVALUATE, 0 if normal input */
+    TIB             tib;        /* address of incoming text string  */
+#if FICL_WANT_USER
+    CELL            user[FICL_USER_CELLS];
+#endif
+    char            pad[nPAD];  /* the scratch area (see above)     */
+};
+
+/*
+** A FICL_CODE points to a function that gets called to help execute
+** a word in the dictionary. It always gets passed a pointer to the
+** running virtual machine, and from there it can get the address
+** of the parameter area of the word it's supposed to operate on.
+** For precompiled words, the code is all there is. For user defined
+** words, the code assumes that the word's parameter area is a list
+** of pointers to the code fields of other words to execute, and
+** may also contain inline data. The first parameter is always
+** a pointer to a code field.
+*/
+typedef void (*FICL_CODE)(FICL_VM *pVm);
+
+#if 0
+#define VM_ASSERT(pVM) assert((*(pVM->ip - 1)) == pVM->runningWord)
+#else
+#define VM_ASSERT(pVM) 
+#endif
+
+#define nName length
+#define ficl_word ficlWord
+#define FICL_WORD ficlWord
+
+#define CELLS_PER_WORD  \
+    ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \
+                          / (sizeof (CELL)) )
+
+int wordIsImmediate(FICL_WORD *pFW);
+int wordIsCompileOnly(FICL_WORD *pFW);
+
+#define FW_IMMEDIATE    FICL_WORD_IMMEDIATE
+#define FW_COMPILE      FICL_WORD_COMPILE_ONLY
+#define FW_SMUDGE       FICL_WORD_SMUDGED
+#define FW_ISOBJECT     FICL_WORD_OBJECT
+
+#define FW_COMPIMMED    (FW_IMMEDIATE | FW_COMPILE_ONLY)
+#define FW_DEFAULT      0
+
+
+/*
+** Exit codes for vmThrow
+*/
+#define VM_INNEREXIT FICL_VM_STATUS_INNER_EXIT
+#define VM_OUTOFTEXT FICL_VM_STATUS_OUT_OF_TEXT
+#define VM_RESTART   FICL_VM_STATUS_RESTART
+#define VM_USEREXIT  FICL_VM_STATUS_USER_EXIT
+#define VM_ERREXIT   FICL_VM_STATUS_ERROR_EXIT
+#define VM_BREAK     FICL_VM_STATUS_BREAK
+#define VM_ABORT     FICL_VM_STATUS_ABORT
+#define VM_ABORTQ    FICL_VM_STATUS_ABORTQ
+#define VM_QUIT      FICL_VM_STATUS_QUIT
+
+
+void        vmBranchRelative(FICL_VM *pVM, int offset);
+FICL_VM *   vmCreate       (FICL_VM *pVM, unsigned nPStack, unsigned nRStack);
+void        vmDelete       (FICL_VM *pVM);
+void        vmExecute      (FICL_VM *pVM, FICL_WORD *pWord);
+FICL_DICT  *vmGetDict      (FICL_VM *pVM);
+char *      vmGetString    (FICL_VM *pVM, FICL_STRING *spDest, char delimiter);
+STRINGINFO  vmGetWord      (FICL_VM *pVM);
+STRINGINFO  vmGetWord0     (FICL_VM *pVM);
+int         vmGetWordToPad (FICL_VM *pVM);
+STRINGINFO  vmParseString  (FICL_VM *pVM, char delimiter);
+STRINGINFO  vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading);
+CELL        vmPop          (FICL_VM *pVM);
+void        vmPush         (FICL_VM *pVM, CELL c);
+void        vmPopIP        (FICL_VM *pVM);
+void        vmPushIP       (FICL_VM *pVM, IPTYPE newIP);
+void        vmQuit         (FICL_VM *pVM);
+void        vmReset        (FICL_VM *pVM);
+void        vmSetTextOut   (FICL_VM *pVM, OUTFUNC textOut);
+void        vmTextOut      (FICL_VM *pVM, char *text, int fNewline);
+void        vmThrow        (FICL_VM *pVM, int except);
+void        vmThrowErr     (FICL_VM *pVM, char *fmt, ...);
+
+#define vmGetRunningWord(pVM) ((pVM)->runningWord)
+
+
+#define M_VM_STEP(pVM) \
+        FICL_WORD *tempFW = *(pVM)->ip++; \
+        ficlVmInnerLoop((ficlVm *)pVM, (ficlWord *)tempFW); \
+
+#define M_INNER_LOOP(pVM) \
+    ficlVmInnerLoop((ficlVm *)pVm);
+
+
+void        vmCheckStack(FICL_VM *pVM, int popCells, int pushCells);
+#if FICL_WANT_FLOAT
+void        vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells);
+#endif
+
+void        vmPushTib  (FICL_VM *pVM, char *text, FICL_INT nChars, TIB *pSaveTib);
+void        vmPopTib   (FICL_VM *pVM, TIB *pTib);
+#define     vmGetInBuf(pVM)      ((pVM)->tib.cp + (pVM)->tib.index)
+#define     vmGetInBufLen(pVM)   ((pVM)->tib.end - (pVM)->tib.cp)
+#define     vmGetInBufEnd(pVM)   ((pVM)->tib.end)
+#define     vmGetTibIndex(pVM)    (pVM)->tib.index
+#define     vmSetTibIndex(pVM, i) (pVM)->tib.index = i
+#define     vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp
+
+#if defined(_WIN32)
+/* #SHEESH
+** Why do Microsoft Meatballs insist on contaminating
+** my namespace with their string functions???
+*/
+#pragma warning(disable: 4273)
+#endif
+
+int        isPowerOfTwo(FICL_UNS u);
+
+char       *ltoa( FICL_INT value, char *string, int radix );
+char       *ultoa(FICL_UNS value, char *string, int radix );
+char        digit_to_char(int value);
+char       *strrev( char *string );
+char       *skipSpace(char *cp, char *end);
+char       *caseFold(char *cp);
+int         strincmp(char *cp1, char *cp2, FICL_UNS count);
+
+#if defined(_WIN32)
+#pragma warning(default: 4273)
+#endif
+
+#if !defined HASHSIZE /* Default size of hash table. For most uniform */
+#define HASHSIZE FICL_HASHSIZE  /*   performance, use a prime number!   */
+#endif
+
+#define ficl_hash ficlHash
+#define FICL_HASH ficlHash
+
+void        hashForget    (FICL_HASH *pHash, void *where);
+UNS16       hashHashCode  (STRINGINFO si);
+void        hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW);
+FICL_WORD  *hashLookup    (FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode);
+void        hashReset     (FICL_HASH *pHash);
+
+struct ficl_dict
+{
+    CELL *here;
+	void *context;
+    FICL_WORD *smudge;
+    FICL_HASH *pForthWords;
+    FICL_HASH *pCompile;
+    FICL_HASH *pSearch[FICL_DEFAULT_VOCS];
+    int        nLists;
+    unsigned   size;    /* Number of cells in dict (total)*/
+	ficlSystem *system;
+    CELL       dict[1]; /* Base of dictionary memory      */
+};
+
+void       *alignPtr(void *ptr);
+void        dictAbortDefinition(FICL_DICT *pDict);
+void        dictAlign      (FICL_DICT *pDict);
+int         dictAllot      (FICL_DICT *pDict, int n);
+int         dictAllotCells (FICL_DICT *pDict, int nCells);
+void        dictAppendCell (FICL_DICT *pDict, CELL c);
+void        dictAppendChar (FICL_DICT *pDict, char c);
+FICL_WORD  *dictAppendWord (FICL_DICT *pDict, 
+                           char *name, 
+                           FICL_CODE pCode, 
+                           UNS8 flags);
+FICL_WORD  *dictAppendWord2(FICL_DICT *pDict, 
+                           STRINGINFO si, 
+                           FICL_CODE pCode, 
+                           UNS8 flags);
+void        dictAppendUNS  (FICL_DICT *pDict, FICL_UNS u);
+int         dictCellsAvail (FICL_DICT *pDict);
+int         dictCellsUsed  (FICL_DICT *pDict);
+void        dictCheck      (FICL_DICT *pDict, FICL_VM *pVM, int n);
+FICL_DICT  *dictCreate(unsigned nCELLS);
+FICL_DICT  *dictCreateHashed(unsigned nCells, unsigned nHash);
+FICL_HASH  *dictCreateWordlist(FICL_DICT *dp, int nBuckets);
+void        dictDelete     (FICL_DICT *pDict);
+void        dictEmpty      (FICL_DICT *pDict, unsigned nHash);
+#if FICL_WANT_FLOAT
+void        dictHashSummary(FICL_VM *pVM);
+#endif
+int         dictIncludes   (FICL_DICT *pDict, void *p);
+FICL_WORD  *dictLookup     (FICL_DICT *pDict, STRINGINFO si);
+#if FICL_WANT_LOCALS
+FICL_WORD  *ficlLookupLoc  (FICL_SYSTEM *pSys, STRINGINFO si);
+#endif
+void        dictResetSearchOrder(FICL_DICT *pDict);
+void        dictSetFlags   (FICL_DICT *pDict, UNS8 set, UNS8 clr);
+void        dictSetImmediate(FICL_DICT *pDict);
+void        dictUnsmudge   (FICL_DICT *pDict);
+CELL       *dictWhere      (FICL_DICT *pDict);
+
+typedef int (*FICL_PARSE_STEP)(FICL_VM *pVM, STRINGINFO si);
+
+int  ficlAddParseStep(FICL_SYSTEM *pSys, FICL_WORD *pFW); /* ficl.c */
+void ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep);
+void ficlListParseSteps(FICL_VM *pVM);
+
+typedef struct FICL_BREAKPOINT
+{
+    void      *address;
+    FICL_WORD *origXT;
+} FICL_BREAKPOINT;
+
+
+struct ficl_system 
+{
+	void *pExtend;
+	ficlOutputFunction textOut;
+	ficlOutputFunction errorTextOut;
+	ficlSystem *pSys;
+	ficlVm *vm;
+    FICL_SYSTEM *link;
+    FICL_VM *vmList;
+    FICL_DICT *dp;
+    FICL_DICT *envp;
+    FICL_WORD *pInterp[3];
+    FICL_WORD *parseList[FICL_MAX_PARSE_STEPS];
+
+	FICL_WORD *pExitInner;
+	FICL_WORD *pInterpret;
+
+#if FICL_WANT_LOCALS
+    FICL_DICT *localp;
+	FICL_INT   nLocals;
+	CELL *pMarkLocals;
+#endif
+
+	ficlInteger stackSize;
+
+	FICL_BREAKPOINT bpStep;
+};
+
+struct ficl_system_info
+{
+	int size;           /* structure size tag for versioning */
+	void *pExtend;      /* Initializes VM's pExtend pointer - for application use */
+	int nDictCells;     /* Size of system's Dictionary */
+	int stackSize;     /* Size of system's Dictionary */
+	OUTFUNC textOut;    /* default textOut function */
+    int nEnvCells;      /* Size of Environment dictionary */
+};
+
+
+#define ficlInitInfo(x) { memset((x), 0, sizeof(FICL_SYSTEM_INFO)); \
+         (x)->size = sizeof(FICL_SYSTEM_INFO); }
+
+FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi);
+FICL_SYSTEM *ficlInitSystem(int nDictCells);
+void       ficlTermSystem(FICL_SYSTEM *pSys);
+int        ficlEvaluate(FICL_VM *pVM, char *pText);
+int        ficlExec (FICL_VM *pVM, char *pText);
+int        ficlExecC(FICL_VM *pVM, char *pText, FICL_INT nChars);
+int        ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord);
+FICL_VM   *ficlNewVM(FICL_SYSTEM *pSys);
+void ficlFreeVM(FICL_VM *pVM);
+int ficlSetStackSize(int nStackCells);
+FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name);
+FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys);
+FICL_DICT *ficlGetEnv (FICL_SYSTEM *pSys);
+void       ficlSetEnv (FICL_SYSTEM *pSys, char *name, FICL_UNS value);
+void       ficlSetEnvD(FICL_SYSTEM *pSys, char *name, FICL_UNS hi, FICL_UNS lo);
+#if FICL_WANT_LOCALS
+FICL_DICT *ficlGetLoc (FICL_SYSTEM *pSys);
+#endif
+int        ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags);
+void       ficlCompileCore(FICL_SYSTEM *pSys);
+void       ficlCompilePrefix(FICL_SYSTEM *pSys);
+void       ficlCompileSearch(FICL_SYSTEM *pSys);
+void       ficlCompileSoftCore(FICL_SYSTEM *pSys);
+void       ficlCompileTools(FICL_SYSTEM *pSys);
+void       ficlCompileFile(FICL_SYSTEM *pSys);
+#if FICL_WANT_FLOAT
+void       ficlCompileFloat(FICL_SYSTEM *pSys);
+int        ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si ); /* float.c */
+#endif
+#if FICL_WANT_PLATFORM
+void       ficlCompilePlatform(FICL_SYSTEM *pSys);
+#endif
+int        ficlParsePrefix(FICL_VM *pVM, STRINGINFO si);
+
+void       constantParen(FICL_VM *pVM);
+void       twoConstParen(FICL_VM *pVM);
+int        ficlParseNumber(FICL_VM *pVM, STRINGINFO si);
+void       ficlTick(FICL_VM *pVM);
+void       parseStepParen(FICL_VM *pVM);
+
+int        isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW);
+
+
+
+/* we define it ourselves, for naughty programs that call it directly. */
+void        ficlTextOut      (FICL_VM *pVM, char *text, int fNewline);
+/* but you can use this one! */
+void        ficlTextOutLocal (FICL_VM *pVM, char *text, int fNewline);
+
+
+#endif /* FICL_FORCE_COMPATIBILITY */
--- /dev/null
+++ b/ficldll.def
@@ -1,0 +1,176 @@
+;;;
+;;; Generated by makedef.py at 2003/05/17 19:58:13
+;;;
+
+EXPORTS
+
+ficl2IntegerAbsoluteValue @1
+ficl2IntegerDivideFloored @2
+ficl2IntegerDivideSymmetric @3
+ficl2UnsignedDivide @4
+ficlAlignPointer @5
+ficlBitGet @6
+ficlBitGetString @7
+ficlBitSet @8
+ficlCallbackAssert @9
+ficlCallbackDefaultTextOut @10
+ficlCallbackTextOut @11
+ficlDictionaryAbortDefinition @12
+ficlDictionaryAlign @13
+ficlDictionaryAllot @14
+ficlDictionaryAllotCells @15
+ficlDictionaryAppend2Constant @16
+ficlDictionaryAppend2ConstantInstruction @17
+ficlDictionaryAppendCell @18
+ficlDictionaryAppendCharacter @19
+ficlDictionaryAppendConstant @20
+ficlDictionaryAppendConstantInstruction @21
+ficlDictionaryAppendData @22
+ficlDictionaryAppendInstruction @23
+ficlDictionaryAppendPrimitive @24
+ficlDictionaryAppendString @25
+ficlDictionaryAppendUnsigned @26
+ficlDictionaryAppendWord @27
+ficlDictionaryCellsAvailable @28
+ficlDictionaryCellsUsed @29
+ficlDictionaryClearFlags @30
+ficlDictionaryCreate @31
+ficlDictionaryCreateHashed @32
+ficlDictionaryCreateWordlist @33
+ficlDictionaryDestroy @34
+ficlDictionaryEmpty @35
+ficlDictionaryFindEnclosingWord @36
+ficlDictionaryIncludes @37
+ficlDictionaryIsAWord @38
+ficlDictionaryLookup @39
+ficlDictionaryResetSearchOrder @40
+ficlDictionarySee @41
+ficlDictionarySet2Constant @42
+ficlDictionarySet2ConstantInstruction @43
+ficlDictionarySetConstant @44
+ficlDictionarySetConstantInstruction @45
+ficlDictionarySetFlags @46
+ficlDictionarySetImmediate @47
+ficlDictionarySetInstruction @48
+ficlDictionarySetPrimitive @49
+ficlDictionaryUnsmudge @50
+ficlDictionaryWhere @51
+ficlDigitToCharacter @52
+ficlFileTruncate @53
+ficlFree @54
+ficlHashCode @55
+ficlHashForget @56
+ficlHashInsertWord @57
+ficlHashLookup @58
+ficlHashReset @59
+ficlIsPowerOfTwo @60
+ficlLocalParen @61
+ficlLocalParenIm @62
+ficlLtoa @63
+ficlLzDecodeHeaderField @64
+ficlLzUncompress @65
+ficlMalloc @66
+ficlPrimitiveHashSummary @67
+ficlPrimitiveLiteralIm @68
+ficlPrimitiveParseStepParen @69
+ficlPrimitiveTick @70
+ficlRealloc @71
+ficlStackCheck @72
+ficlStackCreate @73
+ficlStackDepth @74
+ficlStackDestroy @75
+ficlStackWalk @76
+ficlStackDisplay @77
+ficlStackDrop @78
+ficlStackFetch @79
+ficlStackGetTop @80
+ficlStackLink @81
+ficlStackPick @82
+ficlStackPop @83
+ficlStackPop2Integer @84
+ficlStackPop2Unsigned @85
+ficlStackPopFloat @86
+ficlStackPopInteger @87
+ficlStackPopPointer @88
+ficlStackPopUnsigned @89
+ficlStackPush @90
+ficlStackPush2Integer @91
+ficlStackPush2Unsigned @92
+ficlStackPushFloat @93
+ficlStackPushInteger @94
+ficlStackPushPointer @95
+ficlStackPushUnsigned @96
+ficlStackReset @97
+ficlStackRoll @98
+ficlStackSetTop @99
+ficlStackStore @100
+ficlStackUnlink @101
+ficlStrincmp @102
+ficlStringCaseFold @103
+ficlStringReverse @104
+ficlStringSkipSpace @105
+ficlSystemAddParseStep @106
+ficlSystemAddPrimitiveParseStep @107
+ficlSystemCompileCore @108
+ficlSystemCompileFile @109
+ficlSystemCompileFloat @110
+ficlSystemCompilePlatform @111
+ficlSystemCompilePrefix @112
+ficlSystemCompileSearch @113
+ficlSystemCompileSoftCore @114
+ficlSystemCompileTools @115
+ficlSystemCreate @116
+ficlSystemCreateVm @117
+ficlSystemDestroy @118
+ficlSystemDestroyVm @119
+ficlSystemGetDictionary @120
+ficlSystemGetEnvironment @121
+ficlSystemGetLocals @122
+ficlSystemLookup @123
+ficlSystemLookupLocal @124
+ficlUltoa @125
+ficlVmBranchRelative @126
+ficlVmCreate @127
+ficlVmDestroy @128
+ficlVmDictionaryAllot @129
+ficlVmDictionaryAllotCells @130
+ficlVmDictionaryCheck @131
+ficlVmDictionarySimpleCheck @132
+ficlVmDisplayDataStack @133
+ficlVmDisplayDataStackSimple @134
+ficlVmDisplayFloatStack @135
+ficlVmDisplayReturnStack @136
+ficlVmEvaluate @137
+ficlVmExecuteString @138
+ficlVmExecuteWord @139
+ficlVmExecuteXT @140
+ficlVmGetDictionary @141
+ficlVmGetString @142
+ficlVmGetWord @143
+ficlVmGetWord0 @144
+ficlVmGetWordToPad @145
+ficlVmInnerLoop @146
+ficlVmParseFloatNumber @147
+ficlVmParseNumber @148
+ficlVmParseString @149
+ficlVmParseStringEx @150
+ficlVmParseWord @151
+ficlVmParsePrefix @152
+ficlVmPop @153
+ficlVmPopIP @154
+ficlVmPopTib @155
+ficlVmPush @156
+ficlVmPushIP @157
+ficlVmPushTib @158
+ficlVmQuit @159
+ficlVmReset @160
+ficlVmSetTextOut @161
+ficlVmTextOut @162
+ficlVmThrow @163
+ficlVmThrowError @164
+ficlWordClassify @165
+ficlWordIsCompileOnly @166
+ficlWordIsImmediate @167
+
+;;; end-of-file
+
--- /dev/null
+++ b/ficldll.dsp
@@ -1,0 +1,219 @@
+# Microsoft Developer Studio Project File - Name="ficldll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=ficldll - Win32 Debug Multithreaded DLL
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "ficldll.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "ficldll.mak" CFG="ficldll - Win32 Debug Multithreaded DLL"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "ficldll - Win32 Release Singlethreaded" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ficldll - Win32 Release Multithreaded" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ficldll - Win32 Release Multithreaded DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ficldll - Win32 Debug Singlethreaded" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ficldll - Win32 Debug Multithreaded" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "ficldll - Win32 Debug Multithreaded DLL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "ficldll"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "ficldll - Win32 Release Singlethreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "dll/release/singlethreaded"
+# PROP BASE Intermediate_Dir "dll/release/singlethreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "dll/release/singlethreaded"
+# PROP Intermediate_Dir "dll/release/singlethreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 lib/release/singlethreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /machine:I386 /out:"dll/release/singlethreaded/ficl.dll"
+
+!ELSEIF  "$(CFG)" == "ficldll - Win32 Release Multithreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "dll/release/multithreaded"
+# PROP BASE Intermediate_Dir "dll/release/multithreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "dll/release/multithreaded"
+# PROP Intermediate_Dir "dll/release/multithreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 lib/release/multithreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /machine:I386 /out:"dll/release/multithreaded/ficl.dll"
+
+!ELSEIF  "$(CFG)" == "ficldll - Win32 Release Multithreaded DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "dll/release/multithreaded_dll"
+# PROP BASE Intermediate_Dir "dll/release/multithreaded_dll"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "dll/release/multithreaded_dll"
+# PROP Intermediate_Dir "dll/release/multithreaded_dll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 lib/release/multithreaded_dll/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /machine:I386 /out:"dll/release/multithreaded_dll/ficl.dll"
+
+!ELSEIF  "$(CFG)" == "ficldll - Win32 Debug Singlethreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "dll/debug/singlethreaded"
+# PROP BASE Intermediate_Dir "dll/debug/singlethreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "dll/debug/singlethreaded"
+# PROP Intermediate_Dir "dll/debug/singlethreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lib/debug/singlethreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /debug /machine:I386 /out:"dll/debug/singlethreaded/ficl.dll" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "ficldll - Win32 Debug Multithreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "dll/debug/multithreaded"
+# PROP BASE Intermediate_Dir "dll/debug/multithreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "dll/debug/multithreaded"
+# PROP Intermediate_Dir "dll/debug/multithreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lib/debug/multithreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /debug /machine:I386 /out:"dll/debug/multithreaded/ficl.dll" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "ficldll - Win32 Debug Multithreaded DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "dll/debug/multithreaded_dll"
+# PROP BASE Intermediate_Dir "dll/debug/multithreaded_dll"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "dll/debug/multithreaded_dll"
+# PROP Intermediate_Dir "dll/debug/multithreaded_dll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "FICLDLL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lib/debug/multithreaded_dll/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /map /debug /machine:I386 /out:"dll/debug/multithreaded_dll/ficl.dll" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "ficldll - Win32 Release Singlethreaded"
+# Name "ficldll - Win32 Release Multithreaded"
+# Name "ficldll - Win32 Release Multithreaded DLL"
+# Name "ficldll - Win32 Debug Singlethreaded"
+# Name "ficldll - Win32 Debug Multithreaded"
+# Name "ficldll - Win32 Debug Multithreaded DLL"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\ficldll.def
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/ficlexe.dsp
@@ -1,0 +1,206 @@
+# Microsoft Developer Studio Project File - Name="ficlexe" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=ficlexe - Win32 Debug Multithreaded DLL
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "ficlexe.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "ficlexe.mak" CFG="ficlexe - Win32 Debug Multithreaded DLL"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "ficlexe - Win32 Release Singlethreaded" (based on "Win32 (x86) Console Application")
+!MESSAGE "ficlexe - Win32 Release Multithreaded" (based on "Win32 (x86) Console Application")
+!MESSAGE "ficlexe - Win32 Release Multithreaded DLL" (based on "Win32 (x86) Console Application")
+!MESSAGE "ficlexe - Win32 Debug Singlethreaded" (based on "Win32 (x86) Console Application")
+!MESSAGE "ficlexe - Win32 Debug Multithreaded" (based on "Win32 (x86) Console Application")
+!MESSAGE "ficlexe - Win32 Debug Multithreaded DLL" (based on "Win32 (x86) Console Application")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "ficlexe"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "ficlexe - Win32 Release Singlethreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "exe/release/singlethreaded"
+# PROP BASE Intermediate_Dir "exe/release/singlethreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "exe/release/singlethreaded"
+# PROP Intermediate_Dir "exe/release/singlethreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 lib/release/singlethreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /machine:I386 /out:"exe/release/singlethreaded/ficl.exe"
+
+!ELSEIF  "$(CFG)" == "ficlexe - Win32 Release Multithreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "exe/release/multithreaded"
+# PROP BASE Intermediate_Dir "exe/release/multithreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "exe/release/multithreaded"
+# PROP Intermediate_Dir "exe/release/multithreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 lib/release/multithreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /machine:I386 /out:"exe/release/multithreaded/ficl.exe"
+
+!ELSEIF  "$(CFG)" == "ficlexe - Win32 Release Multithreaded DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "exe/release/multithreaded_dll"
+# PROP BASE Intermediate_Dir "exe/release/multithreaded_dll"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "exe/release/multithreaded_dll"
+# PROP Intermediate_Dir "exe/release/multithreaded_dll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 lib/release/multithreaded_dll/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /machine:I386 /out:"exe/release/multithreaded_dll/ficl.exe"
+
+!ELSEIF  "$(CFG)" == "ficlexe - Win32 Debug Singlethreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "exe/debug/singlethreaded"
+# PROP BASE Intermediate_Dir "exe/debug/singlethreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "exe/debug/singlethreaded"
+# PROP Intermediate_Dir "exe/debug/singlethreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lib/debug/singlethreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /debug /machine:I386 /out:"exe/debug/singlethreaded/ficl.exe" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "ficlexe - Win32 Debug Multithreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "exe/debug/multithreaded"
+# PROP BASE Intermediate_Dir "exe/debug/multithreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "exe/debug/multithreaded"
+# PROP Intermediate_Dir "exe/debug/multithreaded"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lib/debug/multithreaded/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /debug /machine:I386 /out:"exe/debug/multithreaded/ficl.exe" /pdbtype:sept
+
+!ELSEIF  "$(CFG)" == "ficlexe - Win32 Debug Multithreaded DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "exe/debug/multithreaded_dll"
+# PROP BASE Intermediate_Dir "exe/debug/multithreaded_dll"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "exe/debug/multithreaded_dll"
+# PROP Intermediate_Dir "exe/debug/multithreaded_dll"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 lib/debug/multithreaded_dll/ficl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /map /debug /machine:I386 /out:"exe/debug/multithreaded_dll/ficl.exe" /pdbtype:sept
+
+!ENDIF 
+
+# Begin Target
+
+# Name "ficlexe - Win32 Release Singlethreaded"
+# Name "ficlexe - Win32 Release Multithreaded"
+# Name "ficlexe - Win32 Release Multithreaded DLL"
+# Name "ficlexe - Win32 Debug Singlethreaded"
+# Name "ficlexe - Win32 Debug Multithreaded"
+# Name "ficlexe - Win32 Debug Multithreaded DLL"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/ficllib.dsp
@@ -1,0 +1,296 @@
+# Microsoft Developer Studio Project File - Name="ficllib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=ficllib - Win32 Debug Multithreaded DLL
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "ficllib.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "ficllib.mak" CFG="ficllib - Win32 Debug Multithreaded DLL"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "ficllib - Win32 Debug Singlethreaded" (based on "Win32 (x86) Static Library")
+!MESSAGE "ficllib - Win32 Debug Multithreaded" (based on "Win32 (x86) Static Library")
+!MESSAGE "ficllib - Win32 Debug Multithreaded DLL" (based on "Win32 (x86) Static Library")
+!MESSAGE "ficllib - Win32 Release Singlethreaded" (based on "Win32 (x86) Static Library")
+!MESSAGE "ficllib - Win32 Release Multithreaded" (based on "Win32 (x86) Static Library")
+!MESSAGE "ficllib - Win32 Release Multithreaded DLL" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "ficllib"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "ficllib - Win32 Debug Singlethreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "lib/debug/singlethreaded"
+# PROP BASE Intermediate_Dir "lib/debug/singlethreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "lib/debug/singlethreaded"
+# PROP Intermediate_Dir "lib/debug/singlethreaded"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W4 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /Zm200 /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib/debug/singlethreaded/ficl.lib"
+
+!ELSEIF  "$(CFG)" == "ficllib - Win32 Debug Multithreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "lib/debug/multithreaded"
+# PROP BASE Intermediate_Dir "lib/debug/multithreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "lib/debug/multithreaded"
+# PROP Intermediate_Dir "lib/debug/multithreaded"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W4 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /Zm200 /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib/debug/multithreaded/ficl.lib"
+
+!ELSEIF  "$(CFG)" == "ficllib - Win32 Debug Multithreaded DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "lib/debug/multithreaded_dll"
+# PROP BASE Intermediate_Dir "lib/debug/multithreaded_dll"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "lib/debug/multithreaded_dll"
+# PROP Intermediate_Dir "lib/debug/multithreaded_dll"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W4 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /Zm200 /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib/debug/multithreaded_dll/ficl.lib"
+
+!ELSEIF  "$(CFG)" == "ficllib - Win32 Release Singlethreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "lib/release/singlethreaded"
+# PROP BASE Intermediate_Dir "lib/release/singlethreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "lib/release/singlethreaded"
+# PROP Intermediate_Dir "lib/release/singlethreaded"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W4 /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D FICL_ROBUST=0 /YX /FD /Zm200 /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib/release/singlethreaded/ficl.lib"
+
+!ELSEIF  "$(CFG)" == "ficllib - Win32 Release Multithreaded"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "lib/release/multithreaded"
+# PROP BASE Intermediate_Dir "lib/release/multithreaded"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "lib/release/multithreaded"
+# PROP Intermediate_Dir "lib/release/multithreaded"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MT /W4 /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D FICL_ROBUST=0 /YX /FD /Zm200 /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib/release/multithreaded/ficl.lib"
+
+!ELSEIF  "$(CFG)" == "ficllib - Win32 Release Multithreaded DLL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "lib/release/multithreaded_dll"
+# PROP BASE Intermediate_Dir "lib/release/multithreaded_dll"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "lib/release/multithreaded_dll"
+# PROP Intermediate_Dir "lib/release/multithreaded_dll"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /MD /W4 /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D FICL_ROBUST=0 /YX /FD /Zm200 /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"lib/release/multithreaded_dll/ficl.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "ficllib - Win32 Debug Singlethreaded"
+# Name "ficllib - Win32 Debug Multithreaded"
+# Name "ficllib - Win32 Debug Multithreaded DLL"
+# Name "ficllib - Win32 Release Singlethreaded"
+# Name "ficllib - Win32 Release Multithreaded"
+# Name "ficllib - Win32 Release Multithreaded DLL"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\bit.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\callback.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\compatibility.c
+# End Source File
+# Begin Source File
+
+SOURCE=dictionary.c
+# End Source File
+# Begin Source File
+
+SOURCE=double.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\extras.c
+# End Source File
+# Begin Source File
+
+SOURCE=fileaccess.c
+# End Source File
+# Begin Source File
+
+SOURCE=float.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\lzuncompress.c
+# End Source File
+# Begin Source File
+
+SOURCE=prefix.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\primitives.c
+# End Source File
+# Begin Source File
+
+SOURCE=search.c
+# End Source File
+# Begin Source File
+
+SOURCE=softcore.c
+# End Source File
+# Begin Source File
+
+SOURCE=stack.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\system.c
+# End Source File
+# Begin Source File
+
+SOURCE=tools.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\utility.c
+# End Source File
+# Begin Source File
+
+SOURCE=vm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ficlplatform\win32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\word.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=ficl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ficlcompatibility.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ficllocal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ficltokens.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ficlplatform\win32.h
+# End Source File
+# End Group
+# End Target
+# End Project
--- /dev/null
+++ b/ficllocal.h
@@ -1,0 +1,8 @@
+/*
+**	ficllocal.h
+**
+** Put all local settings here.  This file will always ship empty.
+**
+*/
+
+
--- /dev/null
+++ b/ficlplatform/alpha.h
@@ -1,0 +1,27 @@
+/*
+** FreeBSD Alpha (64 bit) data types
+*/
+
+#define FICL_WANT_PLATFORM (1)
+
+#define FICL_PLATFORM_BASIC_TYPES   (1)
+#define FICL_PLATFORM_ALIGNMENT     (8)
+
+#define FICL_PLATFORM_HAS_2INTEGER  (0)
+#define FICL_PLATFORM_HAS_FTRUNCATE (1)
+#define FICL_PLATFORM_INLINE        inline
+#define FICL_PLATFORM_OS            "FreeBSD"
+#define FICL_PLATFORM_ARCHITECTURE  "alpha"
+
+typedef char ficlInteger8;
+typedef unsigned char ficlUnsigned8;
+typedef short ficlInteger16;
+typedef unsigned short ficlUnsigned16;
+typedef int ficlInteger32;
+typedef unsigned int ficlUnsigned32;
+typedef long ficlInteger64;
+typedef unsigned long ficlUnsigned64;
+
+typedef ficlInteger64 ficlInteger;
+typedef ficlUnsigned64 ficlUnsigned;
+typedef float ficlFloat;
--- /dev/null
+++ b/ficlplatform/ansi.c
@@ -1,0 +1,64 @@
+#include "../ficl.h"
+
+
+
+
+void *ficlMalloc(size_t size)
+{
+    return malloc(size);
+}
+
+void *ficlRealloc(void *p, size_t size)
+{
+    return realloc(p, size);
+}
+
+void ficlFree(void *p)
+{
+    free(p);
+}
+
+void  ficlCallbackDefaultTextOut(ficlCallback *callback, char *message)
+{
+    FICL_IGNORE(callback);
+    if (message != NULL)
+        fputs(message, stdout);
+    else
+        fflush(stdout);
+    return;
+}
+
+
+/* not supported under strict ANSI C */
+int ficlFileStatus(char *filename, int *status)
+{
+    *status = -1;
+    return -1;
+}
+
+
+/* gotta do it the hard way under strict ANSI C */
+long ficlFileSize(ficlFile *ff)
+{
+    long currentOffset;
+    long size;
+
+    if (ff == NULL)
+        return -1;
+
+    currentOffset = ftell(ff->f);
+    fseek(ff->f, 0, SEEK_END);
+    size = ftell(ff->f);
+    fseek(ff->f, currentOffset, SEEK_SET);
+
+    return size;
+}
+
+
+
+void ficlSystemCompilePlatform(ficlSystem *system)
+{
+    return;
+}
+
+
--- /dev/null
+++ b/ficlplatform/ansi.h
@@ -1,0 +1,17 @@
+typedef char ficlInteger8;
+typedef unsigned char ficlUnsigned8;
+typedef short ficlInteger16;
+typedef unsigned short ficlUnsigned16;
+typedef long ficlInteger32;
+typedef unsigned long ficlUnsigned32;
+
+typedef ficlInteger32 ficlInteger;
+typedef ficlUnsigned32 ficlUnsigned;
+typedef float ficlFloat;
+
+#define FICL_PLATFORM_BASIC_TYPES   (1)
+#define FICL_PLATFORM_HAS_2INTEGER  (0)
+#define FICL_PLATFORM_HAS_FTRUNCATE (0)
+
+#define FICL_PLATFORM_OS            "ansi"
+#define FICL_PLATFORM_ARCHITECTURE  "unknown"
--- /dev/null
+++ b/ficlplatform/ficlexports.txt
@@ -1,0 +1,168 @@
+ficl2IntegerAbsoluteValue
+ficl2IntegerDivideFloored
+ficl2IntegerDivideSymmetric
+ficl2UnsignedDivide
+ficlAlignPointer
+ficlBitGet
+ficlBitGetString
+ficlBitSet
+ficlCallbackAssert
+ficlCallbackDefaultTextOut
+ficlCallbackTextOut
+ficlDictionaryAbortDefinition
+ficlDictionaryAlign
+ficlDictionaryAllot
+ficlDictionaryAllotCells
+ficlDictionaryAppend2Constant
+ficlDictionaryAppend2ConstantInstruction
+ficlDictionaryAppendCell
+ficlDictionaryAppendCharacter
+ficlDictionaryAppendConstant
+ficlDictionaryAppendConstantInstruction
+ficlDictionaryAppendData
+ficlDictionaryAppendInstruction
+ficlDictionaryAppendPrimitive
+ficlDictionaryAppendString
+ficlDictionaryAppendUnsigned
+ficlDictionaryAppendWord
+ficlDictionaryCellsAvailable
+ficlDictionaryCellsUsed
+ficlDictionaryClearFlags
+ficlDictionaryCreate
+ficlDictionaryCreateHashed
+ficlDictionaryCreateWordlist
+ficlDictionaryDestroy
+ficlDictionaryEmpty
+ficlDictionaryFindEnclosingWord
+ficlDictionaryIncludes
+ficlDictionaryIsAWord
+ficlDictionaryLookup
+ficlDictionaryResetSearchOrder
+ficlDictionarySee
+ficlDictionarySet2Constant
+ficlDictionarySet2ConstantInstruction
+ficlDictionarySetConstant
+ficlDictionarySetConstantInstruction
+ficlDictionarySetFlags
+ficlDictionarySetImmediate
+ficlDictionarySetInstruction
+ficlDictionarySetPrimitive
+ficlDictionaryUnsmudge
+ficlDictionaryWhere
+ficlDigitToCharacter
+ficlFileTruncate
+ficlFree
+ficlHashCode
+ficlHashForget
+ficlHashInsertWord
+ficlHashLookup
+ficlHashReset
+ficlIsPowerOfTwo
+ficlLocalParen
+ficlLocalParenIm
+ficlLtoa
+ficlLzDecodeHeaderField
+ficlLzUncompress
+ficlMalloc
+ficlPrimitiveHashSummary
+ficlPrimitiveLiteralIm
+ficlPrimitiveParseStepParen
+ficlPrimitiveTick
+ficlRealloc
+ficlStackCheck
+ficlStackCreate
+ficlStackDepth
+ficlStackDestroy
+ficlStackWalk
+ficlStackDisplay
+ficlStackDrop
+ficlStackFetch
+ficlStackGetTop
+ficlStackLink
+ficlStackPick
+ficlStackPop
+ficlStackPop2Integer
+ficlStackPop2Unsigned
+ficlStackPopFloat
+ficlStackPopInteger
+ficlStackPopPointer
+ficlStackPopUnsigned
+ficlStackPush
+ficlStackPush2Integer
+ficlStackPush2Unsigned
+ficlStackPushFloat
+ficlStackPushInteger
+ficlStackPushPointer
+ficlStackPushUnsigned
+ficlStackReset
+ficlStackRoll
+ficlStackSetTop
+ficlStackStore
+ficlStackUnlink
+ficlStrincmp
+ficlStringCaseFold
+ficlStringReverse
+ficlStringSkipSpace
+ficlSystemAddParseStep
+ficlSystemAddPrimitiveParseStep
+ficlSystemCompileCore
+ficlSystemCompileFile
+ficlSystemCompileFloat
+ficlSystemCompilePlatform
+ficlSystemCompilePrefix
+ficlSystemCompileSearch
+ficlSystemCompileSoftCore
+ficlSystemCompileTools
+ficlSystemCreate
+ficlSystemCreateVm
+ficlSystemDestroy
+ficlSystemDestroyVm
+ficlSystemGetDictionary
+ficlSystemGetEnvironment
+ficlSystemGetLocals
+ficlSystemLookup
+ficlSystemLookupLocal
+ficlUltoa
+ficlVmBranchRelative
+ficlVmCreate
+ficlVmDestroy
+ficlVmDictionaryAllot
+ficlVmDictionaryAllotCells
+ficlVmDictionaryCheck
+ficlVmDictionarySimpleCheck
+ficlVmDisplayDataStack
+ficlVmDisplayDataStackSimple
+ficlVmDisplayFloatStack
+ficlVmDisplayReturnStack
+ficlVmEvaluate
+ficlVmExecuteString
+ficlVmExecuteWord
+ficlVmExecuteXT
+ficlVmGetDictionary
+ficlVmGetString
+ficlVmGetWord
+ficlVmGetWord0
+ficlVmGetWordToPad
+ficlVmInnerLoop
+ficlVmParseFloatNumber
+ficlVmParseNumber
+ficlVmParseString
+ficlVmParseStringEx
+ficlVmParseWord
+ficlVmParsePrefix
+ficlVmPop
+ficlVmPopIP
+ficlVmPopTib
+ficlVmPush
+ficlVmPushIP
+ficlVmPushTib
+ficlVmQuit
+ficlVmReset
+ficlVmSetTextOut
+ficlVmTextOut
+ficlVmThrow
+ficlVmThrowError
+ficlWordClassify
+ficlWordIsCompileOnly
+ficlWordIsImmediate
+
--- /dev/null
+++ b/ficlplatform/makedef.py
@@ -1,0 +1,33 @@
+###
+### makedef.py
+### Generates a simple .DEF file for Ficl,
+### based on a text file containing all exported symbols.
+###
+### Contributed by Larry Hastings.
+###
+
+import string
+import time
+
+f = open("ficlexports.txt", "rt")
+output = open("../ficldll.def", "wt")
+counter = 1
+
+print >> output, ";;;"
+print >> output, ";;; Generated by makedef.py at " + time.strftime("%Y/%m/%d %H:%M:%S")
+print >> output, ";;;"
+print >> output, ""
+print >> output, "EXPORTS"
+print >> output, ""
+for a in f.readlines():
+	a = string.strip(a)
+	if len(a) == 0:
+		continue
+	print >> output, a + " @" + str(counter)
+	counter += 1
+
+print >> output, ""
+print >> output, ";;; end-of-file"
+print >> output, ""
+f.close()
+output.close()
--- /dev/null
+++ b/ficlplatform/unix.c
@@ -1,0 +1,75 @@
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "../ficl.h"
+
+
+
+int ficlFileTruncate(ficlFile *ff, ficlUnsigned size)
+{
+	return ftruncate(fileno(ff->f), size);
+}
+
+
+
+void *ficlMalloc(size_t size)
+{
+    return malloc(size);
+}
+
+void *ficlRealloc(void *p, size_t size)
+{
+    return realloc(p, size);
+}
+
+void ficlFree(void *p)
+{
+    free(p);
+}
+
+void  ficlCallbackDefaultTextOut(ficlCallback *callback, char *message)
+{
+    FICL_IGNORE(callback);
+    if (message != NULL)
+        fputs(message, stdout);
+    else
+        fflush(stdout);
+    return;
+}
+
+int ficlFileStatus(char *filename, int *status)
+{
+    struct stat statbuf;
+    if (stat(filename, &statbuf) == 0)
+    {
+        *status = statbuf.st_mode;
+        return 0;
+    }
+    *status = ENOENT;
+    return -1;
+}
+
+
+long ficlFileSize(ficlFile *ff)
+{
+    struct stat statbuf;
+    if (ff == NULL)
+        return -1;
+	
+    statbuf.st_size = -1;
+    if (fstat(fileno(ff->f), &statbuf) != 0)
+        return -1;
+	
+    return statbuf.st_size;
+}
+
+
+
+
+void ficlSystemCompilePlatform(ficlSystem *system)
+{
+    return;
+}
+
+
--- /dev/null
+++ b/ficlplatform/unix.h
@@ -1,0 +1,30 @@
+#include <unistd.h>
+
+
+#define FICL_WANT_PLATFORM (1)
+
+#define FICL_PLATFORM_OS              "unix"
+#define FICL_PLATFORM_ARCHITECTURE    "unknown"
+
+#define FICL_PLATFORM_BASIC_TYPES     (1)
+#define FICL_PLATFORM_ALIGNMENT       (4)
+#define FICL_PLATFORM_INLINE          inline
+
+#define FICL_PLATFORM_HAS_FTRUNCATE   (1)
+#define FICL_PLATFORM_HAS_2INTEGER    (1)
+
+typedef char ficlInteger8;
+typedef unsigned char ficlUnsigned8;
+typedef short ficlInteger16;
+typedef unsigned short ficlUnsigned16;
+typedef long ficlInteger32;
+typedef unsigned long ficlUnsigned32;
+typedef long long ficlInteger64;
+typedef unsigned long long ficlUnsigned64;
+
+typedef ficlInteger32 ficlInteger;
+typedef ficlUnsigned32 ficlUnsigned;
+typedef float ficlFloat;
+
+typedef ficlInteger64 ficl2Integer;
+typedef ficlUnsigned64 ficl2Unsigned;
--- /dev/null
+++ b/ficlplatform/win32.c
@@ -1,0 +1,413 @@
+/* 
+** win32.c
+** submitted to Ficl by Larry Hastings, larry@hastings.org
+**/
+
+#include <sys/stat.h>
+#include "../ficl.h"
+
+
+/*
+**
+** Heavy, undocumented wizardry here.
+**
+** In Win32, like most OSes, the buffered file I/O functions in the
+** C API (functions that take a FILE * like fopen()) are implemented
+** on top of the raw file I/O functions (functions that take an int,
+** like open()).  However, in Win32, these functions in turn are
+** implemented on top of the Win32 native file I/O functions (functions
+** that take a HANDLE, like CreateFile()).  This behavior is undocumented
+** but easy to deduce by reading the CRT/SRC directory.
+**
+** The below mishmash of typedefs and defines were copied from
+** CRT/SRC/INTERNAL.H from MSVC.
+**
+** --lch
+*/
+typedef struct {
+        long osfhnd;    /* underlying OS file HANDLE */
+        char osfile;    /* attributes of file (e.g., open in text mode?) */
+        char pipech;    /* one char buffer for handles opened on pipes */
+#ifdef _MT
+        int lockinitflag;
+        CRITICAL_SECTION lock;
+#endif  /* _MT */
+    }   ioinfo;
+extern _CRTIMP ioinfo * __pioinfo[];
+
+#define IOINFO_L2E          5
+#define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
+#define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - \
+                              1)) )
+#define _osfhnd(i)  ( _pioinfo(i)->osfhnd )
+
+
+int ficlFileTruncate(ficlFile *ff, ficlUnsigned size)
+{
+    HANDLE hFile = (HANDLE)_osfhnd(_fileno(ff->f));
+    if (SetFilePointer(hFile, size, NULL, FILE_BEGIN) != size)
+        return 0;
+    return !SetEndOfFile(hFile);
+}
+
+
+int ficlFileStatus(char *filename, int *status)
+{
+    /*
+	** The Windows documentation for GetFileAttributes() says it returns
+    ** INVALID_FILE_ATTRIBUTES on error.  There's no such #define.  The
+    ** return value for error is -1, so we'll just use that.
+	*/
+    DWORD attributes = GetFileAttributes(filename);
+	if (attributes == -1)
+	{
+		*status = GetLastError();
+		return -1;
+	}
+    *status = attributes;
+    return 0;
+}
+
+
+long ficlFileSize(ficlFile *ff)
+{
+    struct stat statbuf;
+    if (ff == NULL)
+        return -1;
+	
+    statbuf.st_size = -1;
+    if (fstat(fileno(ff->f), &statbuf) != 0)
+        return -1;
+	
+    return statbuf.st_size;
+}
+
+
+
+
+
+void *ficlMalloc(size_t size)
+{
+    return malloc(size);
+}
+
+void *ficlRealloc(void *p, size_t size)
+{
+    return realloc(p, size);
+}
+
+void ficlFree(void *p)
+{
+    free(p);
+}
+
+void  ficlCallbackDefaultTextOut(ficlCallback *callback, char *message)
+{
+    FICL_IGNORE(callback);
+    if (message != NULL)
+        fputs(message, stdout);
+    else
+        fflush(stdout);
+    return;
+}
+
+
+
+/*
+**
+** Platform-specific functions
+**
+*/
+
+
+/* 
+** m u l t i c a l l
+**
+** The be-all, end-all, swiss-army-chainsaw of native function call methods in Ficl.
+**
+** Usage:
+** ( x*argumentCount [this] [vtable] argumentCount floatArgumentBitfield cstringArgumentBitfield functionAddress flags -- returnValue | )
+** Note that any/all of the arguments (x*argumentCount) and the return value can use the
+** float stack instead of the data stack.
+**
+** To call a simple native function:
+**   call with flags = MULTICALL_CALLTYPE_FUNCTION
+** To call a method on an object:
+**   pass in the "this" pointer just below argumentCount,
+**   call with flags = MULTICALL_CALLTYPE_METHOD
+**   *do not* include the "this" pointer for the purposes of argumentCount
+** To call a virtual method on an object:
+**   pass in the "this" pointer just below argumentCount,
+**   call with flags = MULTICALL_CALLTYPE_VIRTUAL_METHOD
+**   *do not* include the "this" pointer for the purposes of argumentCount
+**   the function address must be the offset into the vtable for that function
+** It doesn't matter whether the function you're calling is "stdcall" (caller pops
+** the stack) or "fastcall" (callee pops the stack); for robustness, multicall
+** always restores the original stack pointer anyway.
+**
+**
+** To handle floating-point arguments:
+**   To thunk an argument from the float stack instead of the data stack, set the corresponding bit
+**   in the "floatArgumentBitfield" argument.  Argument zero is bit 0 (1), argument one is bit 1 (2),
+**   argument 2 is is bit 2 (4), argument 3 is bit 3 (8), etc.  For instance, to call this function:
+**      float greasyFingers(int a, float b, int c, float d)
+**   you would call
+**      4  \ argumentCount
+**      2 8 or \ floatArgumentBitfield, thunk argument 2 (2) and 4 (8)
+**      0 \ cstringArgumentBitfield, don't thunk any arguments
+**      (addressOfGreasyFingers)  MULTICALL-CALLTYPE-FUNCTION MULTICALL-RETURNTYPE-FLOAT or multicall
+**
+** To handle automatic conversion of addr-u arguments to C-style strings:
+**   This is much like handling float arguments.   The bit set in cstringArgumentBitfield specifies
+**   the *length* argument (the higher of the two arguments) for each addr-u you want converted.
+**   You must count *both* arguments for the purposes of the argumentCount parameter.
+**   For instance, to call the Win32 function MessageBoxA:
+**	
+**      0 "Howdy there!" "Title" 0
+**      6  \ argument count is 6!  flags text-addr text-u title-addr title-u hwnd 
+**      0  \ floatArgumentBitfield, don't thunk any float arguments
+**      2 8 or  \ cstringArgumentBitfield, thunk for title-u (argument 2, 2) and text-u (argument 4, 8)
+**      (addressOfMessageBoxA)  MULTICALL-CALLTYPE-FUNCTION MULTICALL-RETURNTYPE-INTEGER or multicall
+**   The strings are copied to temporary storage and appended with a zero.  These strings are freed
+**   before multicall returns.  If you need to call functions that write to these string buffers,
+**   you'll need to handle thunking those arguments yourself.
+**
+** (If you want to call a function with more than 32 parameters, and do thunking, you need to hit somebody
+**  in the head with a rock.  Note: this could be you!)
+**
+** Note that, big surprise, this function is really really really dependent
+** on predefined behavior of Win32 and MSVC.  It would be non-zero amounts of
+** work to port to Win64, Linux, other compilers, etc.
+** 
+** --lch
+*/
+static void ficlPrimitiveMulticall(ficlVm *vm)
+{
+    int flags;
+    int functionAddress;
+    int argumentCount;
+    int *thisPointer;
+    int integerReturnValue;
+#if FICL_WANT_FLOAT
+    float floatReturnValue;
+#endif /* FICL_WANT_FLOAT */
+    int cstringArguments;
+    int floatArguments;
+    int i;
+    char **fixups;
+    int fixupCount;
+    int fixupIndex;
+    int *argumentPointer;
+    int finalArgumentCount;
+    int argumentDirection;
+    int *adjustedArgumentPointer;
+    int originalESP;
+    int vtable;
+
+    flags = ficlStackPopInteger(vm->dataStack);
+
+    functionAddress = ficlStackPopInteger(vm->dataStack);
+    if (FICL_MULTICALL_GET_CALLTYPE(flags) == FICL_MULTICALL_CALLTYPE_VIRTUAL_METHOD)
+        functionAddress *= 4;
+
+    cstringArguments = ficlStackPopInteger(vm->dataStack);
+    floatArguments = ficlStackPopInteger(vm->dataStack);
+#if !FICL_WANT_FLOAT
+    FICL_VM_ASSERT(vm, !floatArguments);
+    FICL_VM_ASSERT(vm, FICL_MULTICALL_GET_RETURNTYPE(flags) != FICL_MULTICALL_RETURNTYPE_FLOAT);
+#endif /* !FICL_WANT_FLOAT */
+    argumentCount = ficlStackPopInteger(vm->dataStack);
+
+    fixupCount = 0;
+    if (cstringArguments)
+    {
+        for (i = 0; i < argumentCount; i++)
+            if (cstringArguments & (1 << i))
+                fixupCount++;
+        fixups = (char **)malloc(fixupCount * sizeof(char *));
+    }
+    else
+    {
+        fixups = NULL;
+    }
+
+
+    /* argumentCount does *not* include the *this* pointer! */
+    if (FICL_MULTICALL_GET_CALLTYPE(flags) != FICL_MULTICALL_CALLTYPE_FUNCTION)
+    {
+        if (flags & FICL_MULTICALL_EXPLICIT_VTABLE)
+            vtable = ficlStackPopInteger(vm->dataStack);
+
+        __asm push ecx
+        thisPointer = (int *)ficlStackPopPointer(vm->dataStack);
+
+        if ((flags & FICL_MULTICALL_EXPLICIT_VTABLE) == 0)
+            vtable = *thisPointer;
+	}
+
+
+    __asm mov originalESP, esp
+
+    fixupIndex = 0;
+    finalArgumentCount = argumentCount - fixupCount;
+    __asm mov argumentPointer, esp
+    adjustedArgumentPointer = argumentPointer - finalArgumentCount;
+    __asm mov esp, adjustedArgumentPointer
+    if (flags & FICL_MULTICALL_REVERSE_ARGUMENTS)
+    {
+        argumentDirection = -1;
+        argumentPointer--;
+    }
+    else
+    {
+        argumentPointer = adjustedArgumentPointer;
+        argumentDirection = 1;
+    }
+
+    for (i = 0; i < argumentCount; i++)
+    {
+        int argument;
+
+        /* a single argument can't be both a float and a cstring! */
+        FICL_VM_ASSERT(vm, !((floatArguments & 1) && (cstringArguments & 1)));
+
+#if FICL_WANT_FLOAT
+        if (floatArguments & 1)
+            argument = ficlStackPopInteger(vm->floatStack);
+        else
+#endif /* FICL_WANT_FLOAT */
+            argument = ficlStackPopInteger(vm->dataStack);
+
+        if (cstringArguments & 1)
+        {
+            int length;
+            char *address;
+            char *buffer;
+            address = ficlStackPopPointer(vm->dataStack);
+            length = argument;
+            buffer = malloc(length + 1);
+            memcpy(buffer, address, length);
+            buffer[length] = 0;
+            fixups[fixupIndex++] = buffer;
+            argument = (int)buffer;
+            argumentCount--;
+            floatArguments >>= 1;
+            cstringArguments >>= 1;
+        }
+
+        *argumentPointer = argument;
+        argumentPointer += argumentDirection;
+
+        floatArguments >>= 1;
+        cstringArguments >>= 1;
+    }
+
+
+    /*
+    ** note! leave the "mov ecx, thisPointer" code where it is.
+    ** yes, it's duplicated in two spots.
+    ** however, MSVC likes to use ecx as a scratch variable,
+    ** so we want to set it as close as possible before the call.
+    */
+    if (FICL_MULTICALL_GET_CALLTYPE(flags) == FICL_MULTICALL_CALLTYPE_VIRTUAL_METHOD)
+    {
+        __asm
+        {
+            /* push thisPointer */
+            mov ecx, thisPointer
+            /* put vtable into eax. */
+            mov eax, vtable
+            /* pull out the address of the function we want... */
+            add eax, functionAddress
+            /* and call it. */
+            call [eax]
+        }
+    }
+    else
+    {
+        FICL_VM_ASSERT(vm, functionAddress != 0);
+        if (FICL_MULTICALL_GET_CALLTYPE(flags))
+        {
+            __asm mov ecx, thisPointer
+        }
+        __asm call functionAddress
+    }
+
+    /* save off the return value, if there is one */
+    __asm mov integerReturnValue, eax
+#if FICL_WANT_FLOAT
+    __asm fst floatReturnValue
+#endif /* FICL_WANT_FLOAT */
+
+    __asm mov esp, originalESP
+
+    if (FICL_MULTICALL_GET_CALLTYPE(flags))
+    {
+        __asm pop ecx
+    }
+
+    if (FICL_MULTICALL_GET_RETURNTYPE(flags) == FICL_MULTICALL_RETURNTYPE_INTEGER)
+        ficlStackPushInteger(vm->dataStack, integerReturnValue);
+    else if (FICL_MULTICALL_GET_RETURNTYPE(flags) == FICL_MULTICALL_RETURNTYPE_CSTRING)
+    {
+        char *str = (char *)(void *)integerReturnValue;
+        ficlStackPushInteger(vm->dataStack, integerReturnValue);
+        ficlStackPushInteger(vm->dataStack, strlen(str));
+    }
+#if FICL_WANT_FLOAT
+    else if (FICL_MULTICALL_GET_RETURNTYPE(flags) == FICL_MULTICALL_RETURNTYPE_FLOAT)
+        ficlStackPushFloat(vm->floatStack, floatReturnValue);
+#endif /* FICL_WANT_FLOAT */
+
+    if (fixups != NULL)
+    {
+        for (i = 0; i < fixupCount; i++)
+            if (fixups[i] != NULL)
+                free(fixups[i]);
+        free(fixups);
+    }
+
+    return;
+}
+
+
+
+
+/**************************************************************************
+                        f i c l C o m p i l e P l a t f o r m
+** Build Win32 platform extensions into the system dictionary
+**************************************************************************/
+void ficlSystemCompilePlatform(ficlSystem *system)
+{
+    HMODULE hModule;
+    ficlDictionary *dictionary = system->dictionary;
+    FICL_SYSTEM_ASSERT(system, dictionary);
+    
+    /*
+    ** one native function call to rule them all, one native function call to find them,
+    ** one native function call to bring them all and in the darkness bind them.
+    ** --lch (with apologies to j.r.r.t.)
+    */
+    ficlDictionarySetPrimitive(dictionary, "multicall",      ficlPrimitiveMulticall,      FICL_WORD_DEFAULT);
+    ficlDictionarySetConstant(dictionary, "multicall-calltype-function", FICL_MULTICALL_CALLTYPE_FUNCTION);
+    ficlDictionarySetConstant(dictionary, "multicall-calltype-method", FICL_MULTICALL_CALLTYPE_METHOD);
+    ficlDictionarySetConstant(dictionary, "multicall-calltype-virtual-method", FICL_MULTICALL_CALLTYPE_VIRTUAL_METHOD);
+    ficlDictionarySetConstant(dictionary, "multicall-returntype-void", FICL_MULTICALL_RETURNTYPE_VOID);
+    ficlDictionarySetConstant(dictionary, "multicall-returntype-integer", FICL_MULTICALL_RETURNTYPE_INTEGER);
+    ficlDictionarySetConstant(dictionary, "multicall-returntype-cstring", FICL_MULTICALL_RETURNTYPE_CSTRING);
+    ficlDictionarySetConstant(dictionary, "multicall-returntype-float", FICL_MULTICALL_RETURNTYPE_FLOAT);
+    ficlDictionarySetConstant(dictionary, "multicall-reverse-arguments", FICL_MULTICALL_REVERSE_ARGUMENTS);
+    ficlDictionarySetConstant(dictionary, "multicall-explit-vtable", FICL_MULTICALL_EXPLICIT_VTABLE);
+
+    /*
+    ** Every other Win32-specific word is implemented in Ficl, with multicall or whatnot.
+    ** (Give me a lever, and a place to stand, and I will move the Earth.)
+    ** See softcore/win32.fr for details.  --lch
+    */
+    hModule = LoadLibrary("kernel32.dll");
+    ficlDictionarySetConstantPointer(dictionary, "kernel32.dll", hModule);
+    ficlDictionarySetConstantPointer(dictionary, "(get-proc-address)", GetProcAddress(hModule, "GetProcAddress"));
+    FreeLibrary(hModule);
+
+    return;
+}
--- /dev/null
+++ b/ficlplatform/win32.h
@@ -1,0 +1,64 @@
+/*
+** Note that Microsoft's own header files won't compile without
+** "language extensions" (anonymous structs/unions) turned on.
+** And even with that, it still gives a warning in rpcasync.h:
+**    warning C4115: '_RPC_ASYNC_STATE' : named type definition in parentheses
+** It compiles clean in C++.  Oy vey.  So I turned off the warning. --lch
+*/
+#pragma warning(disable: 4115)
+#include <windows.h>
+#pragma warning(default: 4115)
+#include <direct.h>
+
+#define FICL_WANT_PLATFORM (1)
+
+#define FICL_PLATFORM_OS             "Win32"
+#define FICL_PLATFORM_ARCHITECTURE   "x86"
+
+#define FICL_PLATFORM_BASIC_TYPES    (1)
+#define FICL_PLATFORM_ALIGNMENT      (4)
+#define FICL_PLATFORM_INLINE	     __inline
+
+#define FICL_PLATFORM_HAS_2INTEGER   (1)
+#define FICL_PLATFORM_HAS_FTRUNCATE  (1)
+
+#define fstat       _fstat
+#define stat        _stat
+#define getcwd      _getcwd
+#define chdir       _chdir
+#define fileno      _fileno
+
+
+extern int ftruncate(int fileno, size_t size);
+
+typedef char ficlInteger8;
+typedef unsigned char ficlUnsigned8;
+typedef short ficlInteger16;
+typedef unsigned short ficlUnsigned16;
+typedef long ficlInteger32;
+typedef unsigned long ficlUnsigned32;
+typedef __int64 ficlInteger64;
+typedef unsigned __int64 ficlUnsigned64;
+
+typedef ficlInteger32 ficlInteger;
+typedef ficlUnsigned32 ficlUnsigned;
+typedef float ficlFloat;
+
+typedef ficlInteger64 ficl2Integer;
+typedef ficlUnsigned64 ficl2Unsigned;
+
+
+#define FICL_MULTICALL_CALLTYPE_FUNCTION        (0)
+#define FICL_MULTICALL_CALLTYPE_METHOD          (1)
+#define FICL_MULTICALL_CALLTYPE_VIRTUAL_METHOD	(2)
+#define FICL_MULTICALL_GET_CALLTYPE(flags)      ((flags) & 0x0f)
+
+#define FICL_MULTICALL_RETURNTYPE_VOID          (0)
+#define FICL_MULTICALL_RETURNTYPE_INTEGER       (16)
+#define FICL_MULTICALL_RETURNTYPE_CSTRING       (32)
+#define FICL_MULTICALL_RETURNTYPE_FLOAT         (48)
+#define FICL_MULTICALL_GET_RETURNTYPE(flags)    ((flags) & 0xf0)
+
+#define FICL_MULTICALL_REVERSE_ARGUMENTS        (1<<8)
+#define FICL_MULTICALL_EXPLICIT_VTABLE          (1<<9) /* the vtable is specified on the stack */
+
--- /dev/null
+++ b/ficltokens.h
@@ -1,0 +1,228 @@
+FICL_TOKEN(ficlInstructionInvalid, "** invalid **")
+FICL_TOKEN(ficlInstruction1, "1")
+FICL_TOKEN(ficlInstruction2, "2")
+FICL_TOKEN(ficlInstruction3, "3")
+FICL_TOKEN(ficlInstruction4, "4")
+FICL_TOKEN(ficlInstruction5, "5")
+FICL_TOKEN(ficlInstruction6, "6")
+FICL_TOKEN(ficlInstruction7, "7")
+FICL_TOKEN(ficlInstruction8, "8")
+FICL_TOKEN(ficlInstruction9, "9")
+FICL_TOKEN(ficlInstruction10, "10")
+FICL_TOKEN(ficlInstruction11, "11")
+FICL_TOKEN(ficlInstruction12, "12")
+FICL_TOKEN(ficlInstruction13, "13")
+FICL_TOKEN(ficlInstruction14, "14")
+FICL_TOKEN(ficlInstruction15, "15")
+FICL_TOKEN(ficlInstruction16, "16")
+FICL_TOKEN(ficlInstruction0, "0")
+FICL_TOKEN(ficlInstructionNeg1, "-1")
+FICL_TOKEN(ficlInstructionNeg2, "-2")
+FICL_TOKEN(ficlInstructionNeg3, "-3")
+FICL_TOKEN(ficlInstructionNeg4, "-4")
+FICL_TOKEN(ficlInstructionNeg5, "-5")
+FICL_TOKEN(ficlInstructionNeg6, "-6")
+FICL_TOKEN(ficlInstructionNeg7, "-7")
+FICL_TOKEN(ficlInstructionNeg8, "-8")
+FICL_TOKEN(ficlInstructionNeg9, "-9")
+FICL_TOKEN(ficlInstructionNeg10, "-10")
+FICL_TOKEN(ficlInstructionNeg11, "-11")
+FICL_TOKEN(ficlInstructionNeg12, "-12")
+FICL_TOKEN(ficlInstructionNeg13, "-13")
+FICL_TOKEN(ficlInstructionNeg14, "-14")
+FICL_TOKEN(ficlInstructionNeg15, "-15")
+FICL_TOKEN(ficlInstructionNeg16, "-16")
+#if FICL_WANT_FLOAT
+FICL_TOKEN(ficlInstructionF0, "0.0e")
+FICL_TOKEN(ficlInstructionF1, "1.0e")
+FICL_TOKEN(ficlInstructionFNeg1, "-1.0e")
+#endif /* FICL_WANT_FLOAT */
+FICL_INSTRUCTION_TOKEN(ficlInstructionPlus, "+", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionMinus, "-", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction1Plus, "1+", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction1Minus, "1-", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Plus, "2+", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Minus, "2-", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionSemiParen, "(;)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionExitParen, "(exit)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionDup, "dup", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionSwap, "swap", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionGreaterThan, ">", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionBranchParenWithCheck, "(branch)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionBranchParen, "(branch-final)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionBranch0ParenWithCheck, "(branch0)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionBranch0Paren, "(branch0-final)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionLiteralParen, "(literal)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionLoopParen, "(loop)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionOfParen, "(of)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionPlusLoopParen, "(+loop)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFetch, "@", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionStore, "!", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionComma, ",", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCComma, "c,", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCells, "cells", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCellPlus, "cell+", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionNegate, "negate", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionStar, "*", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionSlash, "/", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionStarSlash, "*/", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionSlashMod, "/mod", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionStarSlashMod, "*/mod", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Star, "2*", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Slash, "2/", FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionColonParen, "** (colon) **", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionVariableParen, "(variable)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionConstantParen, "(constant)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2ConstantParen, "(2constant)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2LiteralParen, "(2literal)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionDoDoes, "** do-does **", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionDoParen, "(do)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionDoesParen, "(does)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionQDoParen, "(?do)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCreateParen, "(create)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionStringLiteralParen, "(.\")", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCStringLiteralParen, "(c\")", FICL_WORD_COMPILE_ONLY)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionPlusStore,      "+!",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction0Less,       "0<",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction0Greater,    "0>",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction0Equals,     "0=",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Store,       "2!",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Fetch,       "2@",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionOver,           "over",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionRot,            "rot",       FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Drop,        "2drop",     FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Dup,         "2dup",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Over,        "2over",     FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2Swap,        "2swap",     FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFromRStack,     "r>",        FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFetchRStack,    "r@",        FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2ToR,       "2>r",         FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2RFrom,       "2r>",       FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstruction2RFetch,      "2r@",       FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionLess,         "<",         FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionEquals,        "=",         FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToRStack,       ">r",        FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionQuestionDup,    "?dup",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionAnd,     "and",       FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCStore,         "c!",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCFetch,         "c@",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionDrop,           "drop",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionPick,           "pick",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionRoll,           "roll",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionMinusRoll,      "-roll",     FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionMinusRot,      "-rot",     FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFill,           "fill",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionSToD,           "s>d",       FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionULess,        "u<",        FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionQuadFetch,      "q@",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionQuadStore,      "q!",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionWFetch,         "w@",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionWStore,         "w!",        FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionInvert,     "invert",    FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionLShift,         "lshift",    FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionMax,        "max",       FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionMin,        "min",       FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionMove,           "move",      FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionOr,      "or",        FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionRShift,         "rshift",    FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionXor,     "xor",       FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionI,        "i",         FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionJ,        "j",         FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionK,        "k",         FICL_WORD_COMPILE_ONLY)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionCompare,  "compare",   FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionCompareInsensitive,  "compare-insensitive",   FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionRandom,     "random",    FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionSeedRandom,"seed-random",FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionLeave, "leave", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionUnloop, "unloop", FICL_WORD_COMPILE_ONLY)
+
+#if FICL_WANT_USER
+FICL_INSTRUCTION_TOKEN(ficlInstructionUserParen, "(user)", FICL_WORD_DEFAULT)
+#endif /* FICL_WANT_USER */
+
+#if FICL_WANT_LOCALS
+FICL_INSTRUCTION_TOKEN(ficlInstructionLinkParen, "(link)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionUnlinkParen, "(unlink)", FICL_WORD_COMPILE_ONLY)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionGetLocalParen, "(@local)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionGet2LocalParen, "(@2Local)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToLocalParen, "(toLocal)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionTo2LocalParen, "(to2Local)", FICL_WORD_COMPILE_ONLY)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionGetLocal0, "(@local0)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionGet2Local0, "(@2Local0)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToLocal0, "(toLocal0)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionTo2Local0, "(To2Local0)", FICL_WORD_COMPILE_ONLY)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionGetLocal1, "(@local1)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToLocal1, "(toLocal1)", FICL_WORD_COMPILE_ONLY)
+
+#if FICL_WANT_FLOAT
+FICL_INSTRUCTION_TOKEN(ficlInstructionGetFLocalParen, "(@fLocal)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionGetF2LocalParen, "(@f2Local)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToFLocalParen, "(toFLocal)", FICL_WORD_COMPILE_ONLY)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToF2LocalParen, "(toF2Local)", FICL_WORD_COMPILE_ONLY)
+#endif /* FICL_WANT_FLOAT */
+
+#endif /* FICL_WANT_LOCALS */
+
+#if FICL_WANT_FLOAT
+FICL_INSTRUCTION_TOKEN(ficlInstructionFLiteralParen, "(fliteral)", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFConstantParen, "(fconstant)", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2ConstantParen, "(f2constant)", FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionFPlus, "f+", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFMinus, "f-", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFStar, "f*", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFSlash, "f/", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFNegate, "fnegate", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFPlusI, "f+i", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFMinusI, "f-i", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFStarI, "f*i", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFSlashI, "f/i", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionIMinusF, "i-f", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionISlashF, "i/f", FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionFFrom, "float>", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionToF, ">float", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionIntToFloat, "int>float", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFloatToInt, "float>int", FICL_WORD_DEFAULT)
+	
+FICL_INSTRUCTION_TOKEN(ficlInstructionFFetch, "f@", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFStore, "f!", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2Fetch, "f2@", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2Store, "f2!", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFPlusStore, "f+!", FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionFDrop, "fdrop", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2Drop, "f2drop", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFDup, "fdup", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2Dup, "f2dup", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFMinusRoll, "f-roll", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFMinusRot, "f-rot", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFQuestionDup, "f?dup", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFOver, "fover", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2Over, "f2over", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFPick, "fpick", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFRoll, "froll", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFRot, "frot", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFSwap, "fswap", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF2Swap, "f2swap", FICL_WORD_DEFAULT)
+
+FICL_INSTRUCTION_TOKEN(ficlInstructionF0Less, "f0<", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFLess, "f<", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF0Equals, "f0=", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFEquals, "f=", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionF0Greater, "f0>", FICL_WORD_DEFAULT)
+FICL_INSTRUCTION_TOKEN(ficlInstructionFGreater, "f>", FICL_WORD_DEFAULT)
+	
+#endif  /* FICL_WANT_FLOAT */
+
+FICL_TOKEN(ficlInstructionExitInnerLoop, "** exit inner loop **")
--- /dev/null
+++ b/hash.c
@@ -1,0 +1,161 @@
+#include "ficl.h"
+
+
+#define FICL_ASSERT_PHASH(hash, expression) FICL_ASSERT(NULL, expression)
+
+
+
+/**************************************************************************
+                        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 ficlHashForget(ficlHash *hash, void *where)
+{
+    ficlWord *pWord;
+    unsigned i;
+
+    FICL_ASSERT_PHASH(hash, hash);
+    FICL_ASSERT_PHASH(hash, where);
+
+    for (i = 0; i < hash->size; i++)
+    {
+        pWord = hash->table[i];
+
+        while ((void *)pWord >= where)
+        {
+            pWord = pWord->link;
+        }
+
+        hash->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.
+**************************************************************************/
+ficlUnsigned16 ficlHashCode(ficlString s)
+{   
+    /* hashPJW */
+    ficlUnsigned8 *trace;
+    ficlUnsigned16 code = (ficlUnsigned16)s.length;
+    ficlUnsigned16 shift = 0;
+
+    if (s.length == 0)
+        return 0;
+
+    /* changed to run without errors under Purify -- lch */
+    for (trace = (ficlUnsigned8 *)s.text; s.length && *trace; trace++, s.length--)
+    {
+        code = (ficlUnsigned16)((code << 4) + tolower(*trace));
+        shift = (ficlUnsigned16)(code & 0xf000);
+        if (shift)
+        {
+            code ^= (ficlUnsigned16)(shift >> 8);
+            code ^= (ficlUnsigned16)shift;
+        }
+    }
+
+    return (ficlUnsigned16)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 ficlHashInsertWord(ficlHash *hash, ficlWord *word)
+{
+    ficlWord **pList;
+
+    FICL_ASSERT_PHASH(hash, hash);
+    FICL_ASSERT_PHASH(hash, word);
+
+    if (hash->size == 1)
+    {
+        pList = hash->table;
+    }
+    else
+    {
+        pList = hash->table + (word->hash % hash->size);
+    }
+
+    word->link = *pList;
+    *pList = word;
+    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 ficlWord 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.
+**************************************************************************/
+ficlWord *ficlHashLookup(ficlHash *hash, ficlString name, ficlUnsigned16 hashCode)
+{
+    ficlUnsigned nCmp = name.length;
+    ficlWord *word;
+    ficlUnsigned16 hashIdx;
+
+    if (nCmp > FICL_NAME_LENGTH)
+        nCmp = FICL_NAME_LENGTH;
+
+    for (; hash != NULL; hash = hash->link)
+    {
+        if (hash->size > 1)
+            hashIdx = (ficlUnsigned16)(hashCode % hash->size);
+        else            /* avoid the modulo op for single threaded lists */
+            hashIdx = 0;
+
+        for (word = hash->table[hashIdx]; word; word = word->link)
+        {
+            if ( (word->length == name.length) 
+                && (!ficlStrincmp(name.text, word->name, nCmp)) )
+                return word;
+#if FICL_ROBUST
+            FICL_ASSERT_PHASH(hash, word != word->link);
+#endif
+        }
+    }
+
+    return NULL;
+}
+
+
+/**************************************************************************
+                             h a s h R e s e t
+** Initialize a ficlHash to empty state.
+**************************************************************************/
+void ficlHashReset(ficlHash *hash)
+{
+    unsigned i;
+
+    FICL_ASSERT_PHASH(hash, hash);
+
+    for (i = 0; i < hash->size; i++)
+    {
+        hash->table[i] = NULL;
+    }
+
+    hash->link = NULL;
+    hash->name = NULL;
+    return;
+}
+
+
--- /dev/null
+++ b/lzcompress.c
@@ -1,0 +1,202 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ficl.h"
+
+#define NETWORK_ORDER(X) ((((unsigned char*)X[0]) << 8) | (((unsigned char *)X[1])))
+
+
+static int ficlLzCompareWindow(const unsigned char *window, const unsigned char *buffer,
+	int *offset, unsigned char *next, int windowSize, int bufferSize)
+	{
+	const unsigned char *windowEnd;
+	const unsigned char *bufferEnd;
+	int longest;
+	unsigned char bufferFirst;
+	const unsigned char *windowTrace;
+
+	longest = 0;
+	bufferFirst = buffer[0];
+	*next = bufferFirst;
+
+	/*
+	** we can't match more than bufferSize-1 characters...
+	** we need to reserve the last character for the "next",
+	** and this also prevents us from returning FICL_LZ_BUFFER_LENGTH
+	** as the length (which won't work, max we can store is FICL_LZ_BUFFER_LENGTH - 1)
+	*/
+	bufferSize--;
+
+	windowEnd = window + windowSize;
+	bufferEnd = buffer + bufferSize;
+
+	for (windowTrace = window; windowTrace < windowEnd; windowTrace++)
+		{
+		const unsigned char *bufferTrace;
+		const unsigned char *windowTrace2;
+		int length;
+
+		if (*windowTrace != bufferFirst)
+			continue;
+
+		bufferTrace = buffer;
+		for (windowTrace2 = windowTrace;
+			(windowTrace2 < windowEnd) && (bufferTrace < bufferEnd)
+				&& (*windowTrace2 == *bufferTrace);
+			windowTrace2++, bufferTrace++)
+			{
+			}
+
+		length = windowTrace2 - windowTrace;
+		if ((length > longest) && (length >= FICL_LZ_MINIMUM_USEFUL_MATCH))
+			{
+			*offset = windowTrace - window;
+			longest = length;
+			*next = *bufferTrace;
+			}
+		}
+
+	return longest;
+	}
+
+
+
+void ficlLzEncodeHeaderField(unsigned char *data, unsigned int input, int *byteOffset)
+	{
+	int i;
+
+	if (input <= 252)
+		data[(*byteOffset)++] = (unsigned char)input;
+	else
+		{
+		unsigned char id;
+		int length;
+		int inputPosition;
+		int bitsOffset;
+
+		if (input <= 65536)
+			{
+			id = 253;
+			length = 2;
+			}
+		else
+			{
+			id = 254;
+			length = 4;
+			}
+
+		input = ficlNetworkUnsigned32(input);
+		inputPosition = (sizeof(unsigned long) * 8) - (length * 8);
+		bitsOffset;
+
+		data[(*byteOffset)++] = (unsigned char)id;
+		bitsOffset = *byteOffset * 8;
+		(*byteOffset) += length;
+
+		for (i = 0; i < (length * 8); i++)
+			ficlBitSet(data, bitsOffset++, ficlBitGet((unsigned char *)&input, inputPosition++));
+		}
+	}
+
+
+
+int ficlLzCompress(const unsigned char *uncompressed, size_t uncompressedSize, unsigned char **compressed_p, size_t *compressedSize_p)
+	{
+	unsigned char *compressed;
+	const unsigned char *window;
+	const unsigned char *buffer;
+	int outputPosition;
+	int remaining;
+	int windowSize;
+	int headerLength;
+	unsigned char headerBuffer[10];
+	int compressedSize;
+	int totalSize;
+
+	*compressed_p = NULL;
+
+	compressed = (unsigned char *)calloc(((uncompressedSize * 5) / 4) + 10, 1);
+	if (compressed == NULL)
+		return -1;
+
+	window = buffer = uncompressed;
+
+	outputPosition = 0;
+	remaining = uncompressedSize;
+	windowSize = 0;
+
+	while (remaining > 0)
+		{
+		int bufferSize = FICL_MIN(remaining, FICL_LZ_BUFFER_SIZE);
+		int useWindowSize = FICL_MIN(remaining, windowSize);
+		int offset = 0;
+		int i;
+
+		unsigned long token;
+		int tokenLength;
+		unsigned char next;
+
+		int length = ficlLzCompareWindow(window, buffer, &offset, &next, useWindowSize, bufferSize);
+		if (length > 1)
+			{
+			/* phrase token */
+			assert((length - FICL_LZ_MINIMUM_USEFUL_MATCH) < (1 << FICL_LZ_LENGTH_BITS));
+			token = (1 << (FICL_LZ_PHRASE_BITS - 1))
+				| (offset << (FICL_LZ_PHRASE_BITS - FICL_LZ_TYPE_BITS - FICL_LZ_OFFSET_BITS))
+				| ((length - FICL_LZ_MINIMUM_USEFUL_MATCH) << (FICL_LZ_PHRASE_BITS - FICL_LZ_TYPE_BITS - FICL_LZ_OFFSET_BITS - FICL_LZ_LENGTH_BITS))
+				| next;
+
+			tokenLength = FICL_LZ_PHRASE_BITS;
+			}
+		else
+			{
+			token = next;
+			tokenLength = FICL_LZ_SYMBOL_BITS;
+			}
+
+		token = ficlNetworkUnsigned32(token);
+		for (i = 0; i < tokenLength; i++)
+			{
+			int inputPosition = (sizeof(unsigned long) * 8) - tokenLength + i;
+			ficlBitSet(compressed, outputPosition, ficlBitGet((unsigned char *)&token, inputPosition));
+			outputPosition++;
+			}
+
+		length++;
+
+		buffer += length;
+		if (windowSize == FICL_LZ_WINDOW_SIZE)
+			window += length;
+		else
+			{
+			if ((windowSize + length) < FICL_LZ_WINDOW_SIZE)
+				windowSize += length;
+			else
+				{
+				window += (windowSize + length) - FICL_LZ_WINDOW_SIZE;
+				windowSize = FICL_LZ_WINDOW_SIZE;
+				}
+			}
+
+		remaining -= length;
+		}
+
+	headerLength = 0;
+	memset(&headerBuffer, 0, sizeof(headerBuffer));
+	ficlLzEncodeHeaderField(headerBuffer, outputPosition, &headerLength);
+	ficlLzEncodeHeaderField(headerBuffer, uncompressedSize, &headerLength);
+
+	/* plug in header */
+	compressedSize = (((outputPosition - 1) / 8) + 1);
+	totalSize = compressedSize + headerLength;
+	compressed = (unsigned char *)realloc(compressed, totalSize);
+	memmove(compressed + headerLength, compressed, compressedSize);
+	memcpy(compressed, headerBuffer, headerLength);
+
+	*compressed_p = compressed;
+	*compressedSize_p = totalSize;
+
+	return 0;
+	}
+
--- /dev/null
+++ b/lzuncompress.c
@@ -1,0 +1,94 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "ficl.h"
+
+
+
+int ficlLzDecodeHeaderField(const unsigned char *data, int *byteOffset)
+	{
+	unsigned char id;
+	int networkOrder;
+	int length;
+
+	id = data[(*byteOffset)++];
+	if (id < 252)
+		return id;
+
+	networkOrder = 0;
+	length = (id == 253) ? 2: 4;
+
+	ficlBitGetString(((unsigned char *)&networkOrder), data,
+		(*byteOffset) * 8,
+		length * 8, sizeof(networkOrder) * 8);
+	(*byteOffset) += length;
+
+	return ficlNetworkUnsigned32(networkOrder);
+	}
+
+
+
+int ficlLzUncompress(const unsigned char *compressed, unsigned char **uncompressed_p, size_t *uncompressedSize_p)
+	{
+	unsigned char *window;
+	unsigned char *buffer;
+	unsigned char *uncompressed;
+	unsigned char *initialWindow;
+
+	int bitstreamLength;
+	int inputPosition;
+	int uncompressedSize;
+
+	*uncompressed_p = NULL;
+
+	inputPosition = 0;
+	bitstreamLength = ficlLzDecodeHeaderField(compressed, &inputPosition);
+	uncompressedSize = ficlLzDecodeHeaderField(compressed, &inputPosition);
+
+	inputPosition <<= 3; /* same as * 8 */
+
+	bitstreamLength += inputPosition;
+
+	uncompressed = (unsigned char *)calloc(uncompressedSize + 1, 1);
+	if (uncompressed == NULL)
+		return -1;
+	window = buffer = uncompressed;
+	initialWindow = buffer + FICL_LZ_WINDOW_SIZE;
+
+	while (inputPosition != bitstreamLength)
+		{
+		int length;
+		int token = ficlBitGet(compressed, inputPosition);
+		inputPosition++;
+
+		if (token)
+			{
+			/* phrase token */
+			int offset = 0;
+			ficlBitGetString((unsigned char *)&offset, compressed, inputPosition, FICL_LZ_PHRASE_BITS - (1 + FICL_LZ_NEXT_BITS), sizeof(offset) * 8);
+			offset = ficlNetworkUnsigned32(offset);
+			inputPosition += FICL_LZ_PHRASE_BITS - (1 + FICL_LZ_NEXT_BITS);
+
+			length = (offset & ((1 << FICL_LZ_LENGTH_BITS) - 1)) + FICL_LZ_MINIMUM_USEFUL_MATCH;
+			offset >>= FICL_LZ_LENGTH_BITS;
+
+			memmove(buffer, window + offset, length);
+			buffer += length;
+			length++;
+			}
+		else
+			length = 1;
+
+		/* symbol token */
+		*buffer = 0;
+		ficlBitGetString(buffer++, compressed, inputPosition, FICL_LZ_NEXT_BITS, sizeof(*buffer) * 8);
+		inputPosition += FICL_LZ_NEXT_BITS;
+		if (buffer > initialWindow)
+			window = buffer - FICL_LZ_WINDOW_SIZE;
+		}
+
+	*uncompressed_p = uncompressed;
+	*uncompressedSize_p = uncompressedSize;
+
+	return 0;
+	}
--- /dev/null
+++ b/main.c
@@ -1,0 +1,78 @@
+/*
+** stub main for testing Ficl
+** $Id: main.c,v 1.1 2010/08/12 12:50:32 asau Exp $
+*/
+/*
+** 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 <stdio.h>
+#include <stdlib.h>
+
+#include "ficl.h"
+
+
+int main(int argc, char **argv)
+{
+    int returnValue = 0;
+    char buffer[256];
+    ficlVm *vm;
+	ficlSystem *system;
+
+    system = ficlSystemCreate(NULL);
+    ficlSystemCompileExtras(system);
+    vm = ficlSystemCreateVm(system);
+
+    returnValue = ficlVmEvaluate(vm, ".ver .( " __DATE__ " ) cr quit");
+
+    /*
+    ** load files specified on command-line
+    */
+    if (argc  > 1)
+    {
+        sprintf(buffer, ".( loading %s ) cr load %s\n cr", argv[1], argv[1]);
+        returnValue = ficlVmEvaluate(vm, buffer);
+    }
+
+    while (returnValue != FICL_VM_STATUS_USER_EXIT)
+    {
+	    fputs(FICL_PROMPT, stdout);
+        fgets(buffer, sizeof(buffer), stdin);
+        returnValue = ficlVmEvaluate(vm, buffer);
+    }
+
+    ficlSystemDestroy(system);
+    return 0;
+}
+
--- /dev/null
+++ b/primitives.c
@@ -1,0 +1,3513 @@
+/*******************************************************************
+** w o r d s . c
+** Forth Inspired Command Language
+** ANS Forth CORE word-set written in C
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 19 July 1997
+** $Id: primitives.c,v 1.1 2010/08/12 12:50:33 asau Exp $
+*******************************************************************/
+/*
+** 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>
+#include <string.h>
+#include <ctype.h>
+#include "ficl.h"
+
+
+/*
+** Control structure building words use these
+** strings' addresses as markers on the stack to 
+** check for structure completion.
+*/
+static char doTag[]    = "do";
+static char colonTag[] = "colon";
+static char leaveTag[] = "leave";
+
+static char destTag[]  = "target";
+static char origTag[]  = "origin";
+
+static char caseTag[]  = "case";
+static char ofTag[]  = "of";
+static char fallthroughTag[]  = "fallthrough";
+
+/*
+** C O N T R O L   S T R U C T U R E   B U I L D E R S
+**
+** Push current dictionary location for later branch resolution.
+** The location may be either a branch target or a patch address...
+*/
+static void markBranch(ficlDictionary *dictionary, ficlVm *vm, char *tag)
+{
+    ficlStackPushPointer(vm->dataStack, dictionary->here);
+    ficlStackPushPointer(vm->dataStack, tag);
+    return;
+}
+
+static void markControlTag(ficlVm *vm, char *tag)
+{
+    ficlStackPushPointer(vm->dataStack, tag);
+    return;
+}
+
+static void matchControlTag(ficlVm *vm, char *wantTag)
+{
+    char *tag;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    tag = (char *)ficlStackPopPointer(vm->dataStack);
+    /*
+    ** Changed the code below to compare the pointers first (by popular demand)
+    */
+    if ( (tag != wantTag) && strcmp(tag, wantTag) )
+    {
+        ficlVmThrowError(vm, "Error -- unmatched control structure \"%s\"", wantTag);
+    }
+
+    return;
+}
+
+/*
+** Expect a branch target address on the param stack,
+** FICL_VM_STATE_COMPILE a literal offset from the current dictionary location
+** to the target address
+*/
+static void resolveBackBranch(ficlDictionary *dictionary, ficlVm *vm, char *tag)
+{
+    ficlInteger offset;
+    ficlCell *patchAddr;
+
+    matchControlTag(vm, tag);
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack);
+    offset = patchAddr - dictionary->here;
+    ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(offset));
+
+    return;
+}
+
+
+/*
+** Expect a branch patch address on the param stack,
+** FICL_VM_STATE_COMPILE a literal offset from the patch location
+** to the current dictionary location
+*/
+static void resolveForwardBranch(ficlDictionary *dictionary, ficlVm *vm, char *tag)
+{
+    ficlInteger offset;
+    ficlCell *patchAddr;
+
+    matchControlTag(vm, tag);
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack);
+    offset = dictionary->here - patchAddr;
+    *patchAddr = FICL_LVALUE_TO_CELL(offset);
+
+    return;
+}
+
+/*
+** Match the tag to the top of the stack. If success,
+** sopy "here" address into the ficlCell whose address is next
+** on the stack. Used by do..leave..loop.
+*/
+static void resolveAbsBranch(ficlDictionary *dictionary, ficlVm *vm, char *wantTag)
+{
+    ficlCell *patchAddr;
+    char *tag;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 0);
+
+    tag = ficlStackPopPointer(vm->dataStack);
+    /*
+    ** Changed the comparison below to compare the pointers first (by popular demand)
+    */
+    if ((tag != wantTag) && strcmp(tag, wantTag))
+    {
+        ficlVmTextOut(vm, "Warning -- Unmatched control word: ");
+        ficlVmTextOut(vm, wantTag);
+        ficlVmTextOut(vm, "\n");
+    }
+
+    patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack);
+    *patchAddr = FICL_LVALUE_TO_CELL(dictionary->here);
+
+    return;
+}
+
+
+/**************************************************************************
+                        c o l o n   d e f i n i t i o n s
+** Code to begin compiling a colon definition
+** This function sets the state to FICL_VM_STATE_COMPILE, then creates a
+** new word whose name is the next word in the input stream
+** and whose code is colonParen.
+**************************************************************************/
+
+static void ficlPrimitiveColon(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+
+    vm->state = FICL_VM_STATE_COMPILE;
+    markControlTag(vm, colonTag);
+    ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionColonParen, FICL_WORD_DEFAULT | FICL_WORD_SMUDGED);
+#if FICL_WANT_LOCALS
+    vm->callback.system->localsCount = 0;
+#endif
+    return;
+}
+
+
+       
+static void ficlPrimitiveSemicolonCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    matchControlTag(vm, colonTag);
+
+#if FICL_WANT_LOCALS
+    if (vm->callback.system->localsCount > 0)
+    {
+        ficlDictionary *locals = ficlSystemGetLocals(vm->callback.system);
+        ficlDictionaryEmpty(locals, locals->forthWordlist->size);
+            ficlDictionaryAppendUnsigned(dictionary, ficlInstructionUnlinkParen);
+    }
+    vm->callback.system->localsCount = 0;
+#endif
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionSemiParen);
+    vm->state = FICL_VM_STATE_INTERPRET;
+    ficlDictionaryUnsmudge(dictionary);
+    return;
+}
+
+
+/**************************************************************************
+                        e x i t
+** CORE
+** This function simply pops the previous instruction
+** pointer and returns to the "next" loop. Used for exiting from within
+** a definition. Note that exitParen is identical to semiParen - they
+** are in two different functions so that "see" can correctly identify
+** the end of a colon definition, even if it uses "exit".
+**************************************************************************/
+
+static void ficlPrimitiveExitCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    FICL_IGNORE(vm);
+
+#if FICL_WANT_LOCALS
+    if (vm->callback.system->localsCount > 0)
+    {
+		ficlDictionaryAppendUnsigned(dictionary, ficlInstructionUnlinkParen);
+    }
+#endif
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionExitParen);
+    return;
+}
+
+
+/**************************************************************************
+                        c o n s t a n t
+** IMMEDIATE
+** Compiles a constant into the dictionary. Constants return their
+** value when invoked. Expects a value on top of the parm stack.
+**************************************************************************/
+
+static void ficlPrimitiveConstant(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+	ficlDictionaryAppendConstantInstruction(dictionary, name, ficlInstructionConstantParen, ficlStackPopInteger(vm->dataStack));
+    return;
+}
+
+
+static void ficlPrimitive2Constant(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+    
+    FICL_STACK_CHECK(vm->dataStack, 2, 0);
+
+	ficlDictionaryAppend2ConstantInstruction(dictionary, name, ficlInstruction2ConstantParen, ficlStackPop2Integer(vm->dataStack));
+    return;
+}
+
+
+/**************************************************************************
+                        d i s p l a y C e l l
+** Drop and print the contents of the ficlCell at the top of the param
+** stack
+**************************************************************************/
+
+static void ficlPrimitiveDot(ficlVm *vm)
+{
+    ficlCell c;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    c = ficlStackPop(vm->dataStack);
+    ficlLtoa((c).i, vm->pad, vm->base);
+    strcat(vm->pad, " ");
+    ficlVmTextOut(vm, vm->pad);
+    return;
+}
+
+static void ficlPrimitiveUDot(ficlVm *vm)
+{
+    ficlUnsigned u;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    u = ficlStackPopUnsigned(vm->dataStack);
+    ficlUltoa(u, vm->pad, vm->base);
+    strcat(vm->pad, " ");
+    ficlVmTextOut(vm, vm->pad);
+    return;
+}
+
+
+static void ficlPrimitiveHexDot(ficlVm *vm)
+{
+    ficlUnsigned u;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    u = ficlStackPopUnsigned(vm->dataStack);
+    ficlUltoa(u, vm->pad, 16);
+    strcat(vm->pad, " ");
+    ficlVmTextOut(vm, vm->pad);
+    return;
+}
+
+
+/**************************************************************************
+                        s t r l e n
+** Ficl   ( c-string -- length )
+**
+** Returns the length of a C-style (zero-terminated) string.
+**
+** --lch
+**/
+static void ficlPrimitiveStrlen(ficlVm *vm)
+	{
+	char *address = (char *)ficlStackPopPointer(vm->dataStack);
+	ficlStackPushInteger(vm->dataStack, strlen(address));
+	}
+
+
+/**************************************************************************
+                        s p r i n t f
+** Ficl   ( i*x c-addr-fmt u-fmt c-addr-buffer u-buffer -- c-addr-buffer u-written success-flag )
+** Similar to the C sprintf() function.  It formats into a buffer based on
+** a "format" string.  Each character in the format string is copied verbatim
+** to the output buffer, until SPRINTF encounters a percent sign ("%").
+** SPRINTF then skips the percent sign, and examines the next character
+** (the "format character").  Here are the valid format characters:
+**    s - read a C-ADDR U-LENGTH string from the stack and copy it to
+**        the buffer
+**    d - read a ficlCell from the stack, format it as a string (base-10,
+**        signed), and copy it to the buffer
+**    x - same as d, except in base-16
+**    u - same as d, but unsigned
+**    % - output a literal percent-sign to the buffer
+** SPRINTF returns the c-addr-buffer argument unchanged, the number of bytes
+** written, and a flag indicating whether or not it ran out of space while
+** writing to the output buffer (FICL_TRUE if it ran out of space).
+**
+** If SPRINTF runs out of space in the buffer to store the formatted string,
+** it still continues parsing, in an effort to preserve your stack (otherwise
+** it might leave uneaten arguments behind).
+**
+** --lch
+**************************************************************************/
+static void ficlPrimitiveSprintf(ficlVm *vm) /*  */
+{
+	int bufferLength = ficlStackPopInteger(vm->dataStack);
+	char *buffer = (char *)ficlStackPopPointer(vm->dataStack);
+	char *bufferStart = buffer;
+
+	int formatLength = ficlStackPopInteger(vm->dataStack);
+	char *format = (char *)ficlStackPopPointer(vm->dataStack);
+	char *formatStop = format + formatLength;
+
+	int base = 10;
+	int unsignedInteger = FICL_FALSE;
+
+	int append = FICL_TRUE;
+
+	while (format < formatStop)
+	{
+		char scratch[64];
+		char *source;
+		int actualLength;
+		int desiredLength;
+		int leadingZeroes;
+
+
+		if (*format != '%')
+		{
+			source = format;
+			actualLength = desiredLength = 1;
+			leadingZeroes = 0;
+		}
+		else
+		{
+			format++;
+			if (format == formatStop)
+				break;
+
+			leadingZeroes = (*format == '0');
+			if (leadingZeroes)
+				{
+				format++;
+				if (format == formatStop)
+					break;
+				}
+
+			desiredLength = isdigit(*format);
+			if (desiredLength)
+				{
+				desiredLength = strtoul(format, &format, 10);
+				if (format == formatStop)
+					break;
+				}
+			else if (*format == '*')
+				{
+				desiredLength = ficlStackPopInteger(vm->dataStack);
+				format++;
+				if (format == formatStop)
+					break;
+				}
+
+
+			switch (*format)
+			{
+				case 's':
+				case 'S':
+				{
+					actualLength = ficlStackPopInteger(vm->dataStack);
+					source = (char *)ficlStackPopPointer(vm->dataStack);
+					break;
+				}
+				case 'x':
+				case 'X':
+					base = 16;
+				case 'u':
+				case 'U':
+					unsignedInteger = FICL_TRUE;
+				case 'd':
+				case 'D':
+				{
+					int integer = ficlStackPopInteger(vm->dataStack);
+					if (unsignedInteger)
+						ficlUltoa(integer, scratch, base);
+					else
+						ficlLtoa(integer, scratch, base);
+					base = 10;
+					unsignedInteger = FICL_FALSE;
+					source = scratch;
+					actualLength = strlen(scratch);
+					break;
+				}
+				case '%':
+					source = format;
+					actualLength = 1;
+				default:
+					continue;
+			}
+		}
+
+		if (append == FICL_TRUE)
+		{
+			if (!desiredLength)
+				desiredLength = actualLength;
+			if (desiredLength > bufferLength)
+			{
+				append = FICL_FALSE;
+				desiredLength = bufferLength;
+			}
+			while (desiredLength > actualLength)
+				{
+				*buffer++ = (char)((leadingZeroes) ? '0' : ' ');
+				bufferLength--;
+				desiredLength--;
+				}
+			memcpy(buffer, source, actualLength);
+			buffer += actualLength;
+			bufferLength -= actualLength;
+		}
+
+		format++;
+	}
+
+	ficlStackPushPointer(vm->dataStack, bufferStart);
+	ficlStackPushInteger(vm->dataStack, buffer - bufferStart);
+	ficlStackPushInteger(vm->dataStack, append);
+}
+
+
+/**************************************************************************
+                        d u p   &   f r i e n d s
+** 
+**************************************************************************/
+
+static void ficlPrimitiveDepth(ficlVm *vm)
+{
+    int i;
+
+    FICL_STACK_CHECK(vm->dataStack, 0, 1);
+
+    i = ficlStackDepth(vm->dataStack);
+    ficlStackPushInteger(vm->dataStack, i);
+    return;
+}
+
+
+/**************************************************************************
+                        e m i t   &   f r i e n d s
+** 
+**************************************************************************/
+
+static void ficlPrimitiveEmit(ficlVm *vm)
+{
+    char *buffer = vm->pad;
+    int i;
+
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    i = ficlStackPopInteger(vm->dataStack);
+    buffer[0] = (char)i;
+    buffer[1] = '\0';
+    ficlVmTextOut(vm, buffer);
+    return;
+}
+
+
+static void ficlPrimitiveCR(ficlVm *vm)
+{
+    ficlVmTextOut(vm, "\n");
+    return;
+}
+
+
+static void ficlPrimitiveBackslash(ficlVm *vm)
+{
+    char *trace        = ficlVmGetInBuf(vm);
+    char *stop      = ficlVmGetInBufEnd(vm);
+    char c = *trace;
+
+    while ((trace != stop) && (c != '\r') && (c != '\n'))
+    {
+        c = *++trace;
+    }
+
+    /*
+    ** Cope with DOS or UNIX-style EOLs -
+    ** Check for /r, /n, /r/n, or /n/r end-of-line sequences,
+    ** and point trace to next char. If EOL is \0, we're done.
+    */
+    if (trace != stop)
+    {
+        trace++;
+
+        if ( (trace != stop) && (c != *trace) 
+             && ((*trace == '\r') || (*trace == '\n')) )
+            trace++;
+    }
+
+    ficlVmUpdateTib(vm, trace);
+    return;
+}
+
+
+/*
+** paren CORE 
+** Compilation: Perform the execution semantics given below.
+** Execution: ( "ccc<paren>" -- )
+** Parse ccc delimited by ) (right parenthesis). ( is an immediate word. 
+** The number of characters in ccc may be zero to the number of characters
+** in the parse area. 
+** 
+*/
+static void ficlPrimitiveParenthesis(ficlVm *vm)
+{
+    ficlVmParseStringEx(vm, ')', 0);
+    return;
+}
+
+
+/**************************************************************************
+                        F E T C H   &   S T O R E
+** 
+**************************************************************************/
+
+/**************************************************************************
+                        i f C o I m
+** IMMEDIATE
+** Compiles code for a conditional branch into the dictionary
+** and pushes the branch patch address on the stack for later
+** patching by ELSE or THEN/ENDIF. 
+**************************************************************************/
+
+static void ficlPrimitiveIfCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranch0ParenWithCheck);
+    markBranch(dictionary, vm, origTag);
+    ficlDictionaryAppendUnsigned(dictionary, 1);
+    return;
+}
+
+
+
+
+/**************************************************************************
+                        e l s e C o I m
+** 
+** IMMEDIATE -- compiles an "else"...
+** 1) FICL_VM_STATE_COMPILE a branch and a patch address; the address gets patched
+**    by "endif" to point past the "else" code.
+** 2) Pop the the "if" patch address
+** 3) Patch the "if" branch to point to the current FICL_VM_STATE_COMPILE address.
+** 4) Push the "else" patch address. ("endif" patches this to jump past 
+**    the "else" code.
+**************************************************************************/
+
+static void ficlPrimitiveElseCoIm(ficlVm *vm)
+{
+    ficlCell *patchAddr;
+    ficlInteger offset;
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+                                            /* (1) FICL_VM_STATE_COMPILE branch runtime */
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranchParenWithCheck);
+    matchControlTag(vm, origTag);
+    patchAddr = 
+        (ficlCell *)ficlStackPopPointer(vm->dataStack);   /* (2) pop "if" patch addr */
+    markBranch(dictionary, vm, origTag);           /* (4) push "else" patch addr */
+    ficlDictionaryAppendUnsigned(dictionary, 1);                 /* (1) FICL_VM_STATE_COMPILE patch placeholder */
+    offset = dictionary->here - patchAddr;
+    *patchAddr = FICL_LVALUE_TO_CELL(offset);      /* (3) Patch "if" */
+
+    return;
+}
+
+
+/**************************************************************************
+                        e n d i f C o I m
+** 
+**************************************************************************/
+
+static void ficlPrimitiveEndifCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    resolveForwardBranch(dictionary, vm, origTag);
+    return;
+}
+
+
+/**************************************************************************
+                        c a s e C o I m
+** IMMEDIATE FICL_VM_STATE_COMPILE-ONLY
+**
+**
+** At FICL_VM_STATE_COMPILE-time, a CASE-SYS (see DPANS94 6.2.0873) looks like this:
+**			i*addr i caseTag
+** and an OF-SYS (see DPANS94 6.2.1950) looks like this:
+**			i*addr i caseTag addr ofTag
+** The integer under caseTag is the count of fixup addresses that branch
+** to ENDCASE.
+**************************************************************************/
+
+static void ficlPrimitiveCaseCoIm(ficlVm *vm)
+{
+    FICL_STACK_CHECK(vm->dataStack, 0, 2);
+
+	ficlStackPushUnsigned(vm->dataStack, 0);
+	markControlTag(vm, caseTag);
+    return;
+}
+
+
+/**************************************************************************
+                        e n d c a s eC o I m
+** IMMEDIATE FICL_VM_STATE_COMPILE-ONLY
+**************************************************************************/
+
+static void ficlPrimitiveEndcaseCoIm(ficlVm *vm)
+{
+	ficlUnsigned fixupCount;
+    ficlDictionary *dictionary;
+    ficlCell *patchAddr;
+    ficlInteger offset;
+
+	/*
+	** if the last OF ended with FALLTHROUGH,
+	** just add the FALLTHROUGH fixup to the
+	** ENDOF fixups
+	*/
+	if (ficlStackGetTop(vm->dataStack).p == fallthroughTag)
+	{
+		matchControlTag(vm, fallthroughTag);
+		patchAddr = ficlStackPopPointer(vm->dataStack);
+	    matchControlTag(vm, caseTag);
+		fixupCount = ficlStackPopUnsigned(vm->dataStack);
+		ficlStackPushPointer(vm->dataStack, patchAddr);
+		ficlStackPushUnsigned(vm->dataStack, fixupCount + 1);
+		markControlTag(vm, caseTag);
+	}
+
+    matchControlTag(vm, caseTag);
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+	fixupCount = ficlStackPopUnsigned(vm->dataStack);
+    FICL_STACK_CHECK(vm->dataStack, fixupCount, 0);
+
+    dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionDrop);
+
+	while (fixupCount--)
+	{
+		patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack);
+		offset = dictionary->here - patchAddr;
+		*patchAddr = FICL_LVALUE_TO_CELL(offset);
+	}
+    return;
+}
+
+
+/**************************************************************************
+                        o f C o I m
+** IMMEDIATE FICL_VM_STATE_COMPILE-ONLY
+**************************************************************************/
+
+static void ficlPrimitiveOfCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+	ficlCell *fallthroughFixup = NULL;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 3);
+
+	if (ficlStackGetTop(vm->dataStack).p == fallthroughTag)
+	{
+		matchControlTag(vm, fallthroughTag);
+		fallthroughFixup = ficlStackPopPointer(vm->dataStack);
+	}
+
+	matchControlTag(vm, caseTag);
+
+	markControlTag(vm, caseTag);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionOfParen);
+    markBranch(dictionary, vm, ofTag);
+    ficlDictionaryAppendUnsigned(dictionary, 2);
+
+	if (fallthroughFixup != NULL)
+	{
+		ficlInteger offset = dictionary->here - fallthroughFixup;
+		*fallthroughFixup = FICL_LVALUE_TO_CELL(offset);
+	}
+
+    return;
+}
+
+
+/**************************************************************************
+                    e n d o f C o I m
+** IMMEDIATE FICL_VM_STATE_COMPILE-ONLY
+**************************************************************************/
+
+static void ficlPrimitiveEndofCoIm(ficlVm *vm)
+{
+    ficlCell *patchAddr;
+    ficlUnsigned fixupCount;
+    ficlInteger offset;
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    FICL_STACK_CHECK(vm->dataStack, 4, 3);
+
+	/* ensure we're in an OF, */
+    matchControlTag(vm, ofTag);
+	/* grab the address of the branch location after the OF */
+    patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack);
+	/* ensure we're also in a "case" */
+    matchControlTag(vm, caseTag);
+	/* grab the current number of ENDOF fixups */
+	fixupCount = ficlStackPopUnsigned(vm->dataStack);
+
+    /* FICL_VM_STATE_COMPILE branch runtime */
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranchParenWithCheck);
+
+	/* push a new ENDOF fixup, the updated count of ENDOF fixups, and the caseTag */
+    ficlStackPushPointer(vm->dataStack, dictionary->here);
+    ficlStackPushUnsigned(vm->dataStack, fixupCount + 1);
+	markControlTag(vm, caseTag);
+
+	/* reserve space for the ENDOF fixup */
+    ficlDictionaryAppendUnsigned(dictionary, 2);
+
+	/* and patch the original OF */
+    offset = dictionary->here - patchAddr;
+    *patchAddr = FICL_LVALUE_TO_CELL(offset);
+}
+
+/**************************************************************************
+                    f a l l t h r o u g h C o I m
+** IMMEDIATE FICL_VM_STATE_COMPILE-ONLY
+**************************************************************************/
+
+static void ficlPrimitiveFallthroughCoIm(ficlVm *vm)
+{
+    ficlCell *patchAddr;
+    ficlInteger offset;
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    FICL_STACK_CHECK(vm->dataStack, 4, 3);
+
+	/* ensure we're in an OF, */
+    matchControlTag(vm, ofTag);
+	/* grab the address of the branch location after the OF */
+    patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack);
+	/* ensure we're also in a "case" */
+    matchControlTag(vm, caseTag);
+
+	/* okay, here we go.  put the case tag back. */
+	markControlTag(vm, caseTag);
+
+    /* FICL_VM_STATE_COMPILE branch runtime */
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranchParenWithCheck);
+
+	/* push a new FALLTHROUGH fixup and the fallthroughTag */
+    ficlStackPushPointer(vm->dataStack, dictionary->here);
+	markControlTag(vm, fallthroughTag);
+
+	/* reserve space for the FALLTHROUGH fixup */
+    ficlDictionaryAppendUnsigned(dictionary, 2);
+
+	/* and patch the original OF */
+    offset = dictionary->here - patchAddr;
+    *patchAddr = FICL_LVALUE_TO_CELL(offset);
+}
+
+/**************************************************************************
+                        h a s h
+** hash ( c-addr u -- code)
+** calculates hashcode of specified string and leaves it on the stack
+**************************************************************************/
+
+static void ficlPrimitiveHash(ficlVm *vm)
+{
+    ficlString s;
+    FICL_STRING_SET_LENGTH(s, ficlStackPopUnsigned(vm->dataStack));
+    FICL_STRING_SET_POINTER(s, ficlStackPopPointer(vm->dataStack));
+    ficlStackPushUnsigned(vm->dataStack, ficlHashCode(s));
+    return;
+}
+
+
+/**************************************************************************
+                        i n t e r p r e t 
+** This is the "user interface" of a Forth. It does the following:
+**   while there are words in the VM's Text Input Buffer
+**     Copy next word into the pad (ficlVmGetWord)
+**     Attempt to find the word in the dictionary (ficlDictionaryLookup)
+**     If successful, execute the word.
+**     Otherwise, attempt to convert the word to a number (isNumber)
+**     If successful, push the number onto the parameter stack.
+**     Otherwise, print an error message and exit loop...
+**   End Loop
+**
+** From the standard, section 3.4
+** Text interpretation (see 6.1.1360 EVALUATE and 6.1.2050 QUIT) shall
+** repeat the following steps until either the parse area is empty or an 
+** ambiguous condition exists: 
+** a) Skip leading spaces and parse a name (see 3.4.1); 
+**************************************************************************/
+
+static void ficlPrimitiveInterpret(ficlVm *vm)
+{
+    ficlString s;
+    int i;
+    ficlSystem *system;
+
+    FICL_VM_ASSERT(vm, vm);
+
+    system = vm->callback.system;
+    s   = ficlVmGetWord0(vm);
+
+    /*
+    ** Get next word...if out of text, we're done.
+    */
+    if (s.length == 0)
+    {
+        ficlVmThrow(vm, FICL_VM_STATUS_OUT_OF_TEXT);
+    }
+
+    /*
+    ** Run the parse chain against the incoming token until somebody eats it.
+    ** Otherwise emit an error message and give up.
+    */
+    for (i=0; i < FICL_MAX_PARSE_STEPS; i++)
+    {
+        ficlWord *word = system->parseList[i];
+           
+        if (word == NULL)
+            break;
+
+        if (word->code == ficlPrimitiveParseStepParen)
+        {
+            ficlParseStep pStep;
+            pStep = (ficlParseStep)(word->param->fn);
+            if ((*pStep)(vm, s))
+                return;
+        }
+        else
+        {
+            ficlStackPushPointer(vm->dataStack, FICL_STRING_GET_POINTER(s));
+            ficlStackPushUnsigned(vm->dataStack, FICL_STRING_GET_LENGTH(s));
+            ficlVmExecuteXT(vm, word);
+            if (ficlStackPopInteger(vm->dataStack))
+                return;
+        }
+    }
+
+    ficlVmThrowError(vm, "%.*s not found", FICL_STRING_GET_LENGTH(s), FICL_STRING_GET_POINTER(s));
+
+    return;                 /* back to inner interpreter */
+}
+
+
+/*
+** Surrogate precompiled parse step for ficlParseWord (this step is hard coded in 
+** FICL_VM_STATE_INTERPRET)
+*/
+static void ficlPrimitiveLookup(ficlVm *vm)
+{
+    ficlString name;
+    FICL_STRING_SET_LENGTH(name, ficlStackPopUnsigned(vm->dataStack));
+    FICL_STRING_SET_POINTER(name, ficlStackPopPointer(vm->dataStack));
+    ficlStackPushInteger(vm->dataStack, ficlVmParseWord(vm, name));
+    return;
+}
+
+
+/**************************************************************************
+                        p a r e n P a r s e S t e p
+** (parse-step)  ( c-addr u -- flag )
+** runtime for a precompiled parse step - pop a counted string off the
+** stack, run the parse step against it, and push the result flag (FICL_TRUE
+** if success, FICL_FALSE otherwise).
+**************************************************************************/
+
+void ficlPrimitiveParseStepParen(ficlVm *vm)
+{
+    ficlString s;
+    ficlWord *word = vm->runningWord;
+    ficlParseStep pStep = (ficlParseStep)(word->param->fn);
+
+    FICL_STRING_SET_LENGTH(s, ficlStackPopInteger(vm->dataStack));
+    FICL_STRING_SET_POINTER(s, ficlStackPopPointer(vm->dataStack));
+    
+    ficlStackPushInteger(vm->dataStack, (*pStep)(vm, s));
+
+    return;
+}
+
+
+static void ficlPrimitiveAddParseStep(ficlVm *vm)
+{
+    ficlWord *pStep;
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    pStep = (ficlWord *)(ficlStackPop(vm->dataStack).p);
+    if ((pStep != NULL) && ficlDictionaryIsAWord(dictionary, pStep))
+        ficlSystemAddParseStep(vm->callback.system, pStep);
+    return;
+}
+
+
+
+/**************************************************************************
+                        l i t e r a l I m
+** 
+** IMMEDIATE code for "literal". This function gets a value from the stack 
+** and compiles it into the dictionary preceded by the code for "(literal)".
+** IMMEDIATE
+**************************************************************************/
+
+void ficlPrimitiveLiteralIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+	int value;
+
+	value = ficlStackPopInteger(vm->dataStack);
+
+	switch (value)
+	{
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+		case 13:
+		case 14:
+		case 15:
+		case 16:
+			ficlDictionaryAppendUnsigned(dictionary, value);
+			break;
+
+		case 0:
+		case -1:
+		case -2:
+		case -3:
+		case -4:
+		case -5:
+		case -6:
+		case -7:
+		case -8:
+		case -9:
+		case -10:
+		case -11:
+		case -12:
+		case -13:
+		case -14:
+		case -15:
+		case -16:
+			ficlDictionaryAppendUnsigned(dictionary, ficlInstruction0- value);
+			break;
+
+		default:
+			ficlDictionaryAppendUnsigned(dictionary, ficlInstructionLiteralParen);
+			ficlDictionaryAppendUnsigned(dictionary, value);
+			break;
+	}
+
+    return;
+}
+
+
+static void ficlPrimitive2LiteralIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstruction2LiteralParen);
+    ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->dataStack));
+    ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->dataStack));
+
+    return;
+}
+
+/**************************************************************************
+                               D o  /  L o o p
+** do -- IMMEDIATE FICL_VM_STATE_COMPILE ONLY
+**    Compiles code to initialize a loop: FICL_VM_STATE_COMPILE (do), 
+**    allot space to hold the "leave" address, push a branch
+**    target address for the loop.
+** (do) -- runtime for "do"
+**    pops index and limit from the p stack and moves them
+**    to the r stack, then skips to the loop body.
+** loop -- IMMEDIATE FICL_VM_STATE_COMPILE ONLY
+** +loop
+**    Compiles code for the test part of a loop:
+**    FICL_VM_STATE_COMPILE (loop), resolve forward branch from "do", and
+**    copy "here" address to the "leave" address allotted by "do"
+** i,j,k -- FICL_VM_STATE_COMPILE ONLY
+**    Runtime: Push loop indices on param stack (i is innermost loop...)
+**    Note: each loop has three values on the return stack:
+**    ( R: leave limit index )
+**    "leave" is the absolute address of the next ficlCell after the loop
+**    limit and index are the loop control variables.
+** leave -- FICL_VM_STATE_COMPILE ONLY
+**    Runtime: pop the loop control variables, then pop the
+**    "leave" address and jump (absolute) there.
+**************************************************************************/
+
+static void ficlPrimitiveDoCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionDoParen);
+    /*
+    ** Allot space for a pointer to the end
+    ** of the loop - "leave" uses this...
+    */
+    markBranch(dictionary, vm, leaveTag);
+    ficlDictionaryAppendUnsigned(dictionary, 0);
+    /*
+    ** Mark location of head of loop...
+    */
+    markBranch(dictionary, vm, doTag);
+
+    return;
+}
+
+
+static void ficlPrimitiveQDoCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionQDoParen);
+    /*
+    ** Allot space for a pointer to the end
+    ** of the loop - "leave" uses this...
+    */
+    markBranch(dictionary, vm, leaveTag);
+    ficlDictionaryAppendUnsigned(dictionary, 0);
+    /*
+    ** Mark location of head of loop...
+    */
+    markBranch(dictionary, vm, doTag);
+
+    return;
+}
+
+
+static void ficlPrimitiveLoopCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionLoopParen);
+    resolveBackBranch(dictionary, vm, doTag);
+    resolveAbsBranch(dictionary, vm, leaveTag);
+    return;
+}
+
+
+static void ficlPrimitivePlusLoopCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionPlusLoopParen);
+    resolveBackBranch(dictionary, vm, doTag);
+    resolveAbsBranch(dictionary, vm, leaveTag);
+    return;
+}
+
+
+
+/**************************************************************************
+                        v a r i a b l e
+** 
+**************************************************************************/
+
+static void ficlPrimitiveVariable(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+
+    ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionVariableParen, FICL_WORD_DEFAULT);
+    ficlVmDictionaryAllotCells(vm, dictionary, 1);
+    return;
+}
+
+
+static void ficlPrimitive2Variable(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+
+    ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionVariableParen, FICL_WORD_DEFAULT);
+    ficlVmDictionaryAllotCells(vm, dictionary, 2);
+    return;
+}
+
+
+/**************************************************************************
+                        b a s e   &   f r i e n d s
+** 
+**************************************************************************/
+
+static void ficlPrimitiveBase(ficlVm *vm)
+{
+    ficlCell *pBase;
+
+    FICL_STACK_CHECK(vm->dataStack, 0, 1);
+
+    pBase = (ficlCell *)(&vm->base);
+    ficlStackPush(vm->dataStack, FICL_LVALUE_TO_CELL(pBase));
+    return;
+}
+
+
+static void ficlPrimitiveDecimal(ficlVm *vm)
+{
+    vm->base = 10;
+    return;
+}
+
+
+static void ficlPrimitiveHex(ficlVm *vm)
+{
+    vm->base = 16;
+    return;
+}
+
+
+/**************************************************************************
+                        a l l o t   &   f r i e n d s
+** 
+**************************************************************************/
+
+static void ficlPrimitiveAllot(ficlVm *vm)
+{
+    ficlDictionary *dictionary;
+    ficlInteger i;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    dictionary = ficlVmGetDictionary(vm);
+    i = ficlStackPopInteger(vm->dataStack);
+
+    FICL_VM_DICTIONARY_CHECK(vm, dictionary, i);
+
+    ficlVmDictionaryAllot(vm, dictionary, i);
+    return;
+}
+
+
+static void ficlPrimitiveHere(ficlVm *vm)
+{
+    ficlDictionary *dictionary;
+
+    FICL_STACK_CHECK(vm->dataStack, 0, 1);
+
+    dictionary = ficlVmGetDictionary(vm);
+    ficlStackPushPointer(vm->dataStack, dictionary->here);
+    return;
+}
+
+
+
+
+/**************************************************************************
+                        t i c k
+** tick         CORE ( "<spaces>name" -- xt )
+** Skip leading space delimiters. Parse name delimited by a space. Find
+** name and return xt, the execution token for name. An ambiguous condition
+** exists if name is not found. 
+**************************************************************************/
+void ficlPrimitiveTick(ficlVm *vm)
+{
+    ficlWord *word = NULL;
+    ficlString name = ficlVmGetWord(vm);
+
+    FICL_STACK_CHECK(vm->dataStack, 0, 1);
+
+    word = ficlDictionaryLookup(ficlVmGetDictionary(vm), name);
+    if (!word)
+        ficlVmThrowError(vm, "%.*s not found", FICL_STRING_GET_LENGTH(name), FICL_STRING_GET_POINTER(name));
+    ficlStackPushPointer(vm->dataStack, word);
+    return;
+}
+
+
+static void ficlPrimitiveBracketTickCoIm(ficlVm *vm)
+{
+    ficlPrimitiveTick(vm);
+    ficlPrimitiveLiteralIm(vm);
+    
+    return;
+}
+
+
+/**************************************************************************
+                        p o s t p o n e
+** Lookup the next word in the input stream and FICL_VM_STATE_COMPILE code to 
+** insert it into definitions created by the resulting word
+** (defers compilation, even of immediate words)
+**************************************************************************/
+
+static void ficlPrimitivePostponeCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary  = ficlVmGetDictionary(vm);
+    ficlWord *word;
+    ficlWord *pComma = ficlSystemLookup(vm->callback.system, ",");
+    FICL_VM_ASSERT(vm, pComma);
+
+    ficlPrimitiveTick(vm);
+    word = ficlStackGetTop(vm->dataStack).p;
+    if (ficlWordIsImmediate(word))
+    {
+        ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->dataStack));
+    }
+    else
+    {
+        ficlPrimitiveLiteralIm(vm);
+        ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(pComma));
+    }
+    
+    return;
+}
+
+
+
+/**************************************************************************
+                        e x e c u t e
+** Pop an execution token (pointer to a word) off the stack and
+** run it
+**************************************************************************/
+
+static void ficlPrimitiveExecute(ficlVm *vm)
+{
+    ficlWord *word;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    word = ficlStackPopPointer(vm->dataStack);
+    ficlVmExecuteWord(vm, word);
+
+    return;
+}
+
+
+/**************************************************************************
+                        i m m e d i a t e
+** Make the most recently compiled word IMMEDIATE -- it executes even
+** in FICL_VM_STATE_COMPILE state (most often used for control compiling words
+** such as IF, THEN, etc)
+**************************************************************************/
+
+static void ficlPrimitiveImmediate(ficlVm *vm)
+{
+    FICL_IGNORE(vm);
+    ficlDictionarySetImmediate(ficlVmGetDictionary(vm));
+    return;
+}
+
+
+static void ficlPrimitiveCompileOnly(ficlVm *vm)
+{
+    FICL_IGNORE(vm);
+    ficlDictionarySetFlags(ficlVmGetDictionary(vm), FICL_WORD_COMPILE_ONLY);
+    return;
+}
+
+
+static void ficlPrimitiveSetObjectFlag(ficlVm *vm)
+{
+    FICL_IGNORE(vm);
+    ficlDictionarySetFlags(ficlVmGetDictionary(vm), FICL_WORD_OBJECT);
+    return;
+}
+
+static void ficlPrimitiveIsObject(ficlVm *vm)
+{
+    int flag;
+    ficlWord *word = (ficlWord *)ficlStackPopPointer(vm->dataStack);
+    
+    flag = ((word != NULL) && (word->flags & FICL_WORD_OBJECT)) ? FICL_TRUE : FICL_FALSE;
+    ficlStackPushInteger(vm->dataStack, flag);
+    return;
+}
+
+
+
+static void ficlPrimitiveCountedStringQuoteIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    if (vm->state == FICL_VM_STATE_INTERPRET)
+    {
+        ficlCountedString *counted = (ficlCountedString *) dictionary->here;
+        ficlVmGetString(vm, counted, '\"');
+        ficlStackPushPointer(vm->dataStack, counted);
+		/* move HERE past string so it doesn't get overwritten.  --lch */
+		ficlVmDictionaryAllot(vm, dictionary, counted->length + sizeof(ficlUnsigned8));
+    }
+    else    /* FICL_VM_STATE_COMPILE state */
+    {
+        ficlDictionaryAppendUnsigned(dictionary, ficlInstructionCStringLiteralParen);
+        dictionary->here = FICL_POINTER_TO_CELL(ficlVmGetString(vm, (ficlCountedString *)dictionary->here, '\"'));
+        ficlDictionaryAlign(dictionary);
+    }
+
+    return;
+}
+
+/**************************************************************************
+                        d o t Q u o t e
+** IMMEDIATE word that compiles a string literal for later display
+** FICL_VM_STATE_COMPILE fiStringLiteralParen, then copy the bytes of the string from the
+** TIB to the dictionary. Backpatch the count byte and align the dictionary.
+**************************************************************************/
+
+static void ficlPrimitiveDotQuoteCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlWord *pType = ficlSystemLookup(vm->callback.system, "type");
+    FICL_VM_ASSERT(vm, pType);
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionStringLiteralParen);
+    dictionary->here = FICL_POINTER_TO_CELL(ficlVmGetString(vm, (ficlCountedString *)dictionary->here, '\"'));
+    ficlDictionaryAlign(dictionary);
+    ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(pType));
+    return;
+}
+
+
+static void ficlPrimitiveDotParen(ficlVm *vm)
+{
+    char *from      = ficlVmGetInBuf(vm);
+    char *stop      = ficlVmGetInBufEnd(vm);
+    char *to     = vm->pad;
+    char c;
+
+    /*
+    ** Note: the standard does not want leading spaces skipped.
+    */
+    for (c = *from; (from != stop) && (c != ')'); c = *++from)
+        *to++ = c;
+
+    *to = '\0';
+    if ((from != stop) && (c == ')'))
+        from++;
+
+    ficlVmTextOut(vm, vm->pad);
+    ficlVmUpdateTib(vm, from);
+        
+    return;
+}
+
+
+/**************************************************************************
+                        s l i t e r a l
+** STRING 
+** Interpretation: Interpretation semantics for this word are undefined.
+** Compilation: ( c-addr1 u -- )
+** Append the run-time semantics given below to the current definition.
+** Run-time:       ( -- c-addr2 u )
+** Return c-addr2 u describing a string consisting of the characters
+** specified by c-addr1 u during compilation. A program shall not alter
+** the returned string. 
+**************************************************************************/
+static void ficlPrimitiveSLiteralCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary;
+    char *from;
+	char *to;
+    ficlUnsigned length;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 0);
+
+    dictionary = ficlVmGetDictionary(vm);
+    length  = ficlStackPopUnsigned(vm->dataStack);
+    from = ficlStackPopPointer(vm->dataStack);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionStringLiteralParen);
+    to    = (char *) dictionary->here;
+    *to++ = (char)   length;
+
+    for (; length > 0; --length)
+    {
+        *to++ = *from++;
+    }
+
+    *to++ = 0;
+    dictionary->here = FICL_POINTER_TO_CELL(ficlAlignPointer(to));
+    return;
+}
+
+
+/**************************************************************************
+                        s t a t e
+** Return the address of the VM's state member (must be sized the
+** same as a ficlCell for this reason)
+**************************************************************************/
+static void ficlPrimitiveState(ficlVm *vm)
+{
+    FICL_STACK_CHECK(vm->dataStack, 0, 1);
+    ficlStackPushPointer(vm->dataStack, &vm->state);
+    return;
+}
+
+
+/**************************************************************************
+                        c r e a t e . . . d o e s >
+** Make a new word in the dictionary with the run-time effect of 
+** a variable (push my address), but with extra space allotted
+** for use by does> .
+**************************************************************************/
+
+
+static void ficlPrimitiveCreate(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+
+    ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionCreateParen, FICL_WORD_DEFAULT);
+    ficlVmDictionaryAllotCells(vm, dictionary, 1);
+    return;
+}
+
+
+static void ficlPrimitiveDoesCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+#if FICL_WANT_LOCALS
+    if (vm->callback.system->localsCount > 0)
+    {
+        ficlDictionary *locals = ficlSystemGetLocals(vm->callback.system);
+        ficlDictionaryEmpty(locals, locals->forthWordlist->size);
+        ficlDictionaryAppendUnsigned(dictionary, ficlInstructionUnlinkParen);
+    }
+
+    vm->callback.system->localsCount = 0;
+#endif
+    FICL_IGNORE(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionDoesParen);
+    return;
+}
+
+
+/**************************************************************************
+                        t o   b o d y
+** to-body      CORE ( xt -- a-addr )
+** a-addr is the data-field address corresponding to xt. An ambiguous
+** condition exists if xt is not for a word defined via CREATE. 
+**************************************************************************/
+static void ficlPrimitiveToBody(ficlVm *vm)
+{
+    ficlWord *word;
+    FICL_STACK_CHECK(vm->dataStack, 1, 1);
+
+    word = ficlStackPopPointer(vm->dataStack);
+    ficlStackPushPointer(vm->dataStack, word->param + 1);
+    return;
+}
+
+
+/*
+** from-body       Ficl ( a-addr -- xt )
+** Reverse effect of >body
+*/
+static void ficlPrimitiveFromBody(ficlVm *vm)
+{
+    char *ptr;
+    FICL_STACK_CHECK(vm->dataStack, 1, 1);
+
+    ptr = (char *)ficlStackPopPointer(vm->dataStack) - sizeof (ficlWord);
+    ficlStackPushPointer(vm->dataStack, ptr);
+    return;
+}
+
+
+/*
+** >name        Ficl ( xt -- c-addr u )
+** Push the address and length of a word's name given its address
+** xt. 
+*/
+static void ficlPrimitiveToName(ficlVm *vm)
+{
+    ficlWord *word;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 2);
+
+    word = ficlStackPopPointer(vm->dataStack);
+    ficlStackPushPointer(vm->dataStack, word->name);
+    ficlStackPushUnsigned(vm->dataStack, word->length);
+    return;
+}
+
+
+static void ficlPrimitiveLastWord(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlWord *wp = dictionary->smudge;
+    FICL_VM_ASSERT(vm, wp);
+    ficlVmPush(vm, FICL_LVALUE_TO_CELL(wp));
+    return;
+}
+
+
+/**************************************************************************
+                        l b r a c k e t   e t c
+** 
+**************************************************************************/
+
+static void ficlPrimitiveLeftBracketCoIm(ficlVm *vm)
+{
+    vm->state = FICL_VM_STATE_INTERPRET;
+    return;
+}
+
+
+static void ficlPrimitiveRightBracket(ficlVm *vm)
+{
+    vm->state = FICL_VM_STATE_COMPILE;
+    return;
+}
+
+
+/**************************************************************************
+                        p i c t u r e d   n u m e r i c   w o r d s
+**
+** less-number-sign CORE ( -- )
+** Initialize the pictured numeric output conversion process. 
+** (clear the pad)
+**************************************************************************/
+static void ficlPrimitiveLessNumberSign(ficlVm *vm)
+{
+    ficlCountedString *counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad);
+    counted->length = 0;
+    return;
+}
+
+/*
+** number-sign      CORE ( ud1 -- ud2 )
+** Divide ud1 by the number in BASE giving the quotient ud2 and the remainder
+** n. (n is the least-significant digit of ud1.) Convert n to external form
+** and add the resulting character to the beginning of the pictured numeric
+** output  string. An ambiguous condition exists if # executes outside of a
+** <# #> delimited number conversion. 
+*/
+static void ficlPrimitiveNumberSign(ficlVm *vm)
+{
+    ficlCountedString *counted;
+    ficl2Unsigned u;
+    ficl2UnsignedQR uqr;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 2);
+
+    counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad);
+    u = ficlStackPop2Unsigned(vm->dataStack);
+    uqr = ficl2UnsignedDivide(u, (ficlUnsigned16)(vm->base));
+    counted->text[counted->length++] = ficlDigitToCharacter(uqr.remainder);
+    ficlStackPush2Unsigned(vm->dataStack, uqr.quotient);
+    return;
+}
+
+/*
+** number-sign-greater CORE ( xd -- c-addr u )
+** Drop xd. Make the pictured numeric output string available as a character
+** string. c-addr and u specify the resulting character string. A program
+** may replace characters within the string. 
+*/
+static void ficlPrimitiveNumberSignGreater(ficlVm *vm)
+{
+    ficlCountedString *counted;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 2);
+
+    counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad);
+    counted->text[counted->length] = 0;
+    ficlStringReverse(counted->text);
+    ficlStackDrop(vm->dataStack, 2);
+    ficlStackPushPointer(vm->dataStack, counted->text);
+    ficlStackPushUnsigned(vm->dataStack, counted->length);
+    return;
+}
+
+/*
+** number-sign-s    CORE ( ud1 -- ud2 )
+** Convert one digit of ud1 according to the rule for #. Continue conversion
+** until the quotient is zero. ud2 is zero. An ambiguous condition exists if
+** #S executes outside of a <# #> delimited number conversion. 
+** TO DO: presently does not use ud1 hi ficlCell - use it!
+*/
+static void ficlPrimitiveNumberSignS(ficlVm *vm)
+{
+    ficlCountedString *counted;
+    ficl2Unsigned u;
+    ficl2UnsignedQR uqr;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 2);
+
+    counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad);
+    u = ficlStackPop2Unsigned(vm->dataStack);
+
+    do 
+    {
+        uqr = ficl2UnsignedDivide(u, (ficlUnsigned16)(vm->base));
+        counted->text[counted->length++] = ficlDigitToCharacter(uqr.remainder);
+		u = uqr.quotient;
+    }
+    while (FICL_2UNSIGNED_NOT_ZERO(u));
+
+    ficlStackPush2Unsigned(vm->dataStack, u);
+    return;
+}
+
+/*
+** HOLD             CORE ( char -- )
+** Add char to the beginning of the pictured numeric output string. An ambiguous
+** condition exists if HOLD executes outside of a <# #> delimited number conversion.
+*/
+static void ficlPrimitiveHold(ficlVm *vm)
+{
+    ficlCountedString *counted;
+    int i;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad);
+    i = ficlStackPopInteger(vm->dataStack);
+    counted->text[counted->length++] = (char) i;
+    return;
+}
+
+/*
+** SIGN             CORE ( n -- )
+** If n is negative, add a minus sign to the beginning of the pictured
+** numeric output string. An ambiguous condition exists if SIGN
+** executes outside of a <# #> delimited number conversion. 
+*/
+static void ficlPrimitiveSign(ficlVm *vm)
+{
+    ficlCountedString *counted;
+    int i;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad);
+    i = ficlStackPopInteger(vm->dataStack);
+    if (i < 0)
+        counted->text[counted->length++] = '-';
+    return;
+}
+
+
+/**************************************************************************
+                        t o   N u m b e r
+** to-number CORE ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )
+** ud2 is the unsigned result of converting the characters within the
+** string specified by c-addr1 u1 into digits, using the number in BASE,
+** and adding each into ud1 after multiplying ud1 by the number in BASE.
+** Conversion continues left-to-right until a character that is not
+** convertible, including any + or -, is encountered or the string is
+** entirely converted. c-addr2 is the location of the first unconverted
+** character or the first character past the end of the string if the string
+** was entirely converted. u2 is the number of unconverted characters in the
+** string. An ambiguous condition exists if ud2 overflows during the
+** conversion. 
+**************************************************************************/
+static void ficlPrimitiveToNumber(ficlVm *vm)
+{
+    ficlUnsigned length;
+    char *trace;
+    ficl2Unsigned accumulator;
+    ficlUnsigned base = vm->base;
+    ficlUnsigned c;
+    ficlUnsigned digit;
+
+    FICL_STACK_CHECK(vm->dataStack,4,4);
+
+    length = ficlStackPopUnsigned(vm->dataStack);
+    trace = (char *)ficlStackPopPointer(vm->dataStack);
+    accumulator = ficlStackPop2Unsigned(vm->dataStack);
+
+    for (c = *trace; length > 0; c = *++trace, length--)
+    {
+        if (c < '0')
+            break;
+
+        digit = c - '0';
+
+        if (digit > 9)
+            digit = tolower(c) - 'a' + 10;
+        /* 
+        ** Note: following test also catches chars between 9 and a
+        ** because 'digit' is unsigned! 
+        */
+        if (digit >= base)
+            break;
+
+        accumulator = ficl2UnsignedMultiplyAccumulate(accumulator, base, digit);
+    }
+
+    ficlStackPush2Unsigned(vm->dataStack, accumulator);
+    ficlStackPushPointer(vm->dataStack, trace);
+    ficlStackPushUnsigned(vm->dataStack, length);
+
+    return;
+}
+
+
+
+/**************************************************************************
+                        q u i t   &   a b o r t
+** quit CORE   ( -- )  ( R:  i*x -- )
+** Empty the return stack, store zero in SOURCE-ID if it is present, make
+** the user input device the input source, and enter interpretation state. 
+** Do not display a message. Repeat the following: 
+**
+**   Accept a line from the input source into the input buffer, set >IN to
+**   zero, and FICL_VM_STATE_INTERPRET. 
+**   Display the implementation-defined system prompt if in
+**   interpretation state, all processing has been completed, and no
+**   ambiguous condition exists. 
+**************************************************************************/
+
+static void ficlPrimitiveQuit(ficlVm *vm)
+{
+    ficlVmThrow(vm, FICL_VM_STATUS_QUIT);
+    return;
+}
+
+
+static void ficlPrimitiveAbort(ficlVm *vm)
+{
+    ficlVmThrow(vm, FICL_VM_STATUS_ABORT);
+    return;
+}
+
+
+/**************************************************************************
+                        a c c e p t
+** accept       CORE ( c-addr +n1 -- +n2 )
+** Receive a string of at most +n1 characters. An ambiguous condition
+** exists if +n1 is zero or greater than 32,767. Display graphic characters
+** as they are received. A program that depends on the presence or absence
+** of non-graphic characters in the string has an environmental dependency.
+** The editing functions, if any, that the system performs in order to
+** construct the string are implementation-defined. 
+**
+** (Although the standard text doesn't say so, I assume that the intent 
+** of 'accept' is to store the string at the address specified on
+** the stack.)
+** Implementation: if there's more text in the TIB, use it. Otherwise
+** throw out for more text. Copy characters up to the max count into the
+** address given, and return the number of actual characters copied.
+** 
+** Note (sobral) this may not be the behavior you'd expect if you're
+** trying to get user input at load time!
+**************************************************************************/
+static void ficlPrimitiveAccept(ficlVm *vm)
+{
+    ficlUnsigned size;
+    char *address;
+
+	ficlUnsigned length;
+	char *trace;
+	char *end;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 1);
+
+    trace = ficlVmGetInBuf(vm);
+    end = ficlVmGetInBufEnd(vm);
+    length = end - trace;
+    if (length == 0)
+        ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
+
+    /*
+    ** Now we have something in the text buffer - use it 
+    */
+    size = ficlStackPopInteger(vm->dataStack);
+    address = ficlStackPopPointer(vm->dataStack);
+
+    length = (size < length) ? size : length;
+    strncpy(address, trace, length);
+    trace += length;
+    ficlVmUpdateTib(vm, trace);
+    ficlStackPushInteger(vm->dataStack, length);
+
+    return;
+}
+
+
+/**************************************************************************
+                        a l i g n
+** 6.1.0705 ALIGN       CORE ( -- )
+** If the data-space pointer is not aligned, reserve enough space to
+** align it. 
+**************************************************************************/
+static void ficlPrimitiveAlign(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    FICL_IGNORE(vm);
+    ficlDictionaryAlign(dictionary);
+    return;
+}
+
+
+/**************************************************************************
+                        a l i g n e d
+** 
+**************************************************************************/
+static void ficlPrimitiveAligned(ficlVm *vm)
+{
+    void *addr;
+
+    FICL_STACK_CHECK(vm->dataStack,1,1);
+
+    addr = ficlStackPopPointer(vm->dataStack);
+    ficlStackPushPointer(vm->dataStack, ficlAlignPointer(addr));
+    return;
+}
+
+
+/**************************************************************************
+                        b e g i n   &   f r i e n d s
+** Indefinite loop control structures
+** A.6.1.0760 BEGIN 
+** Typical use: 
+**      : X ... BEGIN ... test UNTIL ;
+** or 
+**      : X ... BEGIN ... test WHILE ... REPEAT ;
+**************************************************************************/
+static void ficlPrimitiveBeginCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    markBranch(dictionary, vm, destTag);
+    return;
+}
+
+static void ficlPrimitiveUntilCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranch0ParenWithCheck);
+    resolveBackBranch(dictionary, vm, destTag);
+    return;
+}
+
+static void ficlPrimitiveWhileCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 5);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranch0ParenWithCheck);
+    markBranch(dictionary, vm, origTag);
+
+	/* equivalent to 2swap */
+    ficlStackRoll(vm->dataStack, 3);
+    ficlStackRoll(vm->dataStack, 3);
+
+    ficlDictionaryAppendUnsigned(dictionary, 1);
+    return;
+}
+
+static void ficlPrimitiveRepeatCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranchParenWithCheck);
+    /* expect "begin" branch marker */
+    resolveBackBranch(dictionary, vm, destTag);
+    /* expect "while" branch marker */
+    resolveForwardBranch(dictionary, vm, origTag);
+    return;
+}
+
+
+static void ficlPrimitiveAgainCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionBranchParenWithCheck);
+    /* expect "begin" branch marker */
+    resolveBackBranch(dictionary, vm, destTag);
+    return;
+}
+
+
+/**************************************************************************
+                        c h a r   &   f r i e n d s
+** 6.1.0895 CHAR    CORE ( "<spaces>name" -- char )
+** Skip leading space delimiters. Parse name delimited by a space.
+** Put the value of its first character onto the stack. 
+**
+** bracket-char     CORE 
+** Interpretation: Interpretation semantics for this word are undefined.
+** Compilation: ( "<spaces>name" -- )
+** Skip leading space delimiters. Parse name delimited by a space.
+** Append the run-time semantics given below to the current definition. 
+** Run-time: ( -- char )
+** Place char, the value of the first character of name, on the stack. 
+**************************************************************************/
+static void ficlPrimitiveChar(ficlVm *vm)
+{
+    ficlString s;
+
+    FICL_STACK_CHECK(vm->dataStack, 0, 1);
+
+    s = ficlVmGetWord(vm);
+    ficlStackPushUnsigned(vm->dataStack, (ficlUnsigned)(s.text[0]));
+    return;
+}
+
+static void ficlPrimitiveCharCoIm(ficlVm *vm)
+{
+    ficlPrimitiveChar(vm);
+    ficlPrimitiveLiteralIm(vm);
+    return;
+}
+
+/**************************************************************************
+                        c h a r P l u s
+** char-plus        CORE ( c-addr1 -- c-addr2 )
+** Add the size in address units of a character to c-addr1, giving c-addr2. 
+**************************************************************************/
+static void ficlPrimitiveCharPlus(ficlVm *vm)
+{
+    char *p;
+
+    FICL_STACK_CHECK(vm->dataStack,1,1);
+
+
+    p = ficlStackPopPointer(vm->dataStack);
+    ficlStackPushPointer(vm->dataStack, p + 1);
+    return;
+}
+
+/**************************************************************************
+                        c h a r s
+** chars        CORE ( n1 -- n2 )
+** n2 is the size in address units of n1 characters. 
+** For most processors, this function can be a no-op. To guarantee
+** portability, we'll multiply by sizeof (char).
+**************************************************************************/
+#if defined (_M_IX86)
+#pragma warning(disable: 4127)
+#endif
+static void ficlPrimitiveChars(ficlVm *vm)
+{
+    if (sizeof (char) > 1)
+    {
+        ficlInteger i;
+
+        FICL_STACK_CHECK(vm->dataStack,1,1);
+
+        i = ficlStackPopInteger(vm->dataStack);
+        ficlStackPushInteger(vm->dataStack, i * sizeof (char));
+    }
+    /* otherwise no-op! */
+    return;
+}
+#if defined (_M_IX86)
+#pragma warning(default: 4127)
+#endif
+ 
+
+/**************************************************************************
+                        c o u n t
+** COUNT    CORE ( c-addr1 -- c-addr2 u )
+** Return the character string specification for the counted string stored
+** at c-addr1. c-addr2 is the address of the first character after c-addr1.
+** u is the contents of the character at c-addr1, which is the length in
+** characters of the string at c-addr2. 
+**************************************************************************/
+static void ficlPrimitiveCount(ficlVm *vm)
+{
+    ficlCountedString *counted;
+
+    FICL_STACK_CHECK(vm->dataStack,1,2);
+
+
+    counted = ficlStackPopPointer(vm->dataStack);
+    ficlStackPushPointer(vm->dataStack, counted->text);
+    ficlStackPushUnsigned(vm->dataStack, counted->length);
+    return;
+}
+
+/**************************************************************************
+                        e n v i r o n m e n t ?
+** environment-query CORE ( c-addr u -- FICL_FALSE | i*x FICL_TRUE )
+** c-addr is the address of a character string and u is the string's
+** character count. u may have a value in the range from zero to an
+** implementation-defined maximum which shall not be less than 31. The
+** character string should contain a keyword from 3.2.6 Environmental
+** queries or the optional word sets to be checked for correspondence
+** with an attribute of the present environment. If the system treats the
+** attribute as unknown, the returned flag is FICL_FALSE; otherwise, the flag
+** is FICL_TRUE and the i*x returned is of the type specified in the table for
+** the attribute queried. 
+**************************************************************************/
+static void ficlPrimitiveEnvironmentQ(ficlVm *vm)
+{
+    ficlDictionary *environment;
+    ficlWord *word;
+    ficlString name;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 1);
+
+
+    environment = vm->callback.system->environment;
+    name.length = ficlStackPopUnsigned(vm->dataStack);
+    name.text    = ficlStackPopPointer(vm->dataStack);
+
+    word = ficlDictionaryLookup(environment, name);
+
+    if (word != NULL)
+    {
+        ficlVmExecuteWord(vm, word);
+        ficlStackPushInteger(vm->dataStack, FICL_TRUE);
+    }
+    else
+    {
+        ficlStackPushInteger(vm->dataStack, FICL_FALSE);
+    }
+    return;
+}
+
+/**************************************************************************
+                        e v a l u a t e
+** EVALUATE CORE ( i*x c-addr u -- j*x )
+** Save the current input source specification. Store minus-one (-1) in
+** SOURCE-ID if it is present. Make the string described by c-addr and u
+** both the input source and input buffer, set >IN to zero, and FICL_VM_STATE_INTERPRET.
+** When the parse area is empty, restore the prior input source
+** specification. Other stack effects are due to the words EVALUATEd. 
+**
+**************************************************************************/
+static void ficlPrimitiveEvaluate(ficlVm *vm)
+{
+    ficlCell id;
+    int result;
+	ficlString string;
+
+    FICL_STACK_CHECK(vm->dataStack,2,0);
+
+
+    FICL_STRING_SET_LENGTH(string, ficlStackPopUnsigned(vm->dataStack));
+    FICL_STRING_SET_POINTER(string, ficlStackPopPointer(vm->dataStack));
+
+    id = vm->sourceId;
+    vm->sourceId.i = -1;
+    result = ficlVmExecuteString(vm, string);
+    vm->sourceId = id;
+    if (result != FICL_VM_STATUS_OUT_OF_TEXT)
+        ficlVmThrow(vm, result);
+
+    return;
+}
+
+
+/**************************************************************************
+                        s t r i n g   q u o t e
+** Interpreting: get string delimited by a quote from the input stream,
+** copy to a scratch area, and put its count and address on the stack.
+** Compiling: FICL_VM_STATE_COMPILE code to push the address and count of a string
+** literal, FICL_VM_STATE_COMPILE the string from the input stream, and align the dictionary
+** pointer.
+**************************************************************************/
+static void ficlPrimitiveStringQuoteIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    if (vm->state == FICL_VM_STATE_INTERPRET)
+    {
+        ficlCountedString *counted = (ficlCountedString *)dictionary->here;
+        ficlVmGetString(vm, counted, '\"');
+        ficlStackPushPointer(vm->dataStack, counted->text);
+        ficlStackPushUnsigned(vm->dataStack, counted->length);
+    }
+    else    /* FICL_VM_STATE_COMPILE state */
+    {
+	    ficlDictionaryAppendUnsigned(dictionary, ficlInstructionStringLiteralParen);
+        dictionary->here = FICL_POINTER_TO_CELL(ficlVmGetString(vm, (ficlCountedString *)dictionary->here, '\"'));
+        ficlDictionaryAlign(dictionary);
+    }
+
+    return;
+}
+
+
+/**************************************************************************
+                        t y p e
+** Pop count and char address from stack and print the designated string.
+**************************************************************************/
+static void ficlPrimitiveType(ficlVm *vm)
+{
+    ficlUnsigned length;
+    char *s;
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 0);
+
+
+    length = ficlStackPopUnsigned(vm->dataStack);
+    s = ficlStackPopPointer(vm->dataStack);
+	
+	if ((s == NULL) || (length == 0))
+		return;
+
+    /* 
+    ** Since we don't have an output primitive for a counted string
+    ** (oops), make sure the string is null terminated. If not, copy
+    ** and terminate it.
+    */
+    if (s[length] != 0)
+    {
+        char *here = (char *)ficlVmGetDictionary(vm)->here;
+        if (s != here)
+            strncpy(here, s, length);
+
+        here[length] = '\0';
+        s = here;
+    }
+
+    ficlVmTextOut(vm, s);
+    return;
+}
+
+/**************************************************************************
+                        w o r d
+** word CORE ( char "<chars>ccc<char>" -- c-addr )
+** Skip leading delimiters. Parse characters ccc delimited by char. An
+** ambiguous condition exists if the length of the parsed string is greater
+** than the implementation-defined length of a counted string. 
+** 
+** c-addr is the address of a transient region containing the parsed word
+** as a counted string. If the parse area was empty or contained no
+** characters other than the delimiter, the resulting string has a zero
+** length. A space, not included in the length, follows the string. A
+** program may replace characters within the string. 
+** NOTE! Ficl also NULL-terminates the dest string.
+**************************************************************************/
+static void ficlPrimitiveWord(ficlVm *vm)
+{
+    ficlCountedString *counted;
+    char delim;
+    ficlString name;
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 1);
+
+
+    counted = (ficlCountedString *)vm->pad;
+    delim = (char)ficlStackPopInteger(vm->dataStack);
+    name = ficlVmParseStringEx(vm, delim, 1);
+
+    if (FICL_STRING_GET_LENGTH(name) > FICL_PAD_SIZE - 1)
+        FICL_STRING_SET_LENGTH(name, FICL_PAD_SIZE - 1);
+
+    counted->length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(name);
+    strncpy(counted->text, FICL_STRING_GET_POINTER(name), FICL_STRING_GET_LENGTH(name));
+
+	/* store an extra space at the end of the primitive... why? dunno yet.  Guy Carver did it. */
+    counted->text[counted->length] = ' ';
+    counted->text[counted->length + 1] = 0;
+
+    ficlStackPushPointer(vm->dataStack, counted);
+    return;
+}
+
+
+/**************************************************************************
+                        p a r s e - w o r d
+** Ficl   PARSE-WORD  ( <spaces>name -- c-addr u )
+** 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.
+**************************************************************************/
+static void ficlPrimitiveParseNoCopy(ficlVm *vm)
+{
+    ficlString s;
+
+    FICL_STACK_CHECK(vm->dataStack, 0, 2);
+
+
+    s = ficlVmGetWord0(vm);
+    ficlStackPushPointer(vm->dataStack, FICL_STRING_GET_POINTER(s));
+    ficlStackPushUnsigned(vm->dataStack, FICL_STRING_GET_LENGTH(s));
+    return;
+}
+
+
+/**************************************************************************
+                        p a r s e
+** CORE EXT  ( char "ccc<char>" -- c-addr u )
+** Parse ccc delimited by the delimiter char. 
+** c-addr is the address (within the input buffer) and u is the length of 
+** the parsed string. If the parse area was empty, the resulting string has
+** a zero length. 
+** NOTE! PARSE differs from WORD: it does not skip leading delimiters.
+**************************************************************************/
+static void ficlPrimitiveParse(ficlVm *vm)
+{
+    ficlString s;
+    char delim;
+
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 2);
+
+
+    delim = (char)ficlStackPopInteger(vm->dataStack);
+
+    s = ficlVmParseStringEx(vm, delim, 0);
+    ficlStackPushPointer(vm->dataStack, FICL_STRING_GET_POINTER(s));
+    ficlStackPushUnsigned(vm->dataStack, FICL_STRING_GET_LENGTH(s));
+    return;
+}
+
+
+/**************************************************************************
+                        f i n d
+** FIND CORE ( c-addr -- c-addr 0  |  xt 1  |  xt -1 )
+** Find the definition named in the counted string at c-addr. If the
+** definition is not found, return c-addr and zero. If the definition is
+** found, return its execution token xt. If the definition is immediate,
+** also return one (1), otherwise also return minus-one (-1). For a given
+** string, the values returned by FIND while compiling may differ from
+** those returned while not compiling. 
+**************************************************************************/
+static void do_find(ficlVm *vm, ficlString name, void *returnForFailure)
+{
+    ficlWord *word;
+
+    word = ficlDictionaryLookup(ficlVmGetDictionary(vm), name);
+    if (word)
+    {
+        ficlStackPushPointer(vm->dataStack, word);
+        ficlStackPushInteger(vm->dataStack, (ficlWordIsImmediate(word) ? 1 : -1));
+    }
+    else
+    {
+        ficlStackPushPointer(vm->dataStack, returnForFailure);
+        ficlStackPushUnsigned(vm->dataStack, 0);
+    }
+    return;
+}
+
+
+
+/**************************************************************************
+                        f i n d
+** FIND CORE ( c-addr -- c-addr 0  |  xt 1  |  xt -1 )
+** Find the definition named in the counted string at c-addr. If the
+** definition is not found, return c-addr and zero. If the definition is
+** found, return its execution token xt. If the definition is immediate,
+** also return one (1), otherwise also return minus-one (-1). For a given
+** string, the values returned by FIND while compiling may differ from
+** those returned while not compiling. 
+**************************************************************************/
+static void ficlPrimitiveCFind(ficlVm *vm)
+{
+    ficlCountedString *counted;
+    ficlString name;
+
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 2);
+
+    counted = ficlStackPopPointer(vm->dataStack);
+    FICL_STRING_SET_FROM_COUNTED_STRING(name, *counted);
+    do_find(vm, name, counted);
+}
+
+
+
+/**************************************************************************
+                        s f i n d
+** Ficl   ( c-addr u -- 0 0  |  xt 1  |  xt -1 )
+** Like FIND, but takes "c-addr u" for the string.
+**************************************************************************/
+static void ficlPrimitiveSFind(ficlVm *vm)
+{
+    ficlString name;
+
+
+    FICL_STACK_CHECK(vm->dataStack, 2, 2);
+
+
+    name.length = ficlStackPopInteger(vm->dataStack);
+    name.text = ficlStackPopPointer(vm->dataStack);
+
+    do_find(vm, name, NULL);
+}
+
+
+
+/**************************************************************************
+                        r e c u r s e
+** 
+**************************************************************************/
+static void ficlPrimitiveRecurseCoIm(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+
+    FICL_IGNORE(vm);
+    ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(dictionary->smudge));
+    return;
+}
+
+
+/**************************************************************************
+                        s o u r c e
+** CORE ( -- c-addr u )
+** c-addr is the address of, and u is the number of characters in, the
+** input buffer. 
+**************************************************************************/
+static void ficlPrimitiveSource(ficlVm *vm)
+{
+
+    FICL_STACK_CHECK(vm->dataStack,0,2);
+
+    ficlStackPushPointer(vm->dataStack, vm->tib.text);
+    ficlStackPushInteger(vm->dataStack, ficlVmGetInBufLen(vm));
+    return;
+}
+
+
+/**************************************************************************
+                        v e r s i o n
+** non-standard...
+**************************************************************************/
+static void ficlPrimitiveVersion(ficlVm *vm)
+{
+    ficlVmTextOut(vm, "Ficl version " FICL_VERSION "\n");
+    return;
+}
+
+
+/**************************************************************************
+                        t o I n
+** to-in CORE
+**************************************************************************/
+static void ficlPrimitiveToIn(ficlVm *vm)
+{
+
+    FICL_STACK_CHECK(vm->dataStack,0,1);
+
+    ficlStackPushPointer(vm->dataStack, &vm->tib.index);
+    return;
+}
+
+
+/**************************************************************************
+                        c o l o n N o N a m e
+** CORE EXT ( C:  -- colon-sys )  ( S:  -- xt )
+** Create an unnamed colon definition and push its address.
+** Change state to FICL_VM_STATE_COMPILE.
+**************************************************************************/
+static void ficlPrimitiveColonNoName(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlWord *word;
+    ficlString name;
+
+    FICL_STRING_SET_LENGTH(name, 0);
+    FICL_STRING_SET_POINTER(name, NULL);
+
+    vm->state = FICL_VM_STATE_COMPILE;
+    word = ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionColonParen, FICL_WORD_DEFAULT | FICL_WORD_SMUDGED);
+    ficlStackPushPointer(vm->dataStack, word);
+    markControlTag(vm, colonTag);
+    return;
+}
+
+
+/**************************************************************************
+                        u s e r   V a r i a b l e
+** user  ( u -- )  "<spaces>name"  
+** Get a name from the input stream and create a user variable
+** with the name and the index supplied. The run-time effect
+** of a user variable is to push the address of the indexed ficlCell
+** in the running vm's user array. 
+**
+** User variables are vm local cells. Each vm has an array of
+** FICL_USER_CELLS of them when FICL_WANT_USER is nonzero.
+** Ficl's user facility is implemented with two primitives,
+** "user" and "(user)", a variable ("nUser") (in softcore.c) that 
+** holds the index of the next free user ficlCell, and a redefinition
+** (also in softcore) of "user" that defines a user word and increments
+** nUser.
+**************************************************************************/
+#if FICL_WANT_USER
+static void ficlPrimitiveUser(ficlVm *vm)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlString name = ficlVmGetWord(vm);
+    ficlCell c;
+
+    c = ficlStackPop(vm->dataStack);
+    if (c.i >= FICL_USER_CELLS)
+    {
+        ficlVmThrowError(vm, "Error - out of user space");
+    }
+
+    ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionUserParen, FICL_WORD_DEFAULT);
+    ficlDictionaryAppendCell(dictionary, c);
+    return;
+}
+#endif
+
+
+#if FICL_WANT_LOCALS
+/*
+** Each local is recorded in a private locals dictionary as a 
+** word that does doLocalIm at runtime. DoLocalIm compiles code
+** into the client definition to fetch the value of the 
+** corresponding local variable from the return stack.
+** The private dictionary gets initialized at the end of each block
+** that uses locals (in ; and does> for example).
+*/
+void ficlLocalParenIm(ficlVm *vm, int isDouble, int isFloat)
+{
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlInteger nLocal = vm->runningWord->param[0].i;
+
+#if !FICL_WANT_FLOAT
+	FICL_VM_ASSERT(vm, !isFloat);
+	/* get rid of unused parameter warning */
+	isFloat = 0;
+#endif /* FICL_WANT_FLOAT */
+
+    if (vm->state == FICL_VM_STATE_INTERPRET)
+    {
+		ficlStack *stack;
+#if FICL_WANT_FLOAT
+		if (isFloat)
+			stack = vm->floatStack;
+		else
+#endif /* FICL_WANT_FLOAT */
+		stack = vm->dataStack;
+
+        ficlStackPush(stack, vm->returnStack->frame[nLocal]);
+		if (isDouble)
+            ficlStackPush(stack, vm->returnStack->frame[nLocal+1]);
+    }
+    else
+    {
+		ficlInstruction instruction;
+		ficlInteger appendLocalOffset;
+#if FICL_WANT_FLOAT
+        if (isFloat)
+		{
+			instruction = (isDouble) ? ficlInstructionGetF2LocalParen : ficlInstructionGetFLocalParen;
+			appendLocalOffset = FICL_TRUE;
+		}
+		else
+#endif /* FICL_WANT_FLOAT */
+		if (nLocal == 0)
+		{
+			instruction = (isDouble) ? ficlInstructionGet2Local0 : ficlInstructionGetLocal0;
+			appendLocalOffset = FICL_FALSE;
+		}
+		else if ((nLocal == 1) && !isDouble)
+		{
+			instruction = ficlInstructionGetLocal1;
+			appendLocalOffset = FICL_FALSE;
+		}
+		else
+		{
+			instruction = (isDouble) ? ficlInstructionGet2LocalParen : ficlInstructionGetLocalParen;
+			appendLocalOffset = FICL_TRUE;
+		}
+
+		ficlDictionaryAppendUnsigned(dictionary, instruction);
+		if (appendLocalOffset)
+			ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(nLocal));
+    }
+    return;
+}
+
+static void ficlPrimitiveDoLocalIm(ficlVm *vm)
+{
+    ficlLocalParenIm(vm, FICL_FALSE, FICL_FALSE);
+}
+
+static void ficlPrimitiveDo2LocalIm(ficlVm *vm)
+{
+    ficlLocalParenIm(vm, FICL_TRUE, FICL_FALSE);
+}
+
+#if FICL_WANT_FLOAT
+static void ficlPrimitiveDoFLocalIm(ficlVm *vm)
+{
+    ficlLocalParenIm(vm, FICL_FALSE, FICL_TRUE);
+}
+
+static void ficlPrimitiveDoF2LocalIm(ficlVm *vm)
+{
+    ficlLocalParenIm(vm, FICL_TRUE, FICL_TRUE);
+}
+#endif /* FICL_WANT_FLOAT */
+
+
+
+/**************************************************************************
+                        l o c a l P a r e n
+** paren-local-paren LOCAL 
+** Interpretation: Interpretation semantics for this word are undefined.
+** Execution: ( c-addr u -- )
+** When executed during compilation, (LOCAL) passes a message to the 
+** system that has one of two meanings. If u is non-zero,
+** the message identifies a new local whose definition name is given by
+** the string of characters identified by c-addr u. If u is zero,
+** the message is last local and c-addr has no significance. 
+**
+** The result of executing (LOCAL) during compilation of a definition is
+** to create a set of named local identifiers, each of which is
+** a definition name, that only have execution semantics within the scope
+** of that definition's source. 
+**
+** local Execution: ( -- x )
+**
+** Push the local's value, x, onto the stack. The local's value is
+** initialized as described in 13.3.3 Processing locals and may be
+** changed by preceding the local's name with TO. An ambiguous condition
+** exists when local is executed while in interpretation state. 
+**************************************************************************/
+void ficlLocalParen(ficlVm *vm, int isDouble, int isFloat)
+{
+    ficlDictionary *dictionary;
+    ficlString name;
+
+    FICL_STACK_CHECK(vm->dataStack,2,0);  
+
+
+    dictionary = ficlVmGetDictionary(vm);
+    FICL_STRING_SET_LENGTH(name, ficlStackPopUnsigned(vm->dataStack));
+    FICL_STRING_SET_POINTER(name, (char *)ficlStackPopPointer(vm->dataStack));
+
+    if (FICL_STRING_GET_LENGTH(name) > 0)
+    {   /* add a local to the **locals** dictionary and update localsCount */
+        ficlPrimitive code;
+		ficlInstruction instruction;
+        ficlDictionary *locals = ficlSystemGetLocals(vm->callback.system);
+        if (vm->callback.system->localsCount >= FICL_MAX_LOCALS)
+        {
+            ficlVmThrowError(vm, "Error: out of local space");
+        }
+
+#if !FICL_WANT_FLOAT
+		FICL_VM_ASSERT(vm, !isFloat);
+		/* get rid of unused parameter warning */
+		isFloat = 0;
+#else /* FICL_WANT_FLOAT */
+		if (isFloat)
+		{
+			if (isDouble)
+			{
+				code = ficlPrimitiveDoF2LocalIm;
+				instruction = ficlInstructionToF2LocalParen;
+			}
+			else
+			{
+				code = ficlPrimitiveDoFLocalIm;
+				instruction = ficlInstructionToFLocalParen;
+			}
+		}
+		else
+#endif /* FICL_WANT_FLOAT */
+        if (isDouble)
+		{
+			code = ficlPrimitiveDo2LocalIm;
+			instruction = ficlInstructionTo2LocalParen;
+		}
+		else
+		{
+			code = ficlPrimitiveDoLocalIm;
+			instruction = ficlInstructionToLocalParen;
+		}
+
+        ficlDictionaryAppendWord(locals, name, code, FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+        ficlDictionaryAppendCell(locals,  FICL_LVALUE_TO_CELL(vm->callback.system->localsCount));
+
+        if (vm->callback.system->localsCount == 0)
+        {   /* FICL_VM_STATE_COMPILE code to create a local stack frame */
+            ficlDictionaryAppendUnsigned(dictionary, ficlInstructionLinkParen);
+            /* save location in dictionary for #locals */
+            vm->callback.system->localsFixup = dictionary->here;
+            ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(vm->callback.system->localsCount));
+        }
+
+        ficlDictionaryAppendUnsigned(dictionary, instruction);
+        ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(vm->callback.system->localsCount));
+
+        vm->callback.system->localsCount += (isDouble) ? 2 : 1;
+    }
+    else if (vm->callback.system->localsCount > 0)
+    {
+        /* write localsCount to (link) param area in dictionary */
+        *(ficlInteger *)(vm->callback.system->localsFixup) = vm->callback.system->localsCount;
+    }
+
+    return;
+}
+
+
+static void ficlPrimitiveLocalParen(ficlVm *vm)
+{
+   ficlLocalParen(vm, FICL_FALSE, FICL_FALSE);
+}
+
+static void ficlPrimitive2LocalParen(ficlVm *vm)
+{
+   ficlLocalParen(vm, FICL_TRUE, FICL_FALSE);
+}
+
+
+#endif /* FICL_WANT_LOCALS */
+
+
+/**************************************************************************
+                        t o V a l u e
+** CORE EXT 
+** Interpretation: ( x "<spaces>name" -- )
+** Skip leading spaces and parse name delimited by a space. Store x in 
+** name. An ambiguous condition exists if name was not defined by VALUE. 
+** NOTE: In Ficl, VALUE is an alias of CONSTANT
+**************************************************************************/
+static void ficlPrimitiveToValue(ficlVm *vm)
+{
+    ficlString name = ficlVmGetWord(vm);
+    ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+    ficlWord *word;
+	ficlInstruction instruction = 0;
+	ficlStack *stack;
+	ficlInteger isDouble;
+#if FICL_WANT_LOCALS
+	ficlInteger nLocal;
+	ficlInteger appendLocalOffset;
+	ficlInteger isFloat;
+#endif /* FICL_WANT_LOCALS */
+
+#if FICL_WANT_LOCALS
+    if ((vm->callback.system->localsCount > 0) && (vm->state == FICL_VM_STATE_COMPILE))
+    {
+        ficlDictionary *locals;
+
+        locals = ficlSystemGetLocals(vm->callback.system);
+        word = ficlDictionaryLookup(locals, name);
+		if (!word)
+			goto TO_GLOBAL;
+
+		if (word->code == ficlPrimitiveDoLocalIm)
+		{
+			instruction = ficlInstructionToLocalParen;
+			isDouble = isFloat = FICL_FALSE;
+		}
+		else if (word->code == ficlPrimitiveDo2LocalIm)
+		{
+			instruction = ficlInstructionTo2LocalParen;
+			isDouble = FICL_TRUE;
+			isFloat = FICL_FALSE;
+		}
+#if FICL_WANT_FLOAT
+		else if (word->code == ficlPrimitiveDoFLocalIm)
+		{
+			instruction = ficlInstructionToFLocalParen;
+			isDouble = FICL_FALSE;
+			isFloat = FICL_TRUE;
+		}
+		else if (word->code == ficlPrimitiveDoF2LocalIm)
+		{
+			instruction = ficlInstructionToF2LocalParen;
+			isDouble = isFloat = FICL_TRUE;
+		}
+#endif /* FICL_WANT_FLOAT */
+		else
+		{
+			ficlVmThrowError(vm, "to %.*s : local is of unknown type", FICL_STRING_GET_LENGTH(name), FICL_STRING_GET_POINTER(name));
+			return;
+		}
+
+		nLocal = word->param[0].i;
+		appendLocalOffset = FICL_TRUE;
+
+#if FICL_WANT_FLOAT
+		if (!isFloat)
+		{
+#endif /* FICL_WANT_FLOAT */
+		if (nLocal == 0)
+		{
+			instruction = (isDouble) ? ficlInstructionTo2Local0 : ficlInstructionToLocal0;
+			appendLocalOffset = FICL_FALSE;
+		}
+		else if ((nLocal == 1) && !isDouble)
+		{
+			instruction = ficlInstructionToLocal1;
+			appendLocalOffset = FICL_FALSE;
+		}
+#if FICL_WANT_FLOAT
+		}
+#endif /* FICL_WANT_FLOAT */
+		
+        ficlDictionaryAppendUnsigned(dictionary, instruction);
+		if (appendLocalOffset)
+			ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(nLocal));
+        return;
+    }
+#endif
+
+#if FICL_WANT_LOCALS
+TO_GLOBAL:
+#endif /* FICL_WANT_LOCALS */
+    word = ficlDictionaryLookup(dictionary, name);
+    if (!word)
+        ficlVmThrowError(vm, "%.*s not found", FICL_STRING_GET_LENGTH(name), FICL_STRING_GET_POINTER(name));
+
+	switch ((ficlInstruction)word->code)
+	{
+		case ficlInstructionConstantParen:
+			instruction = ficlInstructionStore;
+			stack = vm->dataStack;
+			isDouble = FICL_FALSE;
+			break;
+		case ficlInstruction2ConstantParen:
+			instruction = ficlInstruction2Store;
+			stack = vm->dataStack;
+			isDouble = FICL_TRUE;
+			break;
+#if FICL_WANT_FLOAT
+		case ficlInstructionFConstantParen:
+			instruction = ficlInstructionFStore;
+			stack = vm->floatStack;
+			isDouble = FICL_FALSE;
+			break;
+		case ficlInstructionF2ConstantParen:
+			instruction = ficlInstructionF2Store;
+			stack = vm->floatStack;
+			isDouble = FICL_TRUE;
+			break;
+#endif /* FICL_WANT_FLOAT */
+		default:
+		{
+		    ficlVmThrowError(vm, "to %.*s : value/constant is of unknown type", FICL_STRING_GET_LENGTH(name), FICL_STRING_GET_POINTER(name));
+		    return;
+		}
+	}
+	
+    if (vm->state == FICL_VM_STATE_INTERPRET)
+	{
+        word->param[0] = ficlStackPop(stack);
+		if (isDouble)
+			word->param[1] = ficlStackPop(stack);
+	}
+    else        /* FICL_VM_STATE_COMPILE code to store to word's param */
+    {
+        ficlStackPushPointer(vm->dataStack, &word->param[0]);
+        ficlPrimitiveLiteralIm(vm);
+        ficlDictionaryAppendUnsigned(dictionary, instruction);
+    }
+    return;
+}
+
+
+/**************************************************************************
+						f m S l a s h M o d
+** f-m-slash-mod CORE ( d1 n1 -- n2 n3 )
+** Divide d1 by n1, giving the floored quotient n3 and the remainder n2.
+** Input and output stack arguments are signed. An ambiguous condition
+** exists if n1 is zero or if the quotient lies outside the range of a
+** single-ficlCell signed integer. 
+**************************************************************************/
+static void ficlPrimitiveFMSlashMod(ficlVm *vm)
+{
+	ficl2Integer d1;
+	ficlInteger n1;
+	ficl2IntegerQR qr;
+
+	FICL_STACK_CHECK(vm->dataStack, 3, 2);
+
+	n1 = ficlStackPopInteger(vm->dataStack);
+	d1 = ficlStackPop2Integer(vm->dataStack);
+	qr = ficl2IntegerDivideFloored(d1, n1);
+	ficlStackPushInteger(vm->dataStack, qr.remainder);
+	ficlStackPushInteger(vm->dataStack, FICL_2UNSIGNED_GET_LOW(qr.quotient));
+	return;
+}
+
+
+/**************************************************************************
+						s m S l a s h R e m
+** s-m-slash-remainder CORE ( d1 n1 -- n2 n3 )
+** Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2.
+** Input and output stack arguments are signed. An ambiguous condition
+** exists if n1 is zero or if the quotient lies outside the range of a
+** single-ficlCell signed integer. 
+**************************************************************************/
+static void ficlPrimitiveSMSlashRem(ficlVm *vm)
+{
+	ficl2Integer d1;
+	ficlInteger n1;
+	ficl2IntegerQR qr;
+	
+	FICL_STACK_CHECK(vm->dataStack, 3, 2);
+
+	n1 = ficlStackPopInteger(vm->dataStack);
+	d1 = ficlStackPop2Integer(vm->dataStack);
+	qr = ficl2IntegerDivideSymmetric(d1, n1);
+	ficlStackPushInteger(vm->dataStack, qr.remainder);
+	ficlStackPushInteger(vm->dataStack, FICL_2UNSIGNED_GET_LOW(qr.quotient));
+	return;
+}
+
+
+static void ficlPrimitiveMod(ficlVm *vm)
+{
+	ficl2Integer d1;
+	ficlInteger n1;
+	ficlInteger i;
+	ficl2IntegerQR qr;
+	FICL_STACK_CHECK(vm->dataStack, 2, 1);
+
+	n1 = ficlStackPopInteger(vm->dataStack);
+	i = ficlStackPopInteger(vm->dataStack);
+	FICL_INTEGER_TO_2INTEGER(i, d1);
+	qr = ficl2IntegerDivideSymmetric(d1, n1);
+	ficlStackPushInteger(vm->dataStack, qr.remainder);
+	return;
+}
+
+
+/**************************************************************************
+						u m S l a s h M o d
+** u-m-slash-mod CORE ( ud u1 -- u2 u3 )
+** Divide ud by u1, giving the quotient u3 and the remainder u2.
+** All values and arithmetic are unsigned. An ambiguous condition
+** exists if u1 is zero or if the quotient lies outside the range of a
+** single-ficlCell unsigned integer. 
+*************************************************************************/
+static void ficlPrimitiveUMSlashMod(ficlVm *vm)
+{
+	ficl2Unsigned ud;
+	ficlUnsigned u1;
+	ficl2UnsignedQR uqr;
+
+	u1    = ficlStackPopUnsigned(vm->dataStack);
+	ud    = ficlStackPop2Unsigned(vm->dataStack);
+	uqr   = ficl2UnsignedDivide(ud, u1);
+	ficlStackPushUnsigned(vm->dataStack, uqr.remainder);
+	ficlStackPushUnsigned(vm->dataStack, FICL_2UNSIGNED_GET_LOW(uqr.quotient));
+	return;
+}
+
+
+
+/**************************************************************************
+						m S t a r
+** m-star CORE ( n1 n2 -- d )
+** d is the signed product of n1 times n2. 
+**************************************************************************/
+static void ficlPrimitiveMStar(ficlVm *vm)
+{
+	ficlInteger n2;
+	ficlInteger n1;
+	ficl2Integer d;
+	FICL_STACK_CHECK(vm->dataStack, 2, 2);
+
+	n2 = ficlStackPopInteger(vm->dataStack);
+	n1 = ficlStackPopInteger(vm->dataStack);
+
+	d = ficl2IntegerMultiply(n1, n2);
+	ficlStackPush2Integer(vm->dataStack, d);
+	return;
+}
+
+
+static void ficlPrimitiveUMStar(ficlVm *vm)
+{
+	ficlUnsigned u2;
+	ficlUnsigned u1;
+	ficl2Unsigned ud;
+	FICL_STACK_CHECK(vm->dataStack, 2, 2);
+
+	u2 = ficlStackPopUnsigned(vm->dataStack);
+	u1 = ficlStackPopUnsigned(vm->dataStack);
+
+	ud = ficl2UnsignedMultiply(u1, u2);
+	ficlStackPush2Unsigned(vm->dataStack, ud);
+	return;
+}
+
+
+/**************************************************************************
+						d n e g a t e
+** DOUBLE   ( d1 -- d2 )
+** d2 is the negation of d1. 
+**************************************************************************/
+static void ficlPrimitiveDNegate(ficlVm *vm)
+{
+	ficl2Integer i = ficlStackPop2Integer(vm->dataStack);
+	i = ficl2IntegerNegate(i);
+	ficlStackPush2Integer(vm->dataStack, i);
+
+	return;
+}
+
+
+
+
+/**************************************************************************
+                        p a d
+** CORE EXT  ( -- c-addr )
+** c-addr is the address of a transient region that can be used to hold
+** data for intermediate processing.
+**************************************************************************/
+static void ficlPrimitivePad(ficlVm *vm)
+{
+    ficlStackPushPointer(vm->dataStack, vm->pad);
+}
+
+
+/**************************************************************************
+                        s o u r c e - i d
+** CORE EXT, FILE   ( -- 0 | -1 | fileid )
+**    Identifies the input source as follows:
+**
+** SOURCE-ID       Input source
+** ---------       ------------
+** fileid          Text file fileid
+** -1              String (via EVALUATE)
+** 0               User input device
+**************************************************************************/
+static void ficlPrimitiveSourceID(ficlVm *vm)
+{
+    ficlStackPushInteger(vm->dataStack, vm->sourceId.i);
+    return;
+}
+
+
+/**************************************************************************
+                        r e f i l l
+** CORE EXT   ( -- flag )
+** Attempt to fill the input buffer from the input source, returning a FICL_TRUE
+** flag if successful. 
+** When the input source is the user input device, attempt to receive input
+** into the terminal input buffer. If successful, make the result the input
+** buffer, set >IN to zero, and return FICL_TRUE. Receipt of a line containing no
+** characters is considered successful. If there is no input available from
+** the current input source, return FICL_FALSE. 
+** When the input source is a string from EVALUATE, return FICL_FALSE and
+** perform no other action. 
+**************************************************************************/
+static void ficlPrimitiveRefill(ficlVm *vm)
+{
+    ficlInteger ret = (vm->sourceId.i == -1) ? FICL_FALSE : FICL_TRUE;
+    if (ret && (vm->restart == 0))
+        ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
+
+    ficlStackPushInteger(vm->dataStack, ret);
+    return;
+}
+
+
+/**************************************************************************
+                        freebsd exception handling words
+** Catch, from ANS Forth standard. Installs a safety net, then EXECUTE
+** the word in ToS. If an exception happens, restore the state to what
+** it was before, and pushes the exception value on the stack. If not,
+** push zero.
+**
+** Notice that Catch implements an inner interpreter. This is ugly,
+** but given how Ficl works, it cannot be helped. The problem is that
+** colon definitions will be executed *after* the function returns,
+** while "code" definitions will be executed immediately. I considered
+** other solutions to this problem, but all of them shared the same
+** basic problem (with added disadvantages): if Ficl ever changes it's
+** inner thread modus operandi, one would have to fix this word.
+**
+** More comments can be found throughout catch's code.
+**
+** Daniel C. Sobral Jan 09/1999
+** sadler may 2000 -- revised to follow ficl.c:ficlExecXT.
+**************************************************************************/
+
+static void ficlPrimitiveCatch(ficlVm *vm)
+{
+    int         except;
+    jmp_buf     vmState;
+    ficlVm     vmCopy;
+    ficlStack  dataStackCopy;
+    ficlStack  returnStackCopy;
+    ficlWord   *word;
+
+    FICL_VM_ASSERT(vm, vm);
+    FICL_VM_ASSERT(vm, vm->callback.system->exitInnerWord);
+    
+
+    /*
+    ** Get xt.
+    ** We need this *before* we save the stack pointer, or
+    ** we'll have to pop one element out of the stack after
+    ** an exception. I prefer to get done with it up front. :-)
+    */
+
+    FICL_STACK_CHECK(vm->dataStack, 1, 0);
+
+    word = ficlStackPopPointer(vm->dataStack);
+
+    /* 
+    ** Save vm's state -- a catch will not back out environmental
+    ** changes.
+    **
+    ** We are *not* saving dictionary state, since it is
+    ** global instead of per vm, and we are not saving
+    ** stack contents, since we are not required to (and,
+    ** thus, it would be useless). We save vm, and vm
+    ** "stacks" (a structure containing general information
+    ** about it, including the current stack pointer).
+    */
+    memcpy((void*)&vmCopy, (void*)vm, sizeof(ficlVm));
+    memcpy((void*)&dataStackCopy, (void*)vm->dataStack, sizeof(ficlStack));
+    memcpy((void*)&returnStackCopy, (void*)vm->returnStack, sizeof(ficlStack));
+
+    /*
+    ** Give vm a jmp_buf
+    */
+    vm->exceptionHandler = &vmState;
+
+    /*
+    ** Safety net
+    */
+    except = setjmp(vmState);
+
+    switch (except)
+    {
+        /*
+        ** Setup condition - push poison pill so that the VM throws
+        ** VM_INNEREXIT if the XT terminates normally, then execute
+        ** the XT
+        */
+    case 0:
+        ficlVmPushIP(vm, &(vm->callback.system->exitInnerWord));          /* Open mouth, insert emetic */
+        ficlVmExecuteWord(vm, word);
+        ficlVmInnerLoop(vm, 0);
+        break;
+
+        /*
+        ** Normal exit from XT - lose the poison pill, 
+        ** restore old setjmp vector and push a zero. 
+        */
+    case FICL_VM_STATUS_INNER_EXIT:
+        ficlVmPopIP(vm);                   /* Gack - hurl poison pill */
+        vm->exceptionHandler = vmCopy.exceptionHandler;        /* Restore just the setjmp vector */
+        ficlStackPushInteger(vm->dataStack, 0);   /* Push 0 -- everything is ok */
+        break;
+
+        /*
+        ** Some other exception got thrown - restore pre-existing VM state
+        ** and push the exception code
+        */
+    default:
+        /* Restore vm's state */
+        memcpy((void*)vm, (void*)&vmCopy, sizeof(ficlVm));
+        memcpy((void*)vm->dataStack, (void*)&dataStackCopy, sizeof(ficlStack));
+        memcpy((void*)vm->returnStack, (void*)&returnStackCopy, sizeof(ficlStack));
+
+        ficlStackPushInteger(vm->dataStack, except);/* Push error */
+        break;
+    }
+}
+
+/**************************************************************************
+**                     t h r o w
+** EXCEPTION
+** Throw --  From ANS Forth standard.
+**
+** Throw takes the ToS and, if that's different from zero,
+** returns to the last executed catch context. Further throws will
+** unstack previously executed "catches", in LIFO mode.
+**
+** Daniel C. Sobral Jan 09/1999
+**************************************************************************/
+static void ficlPrimitiveThrow(ficlVm *vm)
+{
+    int except;
+    
+    except = ficlStackPopInteger(vm->dataStack);
+
+    if (except)
+        ficlVmThrow(vm, except);
+}
+
+
+/**************************************************************************
+**                     a l l o c a t e
+** MEMORY
+**************************************************************************/
+static void ficlPrimitiveAllocate(ficlVm *vm)
+{
+    size_t size;
+    void *p;
+
+    size = ficlStackPopInteger(vm->dataStack);
+    p = ficlMalloc(size);
+    ficlStackPushPointer(vm->dataStack, p);
+    if (p)
+        ficlStackPushInteger(vm->dataStack, 0);
+    else
+        ficlStackPushInteger(vm->dataStack, 1);
+}
+
+
+/**************************************************************************
+**                     f r e e 
+** MEMORY
+**************************************************************************/
+static void ficlPrimitiveFree(ficlVm *vm)
+{
+    void *p;
+
+    p = ficlStackPopPointer(vm->dataStack);
+    ficlFree(p);
+    ficlStackPushInteger(vm->dataStack, 0);
+}
+
+
+/**************************************************************************
+**                     r e s i z e
+** MEMORY
+**************************************************************************/
+static void ficlPrimitiveResize(ficlVm *vm)
+{
+    size_t size;
+    void *new, *old;
+
+    size = ficlStackPopInteger(vm->dataStack);
+    old = ficlStackPopPointer(vm->dataStack);
+    new = ficlRealloc(old, size);
+    if (new) 
+    {
+        ficlStackPushPointer(vm->dataStack, new);
+        ficlStackPushInteger(vm->dataStack, 0);
+    } 
+    else 
+    {
+        ficlStackPushPointer(vm->dataStack, old);
+        ficlStackPushInteger(vm->dataStack, 1);
+    }
+}
+
+
+/**************************************************************************
+**                     e x i t - i n n e r 
+** Signals execXT that an inner loop has completed
+**************************************************************************/
+static void ficlPrimitiveExitInner(ficlVm *vm)
+{
+    ficlVmThrow(vm, FICL_VM_STATUS_INNER_EXIT);
+}
+
+
+#if 0
+/**************************************************************************
+                        
+** 
+**************************************************************************/
+static void ficlPrimitiveName(ficlVm *vm)
+{
+    FICL_IGNORE(vm);
+    return;
+}
+
+
+#endif
+/**************************************************************************
+                        f i c l C o m p i l e C o r e
+** Builds the primitive wordset and the environment-query namespace.
+**************************************************************************/
+
+void ficlSystemCompileCore(ficlSystem *system)
+{
+	ficlWord *interpret;
+    ficlDictionary *dictionary = ficlSystemGetDictionary(system);
+    ficlDictionary *environment = ficlSystemGetEnvironment(system);
+
+    FICL_SYSTEM_ASSERT(system, dictionary);
+    FICL_SYSTEM_ASSERT(system, environment);
+
+
+	#define FICL_TOKEN(token, description) 
+	#define FICL_INSTRUCTION_TOKEN(token, description, flags) ficlDictionarySetInstruction(dictionary, description, token, flags);
+	#include "ficltokens.h"
+	#undef FICL_TOKEN
+	#undef FICL_INSTRUCTION_TOKEN
+
+    /*
+    ** The Core word set
+    ** see softcore.c for definitions of: abs bl space spaces abort"
+    */
+    ficlDictionarySetPrimitive(dictionary, "#",         ficlPrimitiveNumberSign,     FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "#>",        ficlPrimitiveNumberSignGreater,FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "#s",        ficlPrimitiveNumberSignS,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "\'",        ficlPrimitiveTick,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "(",         ficlPrimitiveParenthesis,    FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "+loop",     ficlPrimitivePlusLoopCoIm,   FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, ".",         ficlPrimitiveDot,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, ".\"",       ficlPrimitiveDotQuoteCoIm,   FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, ":",         ficlPrimitiveColon,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, ";",         ficlPrimitiveSemicolonCoIm,  FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "<#",        ficlPrimitiveLessNumberSign, FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, ">body",     ficlPrimitiveToBody,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, ">in",       ficlPrimitiveToIn,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, ">number",   ficlPrimitiveToNumber,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "abort",     ficlPrimitiveAbort,      FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "accept",    ficlPrimitiveAccept,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "align",     ficlPrimitiveAlign,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "aligned",   ficlPrimitiveAligned,        FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "allot",     ficlPrimitiveAllot,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "base",      ficlPrimitiveBase,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "begin",     ficlPrimitiveBeginCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "case",      ficlPrimitiveCaseCoIm,       FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "char",      ficlPrimitiveChar,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "char+",     ficlPrimitiveCharPlus,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "chars",     ficlPrimitiveChars,      FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "constant",  ficlPrimitiveConstant,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "count",     ficlPrimitiveCount,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "cr",        ficlPrimitiveCR,             FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "create",    ficlPrimitiveCreate,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "decimal",   ficlPrimitiveDecimal,        FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "depth",     ficlPrimitiveDepth,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "do",        ficlPrimitiveDoCoIm,         FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "does>",     ficlPrimitiveDoesCoIm,       FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "else",      ficlPrimitiveElseCoIm,       FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "emit",      ficlPrimitiveEmit,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "endcase",   ficlPrimitiveEndcaseCoIm,    FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "endof",     ficlPrimitiveEndofCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "environment?", ficlPrimitiveEnvironmentQ,FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "evaluate",  ficlPrimitiveEvaluate,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "execute",   ficlPrimitiveExecute,        FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "exit",      ficlPrimitiveExitCoIm,       FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "fallthrough",ficlPrimitiveFallthroughCoIm,FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "find",      ficlPrimitiveCFind,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "fm/mod",    ficlPrimitiveFMSlashMod, FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "here",      ficlPrimitiveHere,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "hold",      ficlPrimitiveHold,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "if",        ficlPrimitiveIfCoIm,         FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "immediate", ficlPrimitiveImmediate,      FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "literal",   ficlPrimitiveLiteralIm,      FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "loop",      ficlPrimitiveLoopCoIm,       FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "m*",        ficlPrimitiveMStar,      FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "mod",       ficlPrimitiveMod,        FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "of",        ficlPrimitiveOfCoIm,         FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "postpone",  ficlPrimitivePostponeCoIm,   FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "quit",      ficlPrimitiveQuit,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "recurse",   ficlPrimitiveRecurseCoIm,    FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "repeat",    ficlPrimitiveRepeatCoIm,     FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "s\"",       ficlPrimitiveStringQuoteIm,  FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "sign",      ficlPrimitiveSign,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "sm/rem",    ficlPrimitiveSMSlashRem, FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "source",    ficlPrimitiveSource,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "state",     ficlPrimitiveState,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "then",      ficlPrimitiveEndifCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "type",      ficlPrimitiveType,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "u.",        ficlPrimitiveUDot,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "um*",       ficlPrimitiveUMStar,     FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "um/mod",    ficlPrimitiveUMSlashMod, FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "until",     ficlPrimitiveUntilCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "variable",  ficlPrimitiveVariable,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "while",     ficlPrimitiveWhileCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "word",      ficlPrimitiveWord,   FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "[",         ficlPrimitiveLeftBracketCoIm,   FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "[\']",      ficlPrimitiveBracketTickCoIm,FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "[char]",    ficlPrimitiveCharCoIm,       FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "]",         ficlPrimitiveRightBracket,       FICL_WORD_DEFAULT);
+    /* 
+    ** The Core Extensions word set...
+    ** see softcore.fr for other definitions
+    */
+    /* "#tib" */
+    ficlDictionarySetPrimitive(dictionary, ".(",        ficlPrimitiveDotParen,       FICL_WORD_IMMEDIATE);
+    /* ".r" */
+    ficlDictionarySetPrimitive(dictionary, ":noname",   ficlPrimitiveColonNoName,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "?do",       ficlPrimitiveQDoCoIm,        FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "again",     ficlPrimitiveAgainCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "c\"",       ficlPrimitiveCountedStringQuoteIm, FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "hex",       ficlPrimitiveHex,            FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "pad",       ficlPrimitivePad,            FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "parse",     ficlPrimitiveParse,          FICL_WORD_DEFAULT);
+    /* query restore-input save-input tib u.r u> unused [FICL_VM_STATE_COMPILE] */
+    ficlDictionarySetPrimitive(dictionary, "refill",    ficlPrimitiveRefill,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "source-id", ficlPrimitiveSourceID,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "to",        ficlPrimitiveToValue,        FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "value",     ficlPrimitiveConstant,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "\\",        ficlPrimitiveBackslash,    FICL_WORD_IMMEDIATE);
+
+
+    /*
+    ** Environment query values for the Core word set
+    */
+    ficlDictionarySetConstant(environment, "/counted-string",   FICL_COUNTED_STRING_MAX);
+    ficlDictionarySetConstant(environment, "/hold",             FICL_PAD_SIZE);
+    ficlDictionarySetConstant(environment, "/pad",              FICL_PAD_SIZE);
+    ficlDictionarySetConstant(environment, "address-unit-bits", 8);
+    ficlDictionarySetConstant(environment, "core",              FICL_TRUE);
+    ficlDictionarySetConstant(environment, "core-ext",          FICL_FALSE);
+    ficlDictionarySetConstant(environment, "floored",           FICL_FALSE);
+    ficlDictionarySetConstant(environment, "max-char",          UCHAR_MAX);
+    ficlDictionarySetConstant(environment, "max-n",             0x7fffffff);
+    ficlDictionarySetConstant(environment, "max-u",             0xffffffff);
+	{
+	ficl2Unsigned combined;
+	FICL_2UNSIGNED_SET(INT_MAX, UINT_MAX, combined);
+    ficlDictionarySet2Constant(environment,"max-d",             FICL_2UNSIGNED_TO_2INTEGER(combined));
+	FICL_2UNSIGNED_SET(UINT_MAX, UINT_MAX, combined);
+    ficlDictionarySet2Constant(environment,"max-ud",            FICL_2UNSIGNED_TO_2INTEGER(combined));
+	}
+    ficlDictionarySetConstant(environment, "return-stack-cells",FICL_DEFAULT_STACK_SIZE);
+    ficlDictionarySetConstant(environment, "stack-cells",       FICL_DEFAULT_STACK_SIZE);
+
+    /*
+    ** The optional Double-Number word set (partial)
+    */
+    ficlDictionarySetPrimitive(dictionary, "2constant", ficlPrimitive2Constant,    FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "2value",    ficlPrimitive2Constant,    FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "2literal",  ficlPrimitive2LiteralIm,   FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "2variable", ficlPrimitive2Variable,    FICL_WORD_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "dnegate",   ficlPrimitiveDNegate,    FICL_WORD_DEFAULT);
+
+
+    /*
+    ** The optional Exception and Exception Extensions word set
+    */
+    ficlDictionarySetPrimitive(dictionary, "catch",     ficlPrimitiveCatch,      FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "throw",     ficlPrimitiveThrow,      FICL_WORD_DEFAULT);
+
+    ficlDictionarySetConstant(environment, "exception",         FICL_TRUE);
+    ficlDictionarySetConstant(environment, "exception-ext",     FICL_TRUE);
+
+    /*
+    ** The optional Locals and Locals Extensions word set
+    ** see softcore.c for implementation of locals|
+    */
+#if FICL_WANT_LOCALS
+    ficlDictionarySetPrimitive(dictionary, "doLocal",   ficlPrimitiveDoLocalIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "(local)",   ficlPrimitiveLocalParen,     FICL_WORD_COMPILE_ONLY);
+    ficlDictionarySetPrimitive(dictionary, "(2local)",  ficlPrimitive2LocalParen,  FICL_WORD_COMPILE_ONLY);
+
+    ficlDictionarySetConstant(environment, "locals",            FICL_TRUE);
+    ficlDictionarySetConstant(environment, "locals-ext",        FICL_TRUE);
+    ficlDictionarySetConstant(environment, "#locals",           FICL_MAX_LOCALS);
+#endif
+
+    /*
+    ** The optional Memory-Allocation word set
+    */
+
+    ficlDictionarySetPrimitive(dictionary, "allocate",  ficlPrimitiveAllocate,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "free",      ficlPrimitiveFree,        FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "resize",    ficlPrimitiveResize,      FICL_WORD_DEFAULT);
+    
+    ficlDictionarySetConstant(environment, "memory-alloc",      FICL_TRUE);
+
+    /*
+    ** The optional Search-Order word set 
+    */
+    ficlSystemCompileSearch(system);
+
+    /*
+    ** The optional Programming-Tools and Programming-Tools Extensions word set
+    */
+    ficlSystemCompileTools(system);
+
+    /*
+    ** The optional File-Access and File-Access Extensions word set
+    */
+#if FICL_WANT_FILE
+    ficlSystemCompileFile(system);
+#endif
+
+    /*
+    ** Ficl extras
+    */
+    ficlDictionarySetPrimitive(dictionary, ".ver",      ficlPrimitiveVersion,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, ">name",     ficlPrimitiveToName,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "add-parse-step",
+                                    ficlPrimitiveAddParseStep,   FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "body>",     ficlPrimitiveFromBody,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "compile-only",
+                                    ficlPrimitiveCompileOnly,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "endif",     ficlPrimitiveEndifCoIm,      FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "last-word", ficlPrimitiveLastWord,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "hash",      ficlPrimitiveHash,           FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "objectify", ficlPrimitiveSetObjectFlag,  FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "?object",   ficlPrimitiveIsObject,       FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "parse-word",ficlPrimitiveParseNoCopy,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "sfind",     ficlPrimitiveSFind,          FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "sliteral",  ficlPrimitiveSLiteralCoIm,   FICL_WORD_COMPILE_ONLY_IMMEDIATE);
+    ficlDictionarySetPrimitive(dictionary, "sprintf",   ficlPrimitiveSprintf,    FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "strlen",    ficlPrimitiveStrlen,     FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "x.",        ficlPrimitiveHexDot,         FICL_WORD_DEFAULT);
+#if FICL_WANT_USER
+    ficlDictionarySetPrimitive(dictionary, "user",      ficlPrimitiveUser,   FICL_WORD_DEFAULT);
+#endif
+
+    /*
+    ** internal support words
+    */
+    interpret =
+    ficlDictionarySetPrimitive(dictionary, "interpret", ficlPrimitiveInterpret,      FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "lookup",    ficlPrimitiveLookup,         FICL_WORD_DEFAULT);
+    ficlDictionarySetPrimitive(dictionary, "(parse-step)", 
+                                    ficlPrimitiveParseStepParen, FICL_WORD_DEFAULT);
+	system->exitInnerWord =
+    ficlDictionarySetPrimitive(dictionary, "exit-inner",ficlPrimitiveExitInner,  FICL_WORD_DEFAULT);
+
+	/*
+	** Set constants representing the internal instruction words
+	** If you want all of 'em, turn that "#if 0" to "#if 1".
+	** By default you only get the numbers (fi0, fiNeg1, etc).
+	*/
+	#define FICL_TOKEN(token, description) ficlDictionarySetConstant(dictionary, #token, token);
+#if 0
+	#define FICL_INSTRUCTION_TOKEN(token, description, flags) ficlDictionarySetConstant(dictionary, #token, token);
+#else
+	#define FICL_INSTRUCTION_TOKEN(token, description, flags) 
+#endif /* 0 */
+	#include "ficltokens.h"
+	#undef FICL_TOKEN
+	#undef FICL_INSTRUCTION_TOKEN
+
+
+    /*
+    ** Set up system's outer interpreter loop - maybe this should be in initSystem?
+    */
+	system->interpreterLoop[0] = interpret;
+	system->interpreterLoop[1] = (ficlWord *)ficlInstructionBranchParen;
+	system->interpreterLoop[2] = (ficlWord *)(void *)(-2);
+
+    FICL_SYSTEM_ASSERT(system, ficlDictionaryCellsAvailable(dictionary) > 0);
+
+    return;
+}
+
--- /dev/null
+++ b/softcore/classes.fr
@@ -1,0 +1,172 @@
+S" FICL_WANT_OOP" ENVIRONMENT? drop [if]
+\ ** ficl/softwords/classes.fr
+\ ** F I C L   2 . 0   C L A S S E S
+\ john sadler  1 sep 98
+\ Needs oop.fr
+
+.( loading ficl utility classes ) cr
+also oop definitions
+
+\ REF subclass holds a pointer to an object. It's
+\ mainly for aggregation to help in making data structures.
+\
+object subclass c-ref
+    cell: .class
+    cell: .instance
+
+	: get   ( inst class -- refinst refclass )
+		drop 2@ ;
+	: set   ( refinst refclass inst class -- )
+		drop 2! ;
+end-class
+
+object subclass c-byte
+	char: .payload
+
+	: get  drop c@ ;
+	: set  drop c! ;
+end-class
+
+object subclass c-2byte
+	2 chars: .payload
+
+	: get  drop w@ ;
+	: set  drop w! ;
+end-class
+
+object subclass c-4byte
+	4 chars: .payload
+
+	: get  drop q@ ;
+	: set  drop q! ;
+end-class
+
+
+object subclass c-cell
+	cell: .payload
+
+	: get  drop @ ;
+	: set  drop ! ;
+end-class
+
+
+\ ** C - P T R 
+\ Base class for pointers to scalars (not objects).
+\ Note: use c-ref to make references to objects. C-ptr
+\ subclasses refer to untyped quantities of various sizes.
+
+\ Derived classes must specify the size of the thing
+\ they point to, and supply get and set methods.
+
+\ All derived classes must define the @size method:
+\ @size ( inst class -- addr-units )
+\ Returns the size in address units of the thing the pointer
+\ refers to.
+object subclass c-ptr
+    c-cell obj: .addr
+
+    \ get the value of the pointer
+    : get-ptr   ( inst class -- addr )
+        c-ptr  => .addr  
+        c-cell => get  
+    ;
+
+    \ set the pointer to address supplied
+    : set-ptr   ( addr inst class -- )
+        c-ptr  => .addr  
+        c-cell => set  
+    ;
+
+    \ force the pointer to be null
+	: clr-ptr
+	    0 -rot  c-ptr => .addr  c-cell => set
+	;
+
+    \ return flag indicating null-ness
+	: ?null     ( inst class -- flag )
+	    c-ptr => get-ptr 0= 
+	;
+
+    \ increment the pointer in place
+    : inc-ptr   ( inst class -- )
+        2dup 2dup                   ( i c i c i c )
+        c-ptr => get-ptr  -rot      ( i c addr i c )
+        --> @size  +  -rot          ( addr' i c )
+        c-ptr => set-ptr
+    ;
+
+    \ decrement the pointer in place
+    : dec-ptr    ( inst class -- )
+        2dup 2dup                   ( i c i c i c )
+        c-ptr => get-ptr  -rot      ( i c addr i c )
+        --> @size  -  -rot          ( addr' i c )
+        c-ptr => set-ptr
+    ;
+
+    \ index the pointer in place
+    : index-ptr   { index 2:this -- }
+        this --> get-ptr              ( addr )
+        this --> @size  index *  +    ( addr' )
+        this --> set-ptr
+    ;
+
+end-class
+
+
+\ ** C - C E L L P T R 
+\ Models a pointer to cell (a 32 or 64 bit scalar). 
+c-ptr subclass c-cellPtr
+    : @size   2drop  1 cells ;
+    \ fetch and store through the pointer
+	: get   ( inst class -- cell )
+        c-ptr => get-ptr @  
+    ;
+	: set   ( value inst class -- )
+        c-ptr => get-ptr !  
+    ;
+end-class
+
+
+\ ** C - 4 B Y T E P T R
+\ Models a pointer to a quadbyte scalar 
+c-ptr subclass c-4bytePtr
+    : @size   2drop  4  ;
+    \ fetch and store through the pointer
+	: get   ( inst class -- value )
+        c-ptr => get-ptr q@  
+    ;
+	: set   ( value inst class -- )
+        c-ptr => get-ptr q!  
+    ;
+ end-class
+ 
+\ ** C - 2 B Y T E P T R 
+\ Models a pointer to a 16 bit scalar
+c-ptr subclass c-2bytePtr
+    : @size   2drop  2  ;
+    \ fetch and store through the pointer
+	: get   ( inst class -- value )
+        c-ptr => get-ptr w@  
+    ;
+	: set   ( value inst class -- )
+        c-ptr => get-ptr w!  
+    ;
+end-class
+
+
+\ ** C - B Y T E P T R 
+\ Models a pointer to an 8 bit scalar
+c-ptr subclass c-bytePtr
+    : @size   2drop  1  ;
+    \ fetch and store through the pointer
+	: get   ( inst class -- value )
+        c-ptr => get-ptr c@  
+    ;
+	: set   ( value inst class -- )
+        c-ptr => get-ptr c!  
+    ;
+end-class
+
+
+previous definitions
+[endif]
--- /dev/null
+++ b/softcore/ficl.fr
@@ -1,0 +1,67 @@
+\ ** ficl/softwords/softcore.fr
+\ ** FICL soft extensions
+\ ** John Sadler (john_sadler@alum.mit.edu)
+\ ** September, 1998
+
+S" FICL_WANT_USER" ENVIRONMENT? drop [if]
+\ ** Ficl USER variables
+\ ** See words.c for primitive def'n of USER
+variable nUser  0 nUser ! 
+: user   \ name ( -- )  
+    nUser dup @ user 1 swap +! ; 
+
+[endif]
+
+
+
+S" FICL_WANT_LOCALS" ENVIRONMENT? drop [if]
+
+\ ** LOCAL EXT word set
+
+: locals|  ( name...name | -- )
+    begin
+        bl word   count
+        dup 0= abort" where's the delimiter??"
+        over c@
+        [char] | - over 1- or
+    while
+        (local)
+    repeat 2drop   0 0 (local)
+; immediate
+
+: local  ( name -- )  bl word count (local) ;  immediate
+
+: 2local  ( name -- ) bl word count (2local) ; immediate
+
+: end-locals  ( -- )  0 0 (local) ;  immediate
+
+
+\ Submitted by lch.
+: strdup ( c-addr length -- c-addr2 length2 ior )
+	0 locals| addr2 length c-addr | end-locals
+	length 1 + allocate
+	0= if
+		to addr2
+		c-addr addr2 length move
+		addr2 length 0
+	else
+		0  -1
+	endif
+	;
+
+: strcat ( 2:a 2:b -- 2:new-a )
+	0 locals|  b-length b-u b-addr a-u a-addr | end-locals
+	b-u  to b-length
+	b-addr a-addr a-u + b-length  move
+	a-addr a-u b-length +
+	;
+
+: strcpy ( 2:a 2:b -- 2:new-a )
+	locals| b-u b-addr a-u a-addr | end-locals
+	a-addr 0  b-addr b-u  strcat
+	;
+
+[endif]
+
+\ end-of-file
+
--- /dev/null
+++ b/softcore/ficlclass.fr
@@ -1,0 +1,84 @@
+S" FICL_WANT_OOP" ENVIRONMENT? drop [if]
+\ ** ficl/softwords/ficlclass.fr
+\ Classes to model ficl data structures in objects
+\ This is a demo!
+\ John Sadler 14 Sep 1998
+\
+\ ** C - W O R D
+\ Models a FICL_WORD
+
+object subclass c-word
+    c-word     ref: .link
+    c-2byte    obj: .hashcode
+    c-byte     obj: .flags
+    c-byte     obj: .nName
+    c-bytePtr  obj: .pName
+    c-cellPtr  obj: .pCode
+    c-4byte    obj: .param0
+
+    \ Push word's name...
+    : get-name   ( inst class -- c-addr u )
+        2dup
+        my=[ .pName get-ptr ] -rot
+        my=[ .nName get ]
+    ;
+
+    : next   ( inst class -- link-inst class )
+        my=> .link ;
+        
+    : ?
+        ." c-word: " 
+        2dup --> get-name type cr
+    ;
+
+end-class
+
+\ ** C - W O R D L I S T
+\ Models a FICL_HASH
+\ Example of use:
+\ get-current c-wordlist --> ref current
+\ current --> ?
+\ current --> .hash --> ?
+\ current --> .hash --> next --> ?
+
+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
+
+\ : named-wid  wordlist postpone c-wordlist  metaclass => ref ;
+
+
+\ ** C - F I C L S T A C K
+object subclass c-ficlstack
+    c-4byte    obj: .nCells
+    c-cellPtr  obj: .link
+    c-cellPtr  obj: .sp
+    c-4byte    obj: .stackBase
+
+    : init   2drop ;
+    : ?      2drop
+        ." ficl stack " cr ;
+    : top
+        --> .sp --> .addr --> prev --> get ;
+end-class
+
+[endif]
--- /dev/null
+++ b/softcore/ficllocal.fr
@@ -1,0 +1,46 @@
+\ ** ficl/softwords/ficllocal.fr
+\ ** stack comment style local syntax...
+\ {{ a b c -- d e }}
+\ variables before the "--" are initialized in reverse order
+\ from the stack. Those after the "--" are zero initialized
+\ Uses locals...
+\ locstate: 0 = looking for -- or }}
+\           1 = found --
+hide
+0 constant zero
+
+: ?--   s" --" compare 0= ;
+: ?}}   s" }}" compare 0= ;
+
+set-current
+
+: {{
+    0 dup  locals| nLocs locstate |
+    begin
+        parse-word 
+        ?dup 0= abort" Error: out of text without seeing }}"
+        2dup 2dup  ?-- -rot ?}} or 0=
+    while
+        nLocs 1+ to nLocs
+    repeat
+
+    ?-- if 1 to locstate endif
+
+    nLocs 0 do
+        (local) 
+    loop
+
+    locstate 1 = if
+        begin
+            parse-word
+            2dup ?}} 0=
+        while
+            postpone zero  (local)
+        repeat
+        2drop
+    endif
+
+    0 0 (local)
+; immediate compile-only
+ 
+previous
--- /dev/null
+++ b/softcore/fileaccess.fr
@@ -1,0 +1,22 @@
+S" FICL_WANT_FILE" ENVIRONMENT? drop [if]
+\ ** 
+\ ** File Access words for ficl
+\ ** submitted by Larry Hastings, larry@hastings.org
+\ **
+
+: r/o 1 ;
+: r/w 3 ; 
+: w/o 2 ; 
+: bin 8 or ; 
+
+: included
+    r/o bin open-file 0= if
+        include-file
+    else
+        drop
+    endif
+    ;
+
+: include parse-word included ;
+
+[endif]
--- /dev/null
+++ b/softcore/forml.fr
@@ -1,0 +1,72 @@
+\ examples from FORML conference paper Nov 98
+\ sadler
+.( loading FORML examples ) cr
+object --> sub c-example
+             cell: .cell0
+    c-4byte   obj: .nCells
+  4 c-4byte array: .quad
+       c-byte obj: .length
+         79 chars: .name
+
+    : init   ( inst class -- )
+        2dup  object => init
+        s" aardvark"  2swap  --> set-name
+    ;
+
+    : get-name  ( inst class -- c-addr u )
+        2dup 
+        --> .name  -rot      ( c-addr inst class )
+        --> .length --> get
+    ;
+
+    : set-name  { c-addr u 2:this -- }
+        u       this --> .length --> set
+        c-addr  this --> .name  u move
+    ;
+
+    : ?  ( inst class ) c-example => get-name type cr ;
+end-class
+
+
+: test ." this is a test" cr ;
+' test
+c-word --> ref testref
+
+\ add a method to c-word...
+c-word --> get-wid ficl-set-current
+\ list dictionary thread
+: list  ( inst class )
+    begin
+        2dup --> get-name type cr 
+        --> next over 
+    0= until
+    2drop
+;
+set-current 
+
+object subclass c-led
+    c-byte obj: .state
+
+    : 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
+    ;
+
+end-class
+
+
+object subclass c-switch
+
+    : ?on   { bit# 2:this -- flag }
+        
+        1 bit# lshift
+    ;
+end-class
+
--- /dev/null
+++ b/softcore/ifbrack.fr
@@ -1,0 +1,48 @@
+\ ** ficl/softwords/ifbrack.fr
+\ ** ANS conditional compile directives [if] [else] [then]
+\ ** Requires ficl 2.0 or greater...
+
+hide
+
+: ?[if]   ( c-addr u -- c-addr u flag )
+    2dup s" [if]" compare-insensitive 0=
+;
+
+: ?[else]   ( c-addr u -- c-addr u flag )
+    2dup s" [else]" compare-insensitive 0=
+;
+
+: ?[then]   ( c-addr u -- c-addr u flag )
+    2dup s" [then]" compare-insensitive 0= >r
+    2dup s" [endif]" compare-insensitive 0= r> 
+    or
+;
+
+set-current
+
+: [else]  ( -- )
+    1                                     \ ( level )
+    begin
+      begin
+        parse-word dup  while             \ ( level addr len )
+        ?[if] if                          \ ( level addr len )
+            2drop 1+                      \ ( level )
+        else                              \ ( level addr len )
+            ?[else] if                    \ ( level addr len )
+                 2drop 1- dup if 1+ endif
+            else
+                ?[then] if 2drop 1- else 2drop endif 
+            endif
+        endif ?dup 0=  if exit endif      \ level
+      repeat  2drop                       \ level
+    refill 0= until                       \ level
+    drop
+;  immediate
+
+: [if]  ( flag -- )
+0= if postpone [else] then ;  immediate
+
+: [then]  ( -- )  ;  immediate
+: [endif]  ( -- )  ;  immediate
+
+previous
--- /dev/null
+++ b/softcore/jhlocal.fr
@@ -1,0 +1,171 @@
+S" FICL_WANT_LOCALS" ENVIRONMENT? drop [if]
+\ ** ficl/softwords/jhlocal.fr
+\ ** stack comment style local syntax...
+\ { a b c | cleared -- d e }
+\ variables before the "|" are initialized in reverse order
+\ from the stack. Those after the "|" are zero initialized.
+\ Anything between "--" and "}" is treated as comment
+\ Uses locals...
+\ locstate: 0 = looking for | or -- or }}
+\           1 = found |
+\           2 = found --
+\           3 = found }
+\           4 = end of line
+\
+\ revised 2 June 2000 - { | a -- } now works correctly
+.( loading Johns-Hopkins locals ) cr
+hide
+
+\ What does this do?  It's equivalent to "postpone 0", but faster.
+\ "ficlInstruction0" is the FICL instruction for "push a 0 on the data stack".
+\ --lch
+: compiled-zero ficlInstruction0 , ;
+\ And this is the instruction for a floating-point 0 (0.0e).
+: compiled-float-zero ficlInstructionF0 , ;
+
+
+: ?--   ( c-addr u -- c-addr u flag )
+    2dup s" --" compare 0= ;
+: ?}    ( c-addr u -- c-addr u flag )
+    2dup s" }"  compare 0= ;
+: ?|    ( c-addr u -- c-addr u flag )
+    2dup s" |"  compare 0= ;
+
+1 constant local-is-double
+2 constant local-is-float
+
+\ parse-local-prefix-flags
+\
+\ Parses single-letter prefix flags from the name of a local, and returns
+\ a bitfield of all flags (local-is-float | local-is-double) appropriate
+\ for the local.  Adjusts the "c-addr u" of the name to remove any prefix.
+\
+\ Handled single-letter prefix flags:
+\	1  single-cell
+\	2  double-cell
+\	d  double-cell
+\	f  floating-point (use floating stack)
+\	i  integer (use data stack)
+\	s  single-cell
+\ Specify as many as you like; later flags have precidence.
+\ Thus, "f2:foo" and "2is2f:foo" are both double-cell floats.
+\
+\ If you don't specify anything after the colon, like "f2:",
+\ there is no legal prefix, so "2f:" becomes the name of the
+\ (single-cell data stack) local.
+\
+\ For convention, the "f" is preferred first.
+
+: parse-local-prefix-flags ( c-addr u -- c-addr u flags )
+    0 0 0 locals| stop-loop colon-offset flags   u c-addr |
+
+    \ if the first character is a colon, remove the colon and return 0.
+    c-addr c@ [char] : =
+    if
+        over over 0  exit
+    endif
+
+    u 0 do
+        c-addr i + c@
+       case
+           [char] 1 of  flags local-is-double invert and  to flags  endof
+           [char] 2 of  flags local-is-double or          to flags  endof
+           [char] d of  flags local-is-double or          to flags  endof
+           [char] f of  flags local-is-float  or          to flags  endof
+           [char] i of  flags local-is-float  invert and  to flags  endof
+           [char] s of  flags local-is-double invert and  to flags  endof
+           [char] : of  i 1+ to colon-offset   1 to stop-loop  endof
+           1 to stop-loop
+       endcase
+    stop-loop  if leave  endif
+    loop
+
+    colon-offset 0=
+    colon-offset u =
+    or
+    if
+\        ." Returning variable name -- " c-addr u type ."  -- No flags." cr
+        c-addr u 0 exit
+    endif
+
+    c-addr colon-offset +
+    u colon-offset -
+\    ." Returning variable name -- " 2dup type ."  -- Flags: " flags . cr
+    flags
+;
+
+: ?delim   ( c-addr u -- state | c-addr u 0 )
+    ?|  if  2drop 1 exit endif
+    ?-- if  2drop 2 exit endif
+    ?}  if  2drop 3 exit endif
+    dup 0= 
+        if  2drop 4 exit endif
+    0
+;
+
+
+
+set-current
+
+: {
+    0 0 0 locals| flags local-state nLocals |
+    
+    \ stack locals until we hit a delimiter
+    begin
+        parse-word ?delim  dup to local-state
+    0= while
+        nLocals 1+ to nLocals
+    repeat
+
+    \ now unstack the locals
+    nLocals 0 ?do
+            parse-local-prefix-flags to flags
+            flags local-is-double and if
+                flags local-is-float and if (f2local) else (2local) endif
+            else
+                flags local-is-float and if (flocal) else (local) endif
+            endif
+	loop   \ ( )
+
+    \ zero locals until -- or }
+    local-state 1 = if
+        begin
+            parse-word
+            ?delim dup to local-state
+        0= while
+            parse-local-prefix-flags to flags
+            flags local-is-double and if
+                flags local-is-float and if
+                    compiled-float-zero compiled-float-zero (f2local)
+                else
+                    compiled-zero compiled-zero (2local)
+                endif
+            else
+                flags local-is-float and if
+                    compiled-float-zero (flocal)
+                else
+                    compiled-zero (local)
+                endif
+            endif
+        repeat
+    endif
+
+    0 0 (local)
+
+    \ toss words until }
+    \ (explicitly allow | and -- in the comment)
+    local-state 2 = if
+        begin
+            parse-word
+            ?delim dup  to local-state
+        3 < while
+            local-state 0=  if 2drop endif
+        repeat
+    endif
+
+    local-state 3 <> abort" syntax error in { } local line"
+; immediate compile-only
+
+previous 
+[endif]
+
--- /dev/null
+++ b/softcore/make.bat
@@ -1,0 +1,22 @@
+@echo off
+
+if "%1" == "clean" goto CLEAN
+
+if exist makesoftcore.exe goto SKIPCL
+cl /Zi /Od makesoftcore.c ..\lzcompress.c ..\bit.c
+goto MAKESOFTCORE
+
+:SKIPCL
+echo makesoftcore.exe exists, skipping building it.
+
+:MAKESOFTCORE
+echo on
+makesoftcore softcore.fr ifbrack.fr prefix.fr ficl.fr jhlocal.fr marker.fr oo.fr classes.fr string.fr win32.fr ficllocal.fr fileaccess.fr
+goto EXIT
+
+:CLEAN
+del *.obj
+del makesoftcore.exe
+del ..\softcore.c
+
+:EXIT
--- /dev/null
+++ b/softcore/makefile
@@ -1,0 +1,11 @@
+SOURCES = softcore.fr ifbrack.fr prefix.fr ficl.fr jhlocal.fr marker.fr oo.fr classes.fr string.fr ficllocal.fr fileaccess.fr
+
+../softcore.c: makesoftcore $(SOURCES)
+	makesoftcore $(SOURCES)
+
+makesoftcore: makesoftcore.c ../lzcompress.c ../bit.c
+	cc  -o makesoftcore makesoftcore.c ../lzcompress.c ../bit.c
+
+clean: 
+	- rm ../softcore.c *.o makesoftcore
+
--- /dev/null
+++ b/softcore/makesoftcore.c
@@ -1,0 +1,239 @@
+/*
+** Ficl softcore generator.
+** Generates both uncompressed and Lempel-Ziv compressed versions.
+** Strips blank lines, strips full-line comments, collapses whitespace.
+** Chops, blends, dices, makes julienne fries.
+**
+** Contributed by Larry Hastings, larry@hastings.org
+**/
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "../ficl.h"
+
+
+void fprintDataAsHex(FILE *f, char *data, int length)
+	{
+	int i;
+	while (length)
+		{
+		fprintf(f, "\t");
+		for (i = 0; (i < 8) && length; i++)
+			{
+			char buf[16];
+			/* if you don't do this little stuff, you get ugly sign-extended 0xFFFFFF6b crap. */
+			sprintf(buf, "%08x", (unsigned int)*data++);
+			fprintf(f, "0x%s, ", buf + 6);
+			length--;
+			}
+		fprintf(f, "\n");
+		}
+	}
+
+void fprintDataAsQuotedString(FILE *f, char *data)
+	{
+	int i;
+	int lineIsBlank = FICL_TRUE;
+
+	while (*data)
+		{
+		if (*data == '\n')
+			{
+			if (!lineIsBlank)
+				fprintf(f, "\\n\"\n");
+			lineIsBlank = FICL_TRUE;
+			}
+		else
+			{
+			if (lineIsBlank)
+				{
+				fputc('\t', f);
+				fputc('"', f);
+				lineIsBlank = FICL_FALSE;
+				}
+
+			if (*data == '"')
+				fprintf(f, "\\\"");
+			else if (*data == '\\')
+				fprintf(f, "\\\\");
+			else
+				fputc(*data, f);
+			}
+		data++;
+		}
+	if (!lineIsBlank)
+		fprintf(f, "\"");
+	}
+
+int main(int argc, char *argv[])
+	{
+	char *uncompressed = (char *)malloc(128 * 1024);
+	char *compressed;
+	char *trace = uncompressed;
+	int i;
+	int compressedSize;
+	int uncompressedSize;
+	char *src, *dst;
+	FILE *f;
+	time_t currentTimeT;
+	struct tm *currentTime;
+	char cleverTime[32];
+
+	time(&currentTimeT);
+	currentTime = localtime(&currentTimeT);
+	strftime(cleverTime, sizeof(cleverTime), "%Y/%m/%d %H:%M:%S", currentTime);
+
+	*trace++ = ' ';
+
+	for (i = 1; i < argc; i++)
+		{
+		int size;
+		/*
+		** This ensures there's always whitespace space between files.   It *also*
+		** ensures that src[-1] is always safe in comment detection code below.
+		** (Any leading whitespace will be thrown away in a later pass.)
+		** --lch
+		*/
+		*trace++ = ' ';
+
+		f = fopen(argv[i], "rb");
+		fseek(f, 0, SEEK_END);
+		size = ftell(f);
+		fseek(f, 0, SEEK_SET);
+		fread(trace, 1, size, f);
+		fclose(f);
+		trace += size;
+		}
+	*trace = 0;
+	
+#define IS_EOL(x) ((*x == '\n') || (*x == '\r'))
+#define IS_EOL_COMMENT(x) (((x[0] == '\\') && isspace(x[1]))  || ((x[0] == '/') && (x[1] == '/') && isspace(x[2])))
+#define IS_BLOCK_COMMENT(x) ((x[0] == '(') && isspace(x[1]) && isspace(x[-1]))
+
+	src = dst = uncompressed;
+	while (*src)
+		{
+		/* ignore leading whitespace, or entirely blank lines */
+		while (isspace(*src))
+			src++;
+		/* if the line is commented out */
+		if (IS_EOL_COMMENT(src))
+			{
+			/* throw away this entire line */
+			while (*src && !IS_EOL(src))
+				src++;
+			continue;
+			}
+		/*
+		** This is where we'd throw away mid-line comments, but
+		** that's simply unsafe.  Things like
+		**      start-prefixes
+		**      : \ postpone \ ;
+		**      : ( postpone ( ;
+		** get broken that way.
+		** --lch
+		*/
+		while (*src && !IS_EOL(src))
+		{
+			*dst++ = *src++;
+		}
+
+		/* strip trailing whitespace */
+		dst--;
+		while (isspace(*dst))
+			dst--;
+		dst++;
+
+		/* and end the line */
+		*dst++ = '\n';
+		}
+
+	*dst = 0;
+
+	/* now make a second pass to collapse all contiguous whitespace to a single space. */
+	src = dst = uncompressed;
+	while (*src)
+	{
+		*dst++ = *src;
+		if (!isspace(*src))
+			src++;
+		else
+		{
+			while (isspace(*src))
+				src++;
+		}
+	}
+	*dst = 0;
+
+	f = fopen("../softcore.c", "wt");
+	if (f == NULL)
+		{
+		printf("couldn't open ../softcore.c for writing!  giving up.\n");
+		exit(-1);
+		}
+
+	fprintf(f,
+"/*\n"
+"** Ficl softcore\n"
+"** both uncompressed and Lempel-Ziv compressed versions.\n"
+"**\n"
+"** Generated %s\n"
+"**/\n"
+"\n"
+"#include \"ficl.h\"\n"
+"\n"
+"\n",
+	cleverTime);
+	
+	uncompressedSize = dst - uncompressed;
+	ficlLzCompress(uncompressed, uncompressedSize, &compressed, &compressedSize);
+
+	fprintf(f, "static size_t ficlSoftcoreUncompressedSize = %d; /* not including trailing null */\n", uncompressedSize);
+	fprintf(f, "\n");
+	fprintf(f, "#if !FICL_WANT_LZ_SOFTCORE\n");
+	fprintf(f, "\n");
+	fprintf(f, "static char ficlSoftcoreUncompressed[] =\n");
+	fprintDataAsQuotedString(f, uncompressed);
+	fprintf(f, ";\n");
+	fprintf(f, "\n");
+	fprintf(f, "#else /* !FICL_WANT_LZ_SOFTCORE */\n");
+	fprintf(f, "\n");
+	fprintf(f, "static unsigned char ficlSoftcoreCompressed[%d] = {\n", compressedSize);
+	fprintDataAsHex(f, compressed, compressedSize);
+	fprintf(f, "\t};\n");
+	fprintf(f, "\n");
+	fprintf(f, "#endif /* !FICL_WANT_LZ_SOFTCORE */\n");
+	fprintf(f,
+"\n"
+"\n"
+"void ficlSystemCompileSoftCore(ficlSystem *system)\n"
+"{\n"
+"    ficlVm *vm = system->vmList;\n"
+"    int returnValue;\n"
+"    ficlCell oldSourceID = vm->sourceId;\n"
+"    ficlString s;\n"
+"#if FICL_WANT_LZ_SOFTCORE\n"
+"    char *ficlSoftcoreUncompressed = NULL;\n"
+"    size_t gotUncompressedSize = 0;\n"
+"    returnValue = ficlLzUncompress(ficlSoftcoreCompressed, (unsigned char **)&ficlSoftcoreUncompressed, &gotUncompressedSize);\n"
+"    FICL_VM_ASSERT(vm, returnValue == 0);\n"
+"    FICL_VM_ASSERT(vm, gotUncompressedSize == ficlSoftcoreUncompressedSize);\n"
+"#endif /* FICL_WANT_LZ_SOFTCORE */\n"
+"    vm->sourceId.i = -1;\n"
+"    FICL_STRING_SET_POINTER(s, (char *)(ficlSoftcoreUncompressed));\n"
+"    FICL_STRING_SET_LENGTH(s, ficlSoftcoreUncompressedSize);\n" 
+"    returnValue = ficlVmExecuteString(vm, s);\n"
+"    vm->sourceId = oldSourceID;\n"
+"#if FICL_WANT_LZ_SOFTCORE\n"
+"    free(ficlSoftcoreUncompressed);\n"
+"#endif /* FICL_WANT_LZ_SOFTCORE */\n"
+"    FICL_VM_ASSERT(vm, returnValue != FICL_VM_STATUS_ERROR_EXIT);\n"
+"    return;\n"
+"}\n"
+"\n"
+"/* end-of-file */\n"
+		);
+	free(uncompressed);
+	free(compressed);
+	}
--- /dev/null
+++ b/softcore/marker.fr
@@ -1,0 +1,25 @@
+\ ** ficl/softwords/marker.fr
+\ ** Ficl implementation of CORE EXT MARKER
+\ John Sadler, 4 Oct 98
+\ Requires ficl 2.02 FORGET-WID !!
+.( loading MARKER ) cr
+: marker   ( "name" -- )
+    create  
+    get-current ,
+    get-order dup , 
+    0 ?do , loop 
+  does>
+    0 set-order                     \ clear search order
+    dup body> >name drop 
+    here - allot                    \ reset HERE to my xt-addr
+    dup @                           ( pfa current-wid )
+    dup set-current forget-wid      ( pfa )
+    cell+ dup @ swap                ( count count-addr )
+    over cells + swap               ( last-wid-addr count )
+    0 ?do 
+        dup @ dup                   ( wid-addr wid wid )
+        >search forget-wid          ( wid-addr )
+        cell- 
+    loop
+    drop
+;
--- /dev/null
+++ b/softcore/oo.fr
@@ -1,0 +1,700 @@
+S" FICL_WANT_OOP" ENVIRONMENT? drop [if]
+\ ** ficl/softwords/oo.fr
+\ ** F I C L   O - O   E X T E N S I O N S
+\ ** john sadler aug 1998
+
+.( loading ficl O-O extensions ) cr
+17 ficl-vocabulary oop
+also oop definitions
+
+\ Design goals:
+\ 0. Traditional OOP: late binding by default for safety. 
+\    Early binding if you ask for it.
+\ 1. Single inheritance
+\ 2. Object aggregation (has-a relationship)
+\ 3. Support objects in the dictionary and as proxies for 
+\    existing structures (by reference):
+\    *** A ficl object can wrap a C struct ***
+\ 4. Separate name-spaces for methods - methods are
+\    only visible in the context of a class / object
+\ 5. Methods can be overridden, and subclasses can add methods.
+\    No limit on number of methods.
+
+\ General info:
+\ Classes are objects, too: all classes are instances of METACLASS
+\ All classes are derived (by convention) from OBJECT. This
+\ base class provides a default initializer and superclass 
+\ access method
+
+\ A ficl object binds instance storage (payload) to a class.
+\ object  ( -- instance class )
+\ All objects push their payload address and class address when
+\ executed. 
+
+\ A ficl class consists of a parent class pointer, a wordlist
+\ ID for the methods of the class, and a size for the payload
+\ of objects created by the class. A class is an object.
+\ The NEW method creates and initializes an instance of a class.
+\ Classes have this footprint:
+\ cell 0: parent class address
+\ cell 1: wordlist ID
+\ cell 2: size of instance's payload
+
+\ Methods expect an object couple ( instance class ) 
+\ on the stack. This is by convention - ficl has no way to 
+\ police your code to make sure this is always done, but it 
+\ happens naturally if you use the facilities presented here.
+\
+\ Overridden methods must maintain the same stack signature as
+\ their predecessors. Ficl has no way of enforcing this, either.
+\
+\ Revised Apr 2001 - Added Guy Carver's vtable extensions. Class now
+\ has an extra field for the vtable method count. Hasvtable declares
+\ refs to vtable classes
+\
+\ Revised Nov 2001 - metaclass debug method now finds only metaclass methods
+\
+\ Planned: Ficl vtable support
+\ Each class has a vtable size parameter
+\ END-CLASS allocates and clears the vtable - then it walks class's method 
+\ list and inserts all new methods into table. For each method, if the table
+\ slot is already nonzero, do nothing (overridden method). Otherwise fill
+\ vtable slot. Now do same check for parent class vtable, filling only
+\ empty slots in the new vtable.
+\ Methods are now structured as follows:
+\ - header
+\ - vtable index
+\ - xt
+\ :noname definition for code
+\
+\ : is redefined to check for override, fill in vtable index, increment method
+\ count if not an override, create header and fill in index. Allot code pointer
+\ and run :noname
+\ ; is overridden to fill in xt returned by :noname
+\ --> compiles code to fetch vtable address, offset by index, and execute
+\ => looks up xt in the vtable and compiles it directly
+
+
+
+user current-class
+0 current-class !
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+\ ** L A T E   B I N D I N G
+\ Compile the method name, and code to find and
+\ execute it at run-time...
+\
+
+\ p a r s e - m e t h o d
+\ compiles a method name so that it pushes
+\ the string base address and count at run-time.
+
+: parse-method  \ name  run: ( -- c-addr u )
+    parse-word
+    postpone sliteral
+; compile-only
+
+
+
+: (lookup-method)  { class 2:name -- class 0 | class xt 1 | class xt -1  }
+    class  name class cell+ @  ( class c-addr u wid )
+    search-wordlist
+;
+
+\ l o o k u p - m e t h o d
+\ takes a counted string method name from the stack (as compiled
+\ by parse-method) and attempts to look this method up in the method list of 
+\ the class that's on the stack. If successful, it leaves the class on the stack
+\ and pushes the xt of the method. If not, it aborts with an error message.
+
+: lookup-method  { class 2:name -- class xt }
+    class name (lookup-method)    ( 0 | xt 1 | xt -1 )
+    0= if
+        name type ."  not found in " 
+        class body> >name type
+        cr abort 
+    endif 
+;
+
+: find-method-xt   \ name ( class -- class xt )
+    parse-word lookup-method
+;
+
+: catch-method  ( instance class c-addr u -- <method-signature> exc-flag )
+    lookup-method catch
+;
+
+: exec-method  ( instance class c-addr u -- <method-signature> )
+    lookup-method execute
+;
+
+\ Method lookup operator takes a class-addr and instance-addr
+\ and executes the method from the class's wordlist if
+\ interpreting. If compiling, bind late.
+\
+: -->   ( instance class -- ??? )
+    state @ 0= if
+        find-method-xt execute 
+    else  
+        parse-method  postpone exec-method
+    endif
+; immediate
+
+\ Method lookup with CATCH in case of exceptions
+: c->   ( instance class -- ?? exc-flag )
+    state @ 0= if
+        find-method-xt catch  
+    else  
+        parse-method  postpone catch-method
+    endif
+; immediate
+
+\ METHOD  makes global words that do method invocations by late binding
+\ in case you prefer this style (no --> in your code)
+\ Example: everything has next and prev for array access, so...
+\ method next
+\ method prev
+\ my-instance next ( does whatever next does to my-instance by late binding )
+
+: method   create does> body> >name lookup-method execute ;
+
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+\ ** E A R L Y   B I N D I N G
+\ Early binding operator compiles code to execute a method
+\ given its class at compile time. Classes are immediate,
+\ so they leave their cell-pair on the stack when compiling.
+\ Example: 
+\   : get-wid   metaclass => .wid @ ;
+\ Usage
+\   my-class get-wid  ( -- wid-of-my-class )
+\
+1 ficl-named-wordlist instance-vars
+instance-vars dup >search ficl-set-current
+
+: =>   \ c:( class meta -- ) run: ( -- ??? ) invokes compiled method
+    drop find-method-xt compile, drop
+; immediate compile-only
+
+: my=>   \ c:( -- ) run: ( -- ??? ) late bind compiled method of current-class
+    current-class @ dup postpone =>
+; immediate compile-only
+
+\ Problem: my=[ assumes that each method except the last is an obj: member
+\ which contains its class as the first field of its parameter area. The code
+\ detects non-obect members and assumes the class does not change in this case.
+\ This handles methods like index, prev, and next correctly, but does not deal
+\ correctly with CLASS.
+: my=[   \ same as my=> , but binds a chain of methods
+    current-class @  
+    begin 
+        parse-word 2dup             ( class c-addr u c-addr u )
+        s" ]" compare while         ( class c-addr u )
+        lookup-method               ( class xt )
+        dup compile,                ( class xt )
+        dup ?object if        \ If object member, get new class. Otherwise assume same class
+           nip >body cell+ @        ( new-class )
+        else 
+           drop                     ( class )
+        endif
+    repeat 2drop drop 
+; immediate compile-only
+
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+\ ** I N S T A N C E   V A R I A B L E S
+\ Instance variables (IV) are represented by words in the class's
+\ private wordlist. Each IV word contains the offset
+\ of the IV it represents, and runs code to add that offset
+\ to the base address of an instance when executed.
+\ The metaclass SUB method, defined below, leaves the address
+\ of the new class's offset field and its initial size on the
+\ stack for these words to update. When a class definition is
+\ complete, END-CLASS saves the final size in the class's size
+\ field, and restores the search order and compile wordlist to
+\ prior state. Note that these words are hidden in their own
+\ wordlist to prevent accidental use outside a SUB END-CLASS pair.
+\
+: do-instance-var
+    does>   ( instance class addr[offset] -- addr[field] )
+        nip @ +
+;
+
+: addr-units:  ( offset size "name" -- offset' )
+    create over , + 
+    do-instance-var
+;
+
+: chars:    \ ( offset nCells "name" -- offset' ) Create n char member.
+   chars addr-units: ;
+
+: char:     \ ( offset nCells "name" -- offset' ) Create 1 char member.
+   1 chars: ;
+
+: cells:  ( offset nCells "name" -- offset' )
+    cells >r aligned r> addr-units:
+;
+
+: cell:   ( offset nCells "name" -- offset' )
+    1 cells: ;
+
+\ Aggregate an object into the class...
+\ Needs the class of the instance to create
+\ Example: object obj: m_obj
+\
+: do-aggregate
+    objectify
+    does>   ( instance class pfa -- a-instance a-class )
+    2@          ( inst class a-class a-offset )
+    2swap drop  ( a-class a-offset inst )
+    + swap      ( a-inst a-class )
+;
+
+: obj:   { offset class meta -- offset' }  \ "name" 
+    create  offset , class , 
+    class meta --> get-size  offset +
+    do-aggregate
+;
+
+\ Aggregate an array of objects into a class
+\ Usage example:
+\ 3 my-class array: my-array
+\ Makes an instance variable array of 3 instances of my-class
+\ named my-array.
+\
+: array:   ( offset n class meta "name" -- offset' )
+    locals| meta class nobjs offset |
+    create offset , class , 
+    class meta --> get-size  nobjs * offset + 
+    do-aggregate
+;
+
+\ Aggregate a pointer to an object: REF is a member variable
+\ whose class is set at compile time. This is useful for wrapping
+\ data structures in C, where there is only a pointer and the type
+\ it refers to is known. If you want polymorphism, see c_ref
+\ in classes.fr. REF is only useful for pre-initialized structures,
+\ since there's no supported way to set one.
+: ref:   ( offset class meta "name" -- offset' )
+    locals| meta class offset |
+    create offset , class ,
+    offset cell+
+    does>    ( inst class pfa -- ptr-inst ptr-class )
+    2@       ( inst class ptr-class ptr-offset )
+    2swap drop + @ swap
+;
+
+S" FICL_WANT_VCALL" ENVIRONMENT? drop [if]
+\ vcall extensions contributed by Guy Carver
+: vcall:  ( paramcnt "name" -- )   
+    current-class @ 8 + dup @ dup 1+ rot !  \ Kludge fix to get to .vtCount before it's defined.
+    create , ,                              \ ( paramcnt index -- )
+    does>                                   \ ( inst class pfa -- ptr-inst ptr-class )
+   nip 2@ vcall                             \ ( params offset inst class offset -- )
+;
+
+: vcallr: 0x80000000 or vcall: ;            \ Call with return address desired.
+
+S" FICL_WANT_FLOAT" ENVIRONMENT? drop [if]
+: vcallf:                                   \ ( paramcnt -<name>- f: r )
+    0x80000000 or 
+    current-class @ 8 + dup @ dup 1+ rot !  \ Kludge fix to get to .vtCount before it's defined.
+    create , ,                              \ ( paramcnt index -- )
+    does>                                   \ ( inst class pfa -- ptr-inst ptr-class )
+    nip 2@ vcall f>                         \ ( params offset inst class offset -- f: r )
+;
+
+[endif] \ FICL_WANT_FLOAT
+[endif] \ FICL_WANT_VCALL
+
+\ END-CLASS terminates construction of a class by storing
+\  the size of its instance variables in the class's size field
+\ ( -- old-wid addr[size] 0 )
+\
+: end-class  ( old-wid addr[size] size -- )
+    swap ! set-current 
+    search> drop        \ pop struct builder wordlist
+;
+
+\ See resume-class (a metaclass method) below for usage
+\ This is equivalent to end-class for now, but that will change
+\ when we support vtable bindings.
+: suspend-class  ( old-wid addr[size] size -- )   end-class ;
+
+set-current previous
+\ E N D   I N S T A N C E   V A R I A B L E S
+
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+\ D O - D O - I N S T A N C E
+\ Makes a class method that contains the code for an 
+\ instance of the class. This word gets compiled into
+\ the wordlist of every class by the SUB method.
+\ PRECONDITION: current-class contains the class address
+\ why use a state variable instead of the stack?
+\ >> Stack state is not well-defined during compilation (there are
+\ >> control structure match codes on the stack, of undefined size
+\ >> easiest way around this is use of this thread-local variable
+\
+: do-do-instance  ( -- )
+    s" : .do-instance does> [ current-class @ ] literal ;" 
+    evaluate 
+;
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+\ ** M E T A C L A S S 
+\ Every class is an instance of metaclass. This lets
+\ classes have methods that are different from those
+\ of their instances.
+\ Classes are IMMEDIATE to make early binding simpler
+\ See above...
+\
+:noname
+    wordlist
+    create  
+    immediate
+    0       ,   \ NULL parent class
+    dup     ,   \ wid
+[ S" FICL_WANT_VCALL" ENVIRONMENT? drop ] [if]
+    4 cells ,   \ instance size 
+[else]
+    3 cells ,   \ instance size 
+[endif]
+    ficl-set-current
+    does> dup
+;  execute metaclass 
+\ now brand OBJECT's wordlist (so that ORDER can display it by name)
+metaclass drop cell+ @ brand-wordlist
+
+metaclass drop current-class !
+do-do-instance
+
+\
+\ C L A S S   M E T H O D S
+\
+instance-vars >search
+
+create .super  ( class metaclass -- parent-class )
+    0 cells , do-instance-var 
+
+create .wid    ( class metaclass -- wid ) \ return wid of class
+    1 cells , do-instance-var 
+
+S" FICL_WANT_VCALL" ENVIRONMENT? drop [if]
+create .vtCount   \ Number of VTABLE methods, if any
+    2 cells , do-instance-var 
+
+create  .size  ( class metaclass -- size ) \ return class's payload size 
+    3 cells , do-instance-var 
+
+[else]
+
+create  .size  ( class metaclass -- size ) \ return class's payload size 
+    2 cells , do-instance-var 
+
+[endif]
+
+: get-size    metaclass => .size  @ ;
+: get-wid     metaclass => .wid   @ ;
+: get-super   metaclass => .super @ ;
+S" FICL_WANT_VCALL" ENVIRONMENT? drop [if]
+: get-vtCount metaclass => .vtCount @ ;
+: get-vtAdd   metaclass => .vtCount ;
+[endif]
+
+\ create an uninitialized instance of a class, leaving
+\ the address of the new instance and its class
+\
+: instance   ( class metaclass "name" -- instance class )
+    locals| meta parent |
+    create
+    here parent --> .do-instance \ ( inst class )
+    parent meta metaclass => get-size 
+    allot                        \ allocate payload space
+;
+
+\ create an uninitialized array
+: array   ( n class metaclass "name" -- n instance class ) 
+    locals| meta parent nobj |
+    create  nobj
+    here parent --> .do-instance \ ( nobj inst class )
+    parent meta metaclass => get-size
+    nobj *  allot           \ allocate payload space
+;
+
+\ create an initialized instance
+\
+: new   \ ( class metaclass "name" -- ) 
+    metaclass => instance --> init
+;
+
+\ create an initialized array of instances
+: new-array   ( n class metaclass "name" -- ) 
+    metaclass => array 
+    --> array-init
+;
+
+\ Create an anonymous initialized instance from the heap
+: alloc   \ ( class metaclass -- instance class )
+    locals| meta class |
+    class meta metaclass => get-size allocate   ( -- addr fail-flag )
+    abort" allocate failed "                    ( -- addr )
+    class 2dup --> init
+;
+
+\ Create an anonymous array of initialized instances from the heap
+: alloc-array   \ ( n class metaclass -- instance class )
+    locals| meta class nobj |
+    class meta metaclass => get-size 
+    nobj * allocate                 ( -- addr fail-flag )
+    abort" allocate failed "        ( -- addr )
+    nobj over class --> array-init
+    class 
+;
+
+\ Create an anonymous initialized instance from the dictionary
+: allot   { 2:this -- 2:instance }
+    here   ( instance-address )
+    this my=> get-size  allot
+    this drop 2dup --> init
+;
+
+\ Create an anonymous array of initialized instances from the dictionary
+: allot-array   { nobj 2:this -- 2:instance }
+    here   ( instance-address )
+    this my=> get-size  nobj * allot
+    this drop 2dup     ( 2instance 2instance )
+    nobj -rot --> array-init
+;
+
+\ create a proxy object with initialized payload address given
+: ref   ( instance-addr class metaclass "name" -- )
+    drop create , ,
+    does> 2@ 
+;
+
+\ suspend-class and resume-class help to build mutually referent classes.
+\ Example: 
+\ object subclass c-akbar
+\ suspend-class   ( put akbar on hold while we define jeff )
+\ object subclass c-jeff
+\     c-akbar ref: .akbar
+\     ( and whatever else comprises this class )
+\ end-class    ( done with c-jeff )
+\ c-akbar --> resume-class
+\     c-jeff ref: .jeff
+\     ( and whatever else goes in c-akbar )
+\ end-class    ( done with c-akbar )
+\
+: resume-class   { 2:this -- old-wid addr[size] size }
+    this --> .wid @ ficl-set-current  ( old-wid )
+    this --> .size dup @   ( old-wid addr[size] size )
+    instance-vars >search
+;
+
+\ create a subclass
+\ This method leaves the stack and search order ready for instance variable
+\ building. Pushes the instance-vars wordlist onto the search order,
+\ and sets the compilation wordlist to be the private wordlist of the
+\ new class. The class's wordlist is deliberately NOT in the search order -
+\ to prevent methods from getting used with wrong data.
+\ Postcondition: leaves the address of the new class in current-class
+: sub   ( class metaclass "name" -- old-wid addr[size] size )
+    wordlist
+    locals| wid meta parent |
+    parent meta metaclass => get-wid
+    wid wid-set-super       \ set superclass
+    create  immediate       \ get the  subclass name
+    wid brand-wordlist      \ label the subclass wordlist
+    here current-class !    \ prep for do-do-instance
+    parent ,                \ save parent class
+    wid    ,                \ save wid
+[ S" FICL_WANT_VCALL" ENVIRONMENT? drop ] [if]
+    parent meta --> get-vtCount , 
+[endif]
+    here parent meta --> get-size dup ,  ( addr[size] size )
+    metaclass => .do-instance
+    wid ficl-set-current -rot
+    do-do-instance
+    instance-vars >search \ push struct builder wordlist
+;
+
+\ OFFSET-OF returns the offset of an instance variable
+\ from the instance base address. If the next token is not
+\ the name of in instance variable method, you get garbage
+\ results -- there is no way at present to check for this error.
+: offset-of   ( class metaclass "name" -- offset )
+    drop find-method-xt nip >body @ ;
+
+\ ID returns the string name cell-pair of its class
+: id   ( class metaclass -- c-addr u )
+    drop body> >name  ;
+
+\ list methods of the class
+: methods \ ( class meta -- ) 
+    locals| meta class |
+    begin
+        class body> >name type ."  methods:" cr 
+        class meta --> get-wid >search words cr previous 
+        class meta metaclass => get-super
+        dup to class
+    0= until  cr
+;
+
+\ list class's ancestors
+: pedigree  ( class meta -- )
+    locals| meta class |
+    begin
+        class body> >name type space
+        class meta metaclass => get-super
+        dup to class
+    0= until  cr
+;
+
+\ decompile an instance method
+: see  ( class meta -- )   
+    metaclass => get-wid >search see previous ;
+
+\ debug a method of metaclass
+\ Eg: my-class --> debug my-method
+: debug  ( class meta -- )
+	find-method-xt debug-xt ;
+
+previous set-current    
+\ E N D   M E T A C L A S S
+
+\ ** META is a nickname for the address of METACLASS...
+metaclass drop  
+constant meta
+
+\ ** SUBCLASS is a nickname for a class's SUB method...
+\ Subclass compilation ends when you invoke end-class
+\ This method is late bound for safety...
+: subclass   --> sub ;
+
+S" FICL_WANT_VCALL" ENVIRONMENT? drop [if]
+\ VTABLE Support extensions (Guy Carver)
+\ object --> sub mine hasvtable
+: hasvtable 4 + ; immediate
+[endif]
+
+
+\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+\ ** O B J E C T
+\ Root of all classes
+:noname
+    wordlist
+    create  immediate
+    0       ,   \ NULL parent class
+    dup     ,   \ wid
+    0       ,   \ instance size 
+[ S" FICL_WANT_VCALL" ENVIRONMENT? drop ] [if]
+    0       ,   \ .vtCount
+[endif]
+    ficl-set-current
+    does> meta
+;  execute object
+\ now brand OBJECT's wordlist (so that ORDER can display it by name)
+object drop cell+ @ brand-wordlist
+
+object drop current-class ! 
+do-do-instance
+instance-vars >search
+
+\ O B J E C T   M E T H O D S
+\ Convert instance cell-pair to class cell-pair
+\ Useful for binding class methods from an instance
+: class  ( instance class -- class metaclass )
+    nip meta ;
+
+\ default INIT method zero fills an instance
+: init   ( instance class -- )
+    meta 
+    metaclass => get-size   ( inst size )
+    erase ;
+
+\ Apply INIT to an array of NOBJ objects...
+\
+: array-init   ( nobj inst class -- )
+    0 dup locals| &init &next class inst |
+    \
+    \ bind methods outside the loop to save time
+    \
+    class s" init" lookup-method to &init
+          s" next" lookup-method to &next
+    drop
+    0 ?do 
+        inst class 2dup 
+        &init execute
+        &next execute  drop to inst
+    loop
+;
+
+\ free storage allocated to a heap instance by alloc or alloc-array
+\ NOTE: not protected against errors like FREEing something that's
+\ really in the dictionary.
+: free   \ ( instance class -- )
+    drop free 
+    abort" free failed "
+;
+
+\ Instance aliases for common class methods
+\ Upcast to parent class
+: super     ( instance class -- instance parent-class )
+    meta  metaclass => get-super ;
+
+: pedigree  ( instance class -- )
+    object => class 
+    metaclass => pedigree ;
+
+: size      ( instance class -- sizeof-instance )
+    object => class 
+    metaclass => get-size ;
+
+: methods   ( instance class -- )
+    object => class 
+    metaclass => methods ;
+
+\ Array indexing methods...
+\ Usage examples:
+\ 10 object-array --> index
+\ obj --> next
+\
+: index   ( n instance class -- instance[n] class )
+    locals| class inst |
+    inst class 
+    object => class
+    metaclass => get-size  *   ( n*size )
+    inst +  class ;
+
+: next   ( instance[n] class -- instance[n+1] class )
+    locals| class inst |
+    inst class 
+    object => class
+    metaclass => get-size 
+    inst +
+    class ;
+
+: prev   ( instance[n] class -- instance[n-1] class )
+    locals| class inst |
+    inst class 
+    object => class
+    metaclass => get-size
+    inst swap -
+    class ;
+
+: debug   ( 2this --  ?? )
+    find-method-xt debug-xt ;
+
+previous set-current
+\ E N D   O B J E C T
+
+\ reset to default search order
+only definitions
+
+\ redefine oop in default search order to put OOP words in the search order and make them
+\ the compiling wordlist...
+
+: oo   only also oop definitions ;
+
+[endif]
--- /dev/null
+++ b/softcore/prefix.fr
@@ -1,0 +1,47 @@
+\ ** 
+\ ** Prefix words for ficl
+\ ** submitted by Larry Hastings, larry@hastings.org
+\ **
+\ (jws) To make a prefix, simply create a new definition in the <prefixes> 
+\ wordlist. start-prefixes and end-prefixes handle the bookkeeping
+
+variable save-current
+
+: start-prefixes   get-current save-current ! <prefixes> set-current ;
+: end-prefixes     save-current @ set-current ;
+: show-prefixes    <prefixes> >search  words  search> drop ;
+
+start-prefixes
+
+S" FICL_WANT_EXTENDED_PREFIX" ENVIRONMENT? drop [if]
+
+\ define " (double-quote) as an alias for s", and make it a prefix
+: " postpone s" ; immediate
+
+
+\ make .( a prefix (we just create an alias for it in the prefixes list)
+: .( postpone .( ; immediate
+
+
+\ make \ a prefix, and add // (same thing) as a prefix too
+: \ postpone \ ; immediate
+: // postpone \ ; immediate
+
+
+\ ** add 0b, 0o, 0d, and 0x as prefixes 
+\ ** these temporarily shift the base to 2, 8, 10, and 16 respectively
+\ ** and consume the next number in the input stream, pushing/compiling
+\ ** as normal
+\ **
+\ ** __tempbase is precompiled, see prefix.c
+
+: 0b  2 __tempbase ; immediate
+: 0o  8 __tempbase ; immediate
+
+[endif]
+
+: 0d 10 __tempbase ; immediate
+: 0x 16 __tempbase ; immediate
+
+end-prefixes
+
--- /dev/null
+++ b/softcore/softcore.fr
@@ -1,0 +1,152 @@
+\ ** ficl/softwords/softcore.fr
+\ ** FICL soft extensions
+\ ** John Sadler (john_sadler@alum.mit.edu)
+\ ** September, 1998
+
+
+\ ** ficl extras
+\ EMPTY cleans the parameter stack
+: empty   ( xn..x1 -- ) depth 0 ?do drop loop ;
+\ CELL- undoes CELL+
+: cell-   ( addr -- addr )  [ 1 cells ] literal -  ;
+: -rot   ( a b c -- c a b )  2 -roll ;
+
+\ ** CORE 
+: abs   ( x -- x )
+    dup 0< if negate endif ;
+decimal 32 constant bl
+
+: space   ( -- )     bl emit ;
+
+: spaces  ( n -- )   0 ?do space loop ;
+
+: abort"  
+    state @ if
+        postpone if
+        postpone ."
+        postpone cr
+        -2
+        postpone literal
+        postpone throw
+        postpone endif
+    else
+	    [char] " parse
+        rot if
+            type
+            cr
+            -2 throw
+        else
+            2drop
+        endif
+    endif
+; immediate
+
+
+\ ** CORE EXT
+.( loading CORE EXT words ) cr
+0  constant false 
+false invert constant true 
+: <>   = 0= ; 
+: 0<>  0= 0= ; 
+: compile,  , ; 
+: convert   char+ 65535 >number drop ;  \ cribbed from DPANS A.6.2.0970
+: erase   ( addr u -- )    0 fill ; 
+variable span
+: expect  ( c-addr u1 -- ) accept span ! ;
+\ see marker.fr for MARKER implementation
+: nip     ( y x -- x )     swap drop ; 
+: tuck    ( y x -- x y x)  swap over ; 
+: within  ( test low high -- flag )   over - >r - r>  u<  ;
+
+
+
+\ ** TOOLS word set...
+: ?     ( addr -- )  @ . ;
+: dump  ( addr u -- )
+    0 ?do
+        dup c@ . 1+
+        i 7 and 7 = if cr endif
+    loop drop
+;
+
+\ ** SEARCH+EXT words and ficl helpers
+.( loading SEARCH & SEARCH-EXT words ) cr 
+\ BRAND-WORDLIST is a helper for ficl-named-wordlist. Usage idiom:
+\   wordlist dup create , brand-wordlist
+\ gets the name of the word made by create and applies it to the wordlist...
+: brand-wordlist  ( wid -- )   last-word >name drop wid-set-name ;
+
+: ficl-named-wordlist  \ ( hash-size name -- ) run: ( -- wid )
+    ficl-wordlist dup create , brand-wordlist does> @ ;
+
+: wordlist   ( -- )  
+    1 ficl-wordlist ;
+
+\ FICL-SET-CURRENT sets the compile wordlist and pushes the previous value
+: ficl-set-current   ( wid -- old-wid )  
+    get-current swap set-current ; 
+
+\ DO_VOCABULARY handles the DOES> part of a VOCABULARY
+\ When executed, new voc replaces top of search stack
+: do-vocabulary   ( -- ) 
+    does>  @ search> drop >search ;
+
+: ficl-vocabulary   ( nBuckets name -- )  
+    ficl-named-wordlist do-vocabulary ; 
+
+: vocabulary   ( name -- )  
+    1 ficl-vocabulary ; 
+
+\ PREVIOUS drops the search order stack
+: previous  ( --  )  search> drop ; 
+
+\ HIDDEN vocabulary is a place to keep helper words from cluttering the namespace
+\ USAGE:
+\ hide
+\ <definitions to hide>
+\ set-current
+\ <words that use hidden defs>
+\ previous ( pop HIDDEN off the search order )
+
+1 ficl-named-wordlist hidden
+: hide     hidden dup >search ficl-set-current ;
+
+\ ALSO dups the search stack...
+: also   ( -- )  
+    search> dup >search >search ; 
+
+\ FORTH drops the top of the search stack and pushes FORTH-WORDLIST
+: forth   ( -- )  
+    search> drop  
+    forth-wordlist >search ; 
+
+\ ONLY sets the search order to a default state
+: only   ( -- )  
+    -1 set-order ; 
+
+\ ORDER displays the compile wid and the search order list
+hide
+: list-wid ( wid -- )   
+    dup wid-get-name   ( wid c-addr u )
+    ?dup if 
+        type drop 
+    else 
+        drop ." (unnamed wid) " x.
+    endif cr 
+; 
+set-current   \ stop hiding words
+
+: order   ( -- )  
+    ." Search:" cr
+    get-order  0 ?do 3 spaces list-wid loop cr 
+   ." Compile: " get-current list-wid cr  
+; 
+
+: debug  ' debug-xt ; immediate
+: on-step   ." S: " .s-simple cr ;
+
+
+previous   \ lose hidden words from search order
+
+\ ** E N D   S O F T C O R E . F R
+
--- /dev/null
+++ b/softcore/string.fr
@@ -1,0 +1,149 @@
+S" FICL_WANT_OOP" ENVIRONMENT? drop [if]
+\ ** ficl/softwords/string.fr
+\ A useful dynamic string class
+\ John Sadler 14 Sep 1998
+\
+\ ** C - S T R I N G
+\ counted string, buffer sized dynamically
+\ Creation example:
+\   c-string --> new str
+\   s" arf arf!!" str --> set
+\   s" woof woof woof " str --> cat
+\   str --> type  cr
+\
+
+.( loading ficl string class ) cr
+also oop definitions
+
+object subclass c-string
+    c-cell obj: .count
+    c-cell obj: .buflen
+    c-ptr  obj: .buf
+    32 constant min-buf
+
+    : get-count   ( 2:this -- count )  my=[ .count  get ] ;
+    : set-count   ( count 2:this -- )  my=[ .count  set ] ;
+
+    : ?empty   ( 2:this -- flag )  --> get-count 0= ;
+
+    : get-buflen   ( 2:this -- len )  my=[ .buflen  get ] ;
+    : set-buflen   ( len 2:this -- )  my=[ .buflen  set ] ;
+
+    : get-buf   ( 2:this -- ptr )     my=[ .buf get-ptr ] ;
+    : set-buf   { ptr len 2:this -- }  
+        ptr this my=[ .buf set-ptr ]
+        len this my=> set-buflen 
+    ;
+
+    \ set buffer to null and buflen to zero
+    : clr-buf   ( 2:this -- )
+        0 0 2over  my=> set-buf 
+        0 -rot     my=> set-count
+    ;
+
+    \ free the buffer if there is one, set buf pointer to null
+    : free-buf   { 2:this -- }
+        this my=> get-buf 
+        ?dup if 
+            free 
+			abort" c-string free failed"
+			this  my=> clr-buf
+        endif
+    ;
+
+    \ guarantee buffer is large enough to hold size chars
+    : size-buf  { size 2:this -- }
+        size 0< abort" need positive size for size-buf"
+        size 0= if 
+            this --> free-buf exit
+        endif
+
+        \ force buflen to be a positive multiple of min-buf chars
+        my=> min-buf size over / 1+ * chars to size
+
+        \ if buffer is null, allocate one, else resize it
+        this --> get-buflen  0= 
+        if
+            size allocate 
+            abort" out of memory"
+            size this --> set-buf
+            size this --> set-buflen
+            exit
+        endif
+
+        size this --> get-buflen > if
+            this --> get-buf size resize
+            abort" out of memory"
+            size this --> set-buf
+        endif
+    ;
+
+    : set   { c-addr u 2:this -- }
+        u this --> size-buf
+        u this --> set-count
+        c-addr this --> get-buf  u move  
+    ;
+
+    : get   { 2:this -- c-addr u }
+        this --> get-buf
+        this --> get-count
+    ;
+
+    \ append string to existing one
+    : cat   { c-addr u 2:this -- }
+        this --> get-count u +  dup >r
+        this --> size-buf
+        c-addr  this --> get-buf this --> get-count +  u move
+        r> this --> set-count
+    ;
+
+    : type   { 2:this -- }
+	    this --> ?empty if ." (empty) " exit endif
+        this --> .buf --> get-ptr 
+        this --> .count --> get 
+        type  
+    ;
+
+    : compare   ( 2string 2:this -- n )
+        --> get 
+        2swap 
+        --> get 
+        2swap compare
+    ;
+
+    : hashcode   ( 2:this -- hashcode )
+        --> get  hash
+    ;
+
+    \ destructor method (overrides object --> free) 
+    : free   ( 2:this -- )  2dup --> free-buf  object => free ;
+
+end-class
+
+c-string subclass c-hashstring
+    c-2byte obj: .hashcode
+
+    : set-hashcode   { 2:this -- }
+        this  --> super --> hashcode 
+        this  --> .hashcode --> set
+    ;
+
+    : get-hashcode   ( 2:this -- hashcode )
+        --> .hashcode --> get
+    ;
+
+    : set   ( c-addr u 2:this -- )
+        2swap 2over --> super --> set
+        --> set-hashcode
+    ;
+
+    : cat   ( c-addr u 2:this -- )
+        2swap 2over --> super --> cat
+        --> set-hashcode
+    ;
+
+end-class
+
+previous definitions
+
+[endif]
--- /dev/null
+++ b/softcore/win32.fr
@@ -1,0 +1,211 @@
+\ ** 
+\ ** win32.fr
+\ ** submitted by Larry Hastings, larry@hastings.org
+\ **
+
+
+S" FICL_PLATFORM_OS" ENVIRONMENT? drop S" WIN32" compare-insensitive 0= [if]
+
+
+: GetProcAddress ( name-addr name-u hmodule -- address )
+	3 \ argumentCount
+	0 \ floatArgumentBitfield
+	2 \ cstringArgumentBitfield
+	(get-proc-address) \ functionAddress
+	[
+	multicall-calltype-function multicall-returntype-integer or literal \ flags
+	]
+	multicall ;
+
+
+: LoadLibrary ( name-addr name-u -- hmodule )
+	2 \ argumentCount
+	0 \ floatArgumentBitfield
+	1 \ cstringArgumentBitfield
+	[
+	S" LoadLibraryA" kernel32.dll GetProcAddress literal \ functionAddress
+	multicall-calltype-function multicall-returntype-integer or literal \ flags
+	]
+	multicall ;
+
+
+: FreeLibrary ( hmodule -- success )
+	1 \ argumentCount
+	0 \ floatArgumentBitfield
+	0 \ cstringArgumentBitfield
+	[
+	S" FreeLibrary" kernel32.dll GetProcAddress literal \ functionAddress
+	multicall-calltype-function multicall-returntype-integer or literal \ flags
+	]
+	multicall ;
+
+
+: DebugBreak ( -- )
+	0 \ argumentCount
+	0 \ floatArgumentBitfield
+	0 \ cstringArgumentBitfield
+	[
+	S" DebugBreak" kernel32.dll GetProcAddress literal \ functionAddress
+	multicall-calltype-function multicall-returntype-void or literal \ flags
+	]
+	multicall ;
+
+: OutputDebugString ( addr u -- )
+	2 \ argumentCount
+	0 \ floatArgumentBitfield
+	1 \ cstringArgumentBitfield
+	[
+	S" OutputDebugStringA" kernel32.dll GetProcAddress literal \ functionAddress
+	multicall-calltype-function multicall-returntype-void or literal \ flags
+	]
+	multicall ;
+
+: GetTickCount ( -- ticks )
+	0 \ argumentCount
+	0 \ floatArgumentBitfield
+	0 \ cstringArgumentBitfield
+	[
+	S" GetTickCount" kernel32.dll GetProcAddress literal \ functionAddress
+	multicall-calltype-function multicall-returntype-integer or literal \ flags
+	]
+	multicall ;
+
+S" user32.dll" LoadLibrary constant user32.dll
+
+: MessageBox ( flags title-addr title-u body-addr body-u hwnd -- button )
+	6 \ argumentCount
+	0 \ floatArgumentBitfield
+	[
+	2 8 or literal \ cstringArgumentBitfield
+	S" MessageBoxA" user32.dll GetProcAddress literal \ functionAddress
+	multicall-calltype-function multicall-returntype-integer or literal \ flags
+	]
+	multicall ;
+
+
+\ Constants for use with MessageBox
+\ the ID* names are possible return values.
+
+0x00000000 constant MB_OK
+0x00000001 constant MB_OKCANCEL                 
+0x00000002 constant MB_ABORTRETRYIGNORE         
+0x00000003 constant MB_YESNOCANCEL              
+0x00000004 constant MB_YESNO                    
+0x00000005 constant MB_RETRYCANCEL              
+0x00000010 constant MB_ICONHAND                 
+0x00000020 constant MB_ICONQUESTION             
+0x00000030 constant MB_ICONEXCLAMATION          
+0x00000040 constant MB_ICONASTERISK             
+0x00000080 constant MB_USERICON                 
+0x00000000 constant MB_DEFBUTTON1               
+0x00000100 constant MB_DEFBUTTON2               
+0x00000200 constant MB_DEFBUTTON3               
+0x00000300 constant MB_DEFBUTTON4               
+0x00000000 constant MB_APPLMODAL                
+0x00001000 constant MB_SYSTEMMODAL              
+0x00002000 constant MB_TASKMODAL                
+0x00004000 constant MB_HELP                     
+0x00008000 constant MB_NOFOCUS                  
+0x00010000 constant MB_SETFOREGROUND            
+0x00020000 constant MB_DEFAULT_DESKTOP_ONLY     
+0x00040000 constant MB_TOPMOST                  
+0x00080000 constant MB_RIGHT                    
+0x00100000 constant MB_RTLREADING               
+
+MB_ICONEXCLAMATION constant MB_ICONWARNING              
+MB_ICONHAND        constant MB_ICONERROR                
+MB_ICONASTERISK    constant MB_ICONINFORMATION          
+MB_ICONHAND        constant MB_ICONSTOP                 
+
+
+0x00200000 constant MB_SERVICE_NOTIFICATION          
+0x00040000 constant MB_SERVICE_NOTIFICATION          
+0x00040000 constant MB_SERVICE_NOTIFICATION_NT3X     
+
+0x0000000F constant MB_TYPEMASK                 
+0x000000F0 constant MB_ICONMASK                 
+0x00000F00 constant MB_DEFMASK                  
+0x00003000 constant MB_MODEMASK                 
+0x0000C000 constant MB_MISCMASK                 
+
+
+1 constant IDOK                
+2 constant IDCANCEL            
+3 constant IDABORT             
+4 constant IDRETRY             
+5 constant IDIGNORE            
+6 constant IDYES               
+7 constant IDNO                
+8 constant IDCLOSE         
+9 constant IDHELP          
+
+
+\ ** old names
+: output-debug-string OutputDebugString ;
+: debug-break DebugBreak ;
+
+
+: uaddr->cstring { addr u | cstring -- cstring }
+	u 1+  allocate
+	0= if
+		to cstring
+		addr cstring u move
+		0  cstring u + c!
+		cstring
+	else
+		0
+	endif
+	;
+
+\ **
+\ ** The following four calls:
+\ **    callnativeFunction
+\ **    callcFunction
+\ **    callpascalFunction
+\ **    vcall
+\ ** are deprecated.  Please use the more powerful "multicall" instead.
+\ **
+
+\ ** My original native function caller, reimplemented in Ficl using multicall.
+: callnativeFunction { functionAddress popStack -- }
+	0 \ floatArgumentBitfield
+	0 \ cstringArgumentBitfield
+	functionAddress \ functionAddress
+
+	[
+	multicall-calltype-function
+	multicall-returntype-integer or
+	multicall-reverse-arguments or
+	literal
+	]
+
+	multicall
+	;
+
+
+\ ** simple wrappers for callnativeFunction that specify the calling convention
+: callcfunction 1 callnativeFunction ;
+: callpascalfunction 0 callnativeFunction ;
+
+
+\ ** Guy Carver's "vcall" function, reimplemented in Ficl using multicall.
+: vcall { argumentCount index -- }
+	argumentCount 0x80000000 invert or  \ cleaned-up argumentCount
+	0 \ cstringArgumentBitfield
+	0 \ cstringFlags
+	index \ index
+
+	\ flags:
+	argumentCount 0x80000000 and if multicall-returntype-integer else multicall-returntype-void endif
+	
+	[
+	multicall-calltype-virtual-method
+	multicall-reverse-arguments or
+	literal
+	] or
+
+	multicall
+	;
+
+[endif]
+
--- /dev/null
+++ b/system.c
@@ -1,0 +1,466 @@
+/*******************************************************************
+** f i c l . c
+** Forth Inspired Command Language - external interface
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 19 July 1997
+** $Id: system.c,v 1.1 2010/08/12 12:50:34 asau Exp $
+*******************************************************************/
+/*
+** This is an ANS Forth interpreter written in C.
+** Ficl uses Forth syntax for its commands, but turns the Forth 
+** model on its head in other respects.
+** Ficl provides facilities for interoperating
+** with programs written in C: C functions can be exported to Ficl,
+** and Ficl commands can be executed via a C calling interface. The
+** interpreter is re-entrant, so it can be used in multiple instances
+** in a multitasking system. Unlike Forth, Ficl's outer interpreter
+** expects a text block as input, and returns to the caller after each
+** text block, so the data pump is somewhere in external code in the 
+** style of TCL.
+**
+** Code is written in ANSI C for portability. 
+*/
+/*
+** 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 <string.h>
+#include "ficl.h"
+
+
+/*
+** System statics
+** Each ficlSystem builds a global dictionary during its start
+** sequence. This is shared by all virtual machines of that system.
+** Therefore only one VM can update the dictionary
+** at a time. The system imports a locking function that
+** you can override in order to control update access to
+** the dictionary. The function is stubbed out by default,
+** but you can insert one: #define FICL_WANT_MULTITHREADED 1
+** and supply your own version of ficlDictionaryLock.
+*/
+
+
+ficlSystem *ficlSystemGlobal = NULL;
+
+/**************************************************************************
+                        f i c l S e t V e r s i o n E n v
+** Create a double ficlCell environment constant for the version ID
+**************************************************************************/
+static void ficlSystemSetVersion(ficlSystem *system)
+{
+    int major = 0;
+    int minor = 0;
+	ficl2Integer combined;
+	ficlDictionary *environment = ficlSystemGetEnvironment(system);
+    sscanf(FICL_VERSION, "%d.%d", &major, &minor);
+	FICL_2INTEGER_SET(major, minor, combined);
+    ficlDictionarySet2Constant(environment, "ficl-version", combined);
+    ficlDictionarySetConstant(environment, "ficl-robust",  FICL_ROBUST);
+    return;
+}
+
+
+
+
+
+/**************************************************************************
+                        f i c l I n i t S y s t e m
+** Binds a global dictionary to the interpreter system. 
+** You specify the address and size of the allocated area.
+** After that, Ficl manages it.
+** First step is to set up the static pointers to the area.
+** Then write the "precompiled" portion of the dictionary in.
+** The dictionary needs to be at least large enough to hold the
+** precompiled part. Try 1K cells minimum. Use "words" to find
+** out how much of the dictionary is used at any time.
+**************************************************************************/
+ficlSystem *ficlSystemCreate(ficlSystemInformation *fsi)
+{
+    ficlInteger dictionarySize;
+    ficlInteger environmentSize;
+	ficlInteger stackSize;
+    ficlSystem *system;
+	ficlCallback callback;
+	ficlSystemInformation fauxInfo;
+	ficlDictionary *environment;
+
+
+
+	if (fsi == NULL)
+	{
+		fsi = &fauxInfo;
+		ficlSystemInformationInitialize(fsi);
+	}
+
+	callback.context = fsi->context;
+	callback.textOut = fsi->textOut;
+	callback.errorOut = fsi->errorOut;
+	callback.system = NULL;
+	callback.vm = NULL;
+
+    FICL_ASSERT(&callback, sizeof(ficlInteger) == sizeof(void *));
+    FICL_ASSERT(&callback, sizeof(ficlUnsigned) == sizeof(void *));
+#if (FICL_WANT_FLOAT)
+    FICL_ASSERT(&callback, sizeof(ficlFloat) == sizeof(void *));
+#endif
+
+    system = ficlMalloc(sizeof(ficlSystem));
+
+    FICL_ASSERT(&callback, system);
+
+    memset(system, 0, sizeof(ficlSystem));
+
+    dictionarySize = fsi->dictionarySize;
+    if (dictionarySize <= 0)
+        dictionarySize = FICL_DEFAULT_DICTIONARY_SIZE;
+
+    environmentSize = fsi->environmentSize;
+    if (environmentSize <= 0)
+        environmentSize = FICL_DEFAULT_DICTIONARY_SIZE;
+
+    stackSize = fsi->stackSize;
+    if (stackSize < FICL_DEFAULT_STACK_SIZE)
+        stackSize = FICL_DEFAULT_STACK_SIZE;
+
+    system->dictionary = ficlDictionaryCreateHashed(system, (unsigned)dictionarySize, FICL_HASH_SIZE);
+    system->dictionary->forthWordlist->name = "forth-wordlist";
+
+    environment = ficlDictionaryCreate(system, (unsigned)environmentSize);
+    system->environment = environment;
+    system->environment->forthWordlist->name = "environment";
+
+    system->callback.textOut = fsi->textOut;
+    system->callback.errorOut = fsi->errorOut;
+    system->callback.context = fsi->context;
+    system->callback.system = system;
+    system->callback.vm = NULL;
+    system->stackSize = stackSize;
+
+#if FICL_WANT_LOCALS
+    /*
+    ** The locals dictionary is only searched while compiling,
+    ** but this is where speed is most important. On the other
+    ** hand, the dictionary gets emptied after each use of locals
+    ** The need to balance search speed with the cost of the 'empty'
+    ** operation led me to select a single-threaded list...
+    */
+    system->locals = ficlDictionaryCreate(system, (unsigned)FICL_MAX_LOCALS * FICL_CELLS_PER_WORD);
+#endif /* FICL_WANT_LOCALS */
+
+    /*
+    ** Build the precompiled dictionary and load softwords. We need a temporary
+    ** VM to do this - ficlNewVM links one to the head of the system VM list.
+    ** ficlCompilePlatform (defined in win32.c, for example) adds platform specific words.
+    */
+    ficlSystemCompileCore(system);
+    ficlSystemCompilePrefix(system);
+
+#if FICL_WANT_FLOAT
+    ficlSystemCompileFloat(system);
+#endif /* FICL_WANT_FLOAT */
+
+#if FICL_WANT_PLATFORM
+    ficlSystemCompilePlatform(system);
+#endif /* FICL_WANT_PLATFORM */
+
+    ficlSystemSetVersion(system);
+
+    /*
+    ** Establish the parse order. Note that prefixes precede numbers -
+    ** this allows constructs like "0b101010" which might parse as a
+    ** hex value otherwise.
+    */
+    ficlSystemAddPrimitiveParseStep(system, "?word", ficlVmParseWord);
+    ficlSystemAddPrimitiveParseStep(system, "?prefix", ficlVmParsePrefix);
+    ficlSystemAddPrimitiveParseStep(system, "?number", ficlVmParseNumber);
+#if FICL_WANT_FLOAT
+    ficlSystemAddPrimitiveParseStep(system, "?float", ficlVmParseFloatNumber);
+#endif
+
+    /*
+    ** Now create a temporary VM to compile the softwords. Since all VMs are
+    ** linked into the vmList of ficlSystem, we don't have to pass the VM
+    ** to ficlCompileSoftCore -- it just hijacks whatever it finds in the VM list.
+    ** Ficl 2.05: vmCreate no longer depends on the presence of INTERPRET in the
+    ** dictionary, so a VM can be created before the dictionary is built. It just
+    ** can't do much...
+    */
+    ficlSystemCreateVm(system);
+#define ADD_COMPILE_FLAG(name) ficlDictionarySetConstant(environment, #name, name)
+	ADD_COMPILE_FLAG(FICL_WANT_LZ_SOFTCORE);
+	ADD_COMPILE_FLAG(FICL_WANT_FILE);
+	ADD_COMPILE_FLAG(FICL_WANT_FLOAT);
+	ADD_COMPILE_FLAG(FICL_WANT_DEBUGGER);
+	ADD_COMPILE_FLAG(FICL_WANT_EXTENDED_PREFIX);
+	ADD_COMPILE_FLAG(FICL_WANT_USER);
+	ADD_COMPILE_FLAG(FICL_WANT_LOCALS);
+	ADD_COMPILE_FLAG(FICL_WANT_OOP);
+	ADD_COMPILE_FLAG(FICL_WANT_SOFTWORDS);
+	ADD_COMPILE_FLAG(FICL_WANT_MULTITHREADED);
+	ADD_COMPILE_FLAG(FICL_WANT_OPTIMIZE);
+	ADD_COMPILE_FLAG(FICL_WANT_VCALL);
+
+	ADD_COMPILE_FLAG(FICL_PLATFORM_ALIGNMENT);
+
+	ADD_COMPILE_FLAG(FICL_ROBUST);
+
+#define ADD_COMPILE_STRING(name) ficlDictionarySetConstantString(environment, #name, name)
+	ADD_COMPILE_STRING(FICL_PLATFORM_ARCHITECTURE);
+	ADD_COMPILE_STRING(FICL_PLATFORM_OS);
+
+    ficlSystemCompileSoftCore(system);
+    ficlSystemDestroyVm(system->vmList);
+
+	if (ficlSystemGlobal == NULL)
+		ficlSystemGlobal = system;
+
+    return system;
+}
+
+
+
+/**************************************************************************
+                        f i c l T e r m S y s t e m
+** Tear the system down by deleting the dictionaries and all VMs.
+** This saves you from having to keep track of all that stuff.
+**************************************************************************/
+void ficlSystemDestroy(ficlSystem *system)
+{
+    if (system->dictionary)
+        ficlDictionaryDestroy(system->dictionary);
+    system->dictionary = NULL;
+
+    if (system->environment)
+        ficlDictionaryDestroy(system->environment);
+    system->environment = NULL;
+
+#if FICL_WANT_LOCALS
+    if (system->locals)
+        ficlDictionaryDestroy(system->locals);
+    system->locals = NULL;
+#endif
+
+    while (system->vmList != NULL)
+    {
+        ficlVm *vm = system->vmList;
+        system->vmList = system->vmList->link;
+        ficlVmDestroy(vm);
+    }
+
+    ficlFree(system);
+    system = NULL;
+
+	if (ficlSystemGlobal == system)
+		ficlSystemGlobal = NULL;
+
+    return;
+}
+
+
+/**************************************************************************
+                        f i c l A d d P a r s e S t e p
+** Appends a parse step function to the end of the parse list (see 
+** ficlParseStep notes in ficl.h for details). Returns 0 if successful,
+** nonzero if there's no more room in the list.
+**************************************************************************/
+int ficlSystemAddParseStep(ficlSystem *system, ficlWord *word)
+{
+    int i;
+    for (i = 0; i < FICL_MAX_PARSE_STEPS; i++)
+    {
+        if (system->parseList[i] == NULL)
+        {
+            system->parseList[i] = word;
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+
+/*
+** Compile a word into the dictionary that invokes the specified ficlParseStep
+** function. It is up to the user (as usual in Forth) to make sure the stack 
+** preconditions are valid (there needs to be a counted string on top of the stack)
+** before using the resulting word.
+*/
+void ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name, ficlParseStep pStep)
+{
+    ficlDictionary *dictionary = system->dictionary;
+    ficlWord *word = ficlDictionaryAppendPrimitive(dictionary, name, ficlPrimitiveParseStepParen, FICL_WORD_DEFAULT);
+    ficlDictionaryAppendCell(dictionary, FICL_LVALUE_TO_CELL(pStep));
+    ficlSystemAddParseStep(system, word);
+}
+/**************************************************************************
+                        f i c l N e w V M
+** Create a new virtual machine and link it into the system list
+** of VMs for later cleanup by ficlTermSystem.
+**************************************************************************/
+ficlVm *ficlSystemCreateVm(ficlSystem *system)
+{
+    ficlVm *vm = ficlVmCreate(NULL, system->stackSize, system->stackSize);
+    vm->link = system->vmList;
+
+	memcpy(&(vm->callback), &(system->callback), sizeof(system->callback));
+	vm->callback.vm = vm;
+	vm->callback.system = system;
+
+    system->vmList = vm;
+    return vm;
+}
+
+
+/**************************************************************************
+                        f i c l F r e e V M
+** 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.
+**************************************************************************/
+void ficlSystemDestroyVm(ficlVm *vm)
+{
+    ficlSystem *system = vm->callback.system;
+    ficlVm *pList = system->vmList;
+
+    FICL_VM_ASSERT(vm, vm != NULL);
+
+    if (system->vmList == vm)
+    {
+        system->vmList = system->vmList->link;
+    }
+    else for (; pList != NULL; pList = pList->link)
+    {
+        if (pList->link == vm)
+        {
+            pList->link = vm->link;
+            break;
+        }
+    }
+
+    if (pList)
+        ficlVmDestroy(vm);
+    return;
+}
+
+
+/**************************************************************************
+                        f i c l L o o k u p
+** Look in the system dictionary for a match to the given name. If
+** found, return the address of the corresponding ficlWord. Otherwise
+** return NULL.
+**************************************************************************/
+ficlWord *ficlSystemLookup(ficlSystem *system, char *name)
+{
+    ficlString s;
+    FICL_STRING_SET_FROM_CSTRING(s, name);
+    return ficlDictionaryLookup(system->dictionary, s);
+}
+
+
+/**************************************************************************
+                        f i c l G e t D i c t
+** Returns the address of the system dictionary
+**************************************************************************/
+ficlDictionary *ficlSystemGetDictionary(ficlSystem *system)
+{
+    return system->dictionary;
+}
+
+
+/**************************************************************************
+                        f i c l G e t E n v
+** Returns the address of the system environment space
+**************************************************************************/
+ficlDictionary *ficlSystemGetEnvironment(ficlSystem *system)
+{
+    return system->environment;
+}
+
+
+/**************************************************************************
+                        f i c l G e t L o c
+** Returns the address of the system locals dictionary. This dictionary is
+** only used during compilation, and is shared by all VMs.
+**************************************************************************/
+#if FICL_WANT_LOCALS
+ficlDictionary *ficlSystemGetLocals(ficlSystem *system)
+{
+    return system->locals;
+}
+#endif
+
+
+
+/**************************************************************************
+                        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
+ficlWord *ficlSystemLookupLocal(ficlSystem *system, ficlString name)
+{
+    ficlWord *word = NULL;
+	ficlDictionary *dictionary = system->dictionary;
+    ficlHash *hash = ficlSystemGetLocals(system)->forthWordlist;
+    int i;
+    ficlUnsigned16 hashCode   = ficlHashCode(name);
+
+    FICL_SYSTEM_ASSERT(system, hash);
+    FICL_SYSTEM_ASSERT(system, dictionary);
+
+    ficlDictionaryLock(dictionary, FICL_TRUE);
+    /* 
+    ** check the locals dictionary first... 
+    */
+    word = ficlHashLookup(hash, name, hashCode);
+
+    /* 
+    ** If no joy, (!word) ------------------------------v
+    ** iterate over the search list in the main dictionary
+    */
+    for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i)
+    {
+        hash = dictionary->wordlists[i];
+        word = ficlHashLookup(hash, name, hashCode);
+    }
+
+    ficlDictionaryLock(dictionary, FICL_FALSE);
+    return word;
+}
+#endif
+
+
--- /dev/null
+++ b/test/fib.fr
@@ -1,0 +1,12 @@
+: fib ( n1 -- n2 )
+    dup 1 > if
+	dup
+	1- recurse
+	swap 2 - recurse
+	+
+    then ;
+
+
+35 value nfibs
+: fibtest nfibs fib . cr ;
+
--- /dev/null
+++ b/test/testcase.fr
@@ -1,0 +1,84 @@
+
+
+1 2 3
+.s-simple
+cr
+
+: test-case ( n -- )
+	case
+		0 of
+			." zero"
+			endof
+		1 of
+			." one"
+			endof
+		." something else"
+	endcase
+	cr
+	;
+
+
+see test-case
+
+.( You should see [3] 1 2 3 -> )
+.s-simple
+.( <-) cr
+
+.( You should see "zero": )
+0 test-case
+
+.( You should see "one": )
+1 test-case
+
+.( You should see "something else": )
+324 test-case
+
+.( You should still see [3] 1 2 3 -> )
+.s-simple
+.( <-) cr
+
+
+: test-case-2 ( n -- )
+	case
+		0 of
+			." zero"
+			fallthrough
+		1 of
+			." one"
+			endof
+		2 of
+			." two"
+			fallthrough
+		." something else"
+	endcase
+	cr
+	;
+
+
+see test-case-2
+
+cr
+
+.( You should once more see [3] 1 2 3 -> )
+.s-simple
+.( <-) cr
+
+.( You should see "zeroone": )
+0 test-case-2
+
+.( You should see "one": )
+1 test-case-2
+
+.( You should see "two": )
+2 test-case-2
+
+.( You should see "something else": )
+324 test-case-2
+
+.( You should still see [3] 1 2 3 -> )
+.s-simple
+.( <-) cr
+
+
+
+bye
--- /dev/null
+++ b/utility.c
@@ -1,0 +1,260 @@
+#include "ficl.h"
+
+
+/**************************************************************************
+                        a l i g n P t r
+** Aligns the given pointer to FICL_ALIGN address units.
+** Returns the aligned pointer value.
+**************************************************************************/
+void *ficlAlignPointer(void *ptr)
+{
+#if FICL_PLATFORM_ALIGNMENT > 1
+	int p = (int)ptr;
+	if (p & (FICL_PLATFORM_ALIGNMENT - 1))
+		ptr = (void *)((p & ~(FICL_PLATFORM_ALIGNMENT - 1)) + FICL_PLATFORM_ALIGNMENT);
+#endif
+    return ptr;
+}
+
+
+/**************************************************************************
+                        s t r r e v
+** 
+**************************************************************************/
+char *ficlStringReverse( char *string )    
+{                               /* reverse a string in-place */
+    int i = strlen(string);
+    char *p1 = string;          /* first char of string */
+    char *p2 = string + i - 1;  /* last non-NULL char of string */
+    char c;
+
+    if (i > 1)
+    {
+        while (p1 < p2)
+        {
+            c = *p2;
+            *p2 = *p1;
+            *p1 = c;
+            p1++; p2--;
+        }
+    }
+        
+    return string;
+}
+
+
+/**************************************************************************
+                        d i g i t _ t o _ c h a r
+** 
+**************************************************************************/
+static char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+char ficlDigitToCharacter(int value)
+{
+    return digits[value];
+}
+
+
+/**************************************************************************
+                        i s P o w e r O f T w o
+** Tests whether supplied argument is an integer power of 2 (2**n)
+** where 32 > n > 1, and returns n if so. Otherwise returns zero.
+**************************************************************************/
+int ficlIsPowerOfTwo(ficlUnsigned u)
+{
+    int i = 1;
+    ficlUnsigned t = 2;
+
+    for (; ((t <= u) && (t != 0)); i++, t <<= 1)
+    {
+        if (u == t)
+            return i;
+    }
+
+    return 0;
+}
+
+
+/**************************************************************************
+                        l t o a
+** 
+**************************************************************************/
+char *ficlLtoa( ficlInteger value, char *string, int radix )
+{                               /* convert long to string, any base */
+    char *cp = string;
+    int sign = ((radix == 10) && (value < 0));
+    int pwr;
+
+    FICL_ASSERT(NULL, radix > 1);
+    FICL_ASSERT(NULL, radix < 37);
+    FICL_ASSERT(NULL, string);
+
+    pwr = ficlIsPowerOfTwo((ficlUnsigned)radix);
+
+    if (sign)
+        value = -value;
+
+    if (value == 0)
+        *cp++ = '0';
+    else if (pwr != 0)
+    {
+        ficlUnsigned v = (ficlUnsigned) value;
+        ficlUnsigned mask = (ficlUnsigned) ~(-1 << pwr);
+        while (v)
+        {
+            *cp++ = digits[v & mask];
+            v >>= pwr;
+        }
+    }
+    else
+    {
+        ficl2UnsignedQR result;
+        ficl2Unsigned v;
+		FICL_UNSIGNED_TO_2UNSIGNED((ficlUnsigned)value, v);
+        while (FICL_2UNSIGNED_NOT_ZERO(v))
+        {
+            result = ficl2UnsignedDivide(v, (ficlUnsigned)radix);
+            *cp++ = digits[result.remainder];
+			v = result.quotient;
+        }
+    }
+
+    if (sign)
+        *cp++ = '-';
+
+    *cp++ = '\0';
+
+    return ficlStringReverse(string);
+}
+
+
+/**************************************************************************
+                        u l t o a
+** 
+**************************************************************************/
+char *ficlUltoa(ficlUnsigned value, char *string, int radix )
+{                               /* convert long to string, any base */
+    char *cp = string;
+    ficl2Unsigned ud;
+    ficl2UnsignedQR result;
+
+    FICL_ASSERT(NULL, radix > 1);
+    FICL_ASSERT(NULL, radix < 37);
+    FICL_ASSERT(NULL, string);
+
+    if (value == 0)
+        *cp++ = '0';
+    else
+    {
+		FICL_UNSIGNED_TO_2UNSIGNED(value, ud);
+        while (FICL_2UNSIGNED_NOT_ZERO(ud))
+        {
+            result = ficl2UnsignedDivide(ud, (ficlUnsigned)radix);
+			ud = result.quotient;
+            *cp++ = digits[result.remainder];
+        }
+    }
+
+    *cp++ = '\0';
+
+    return ficlStringReverse(string);
+}
+
+
+/**************************************************************************
+                        c a s e F o l d
+** Case folds a NULL terminated string in place. All characters
+** get converted to lower case.
+**************************************************************************/
+char *ficlStringCaseFold(char *cp)
+{
+    char *oldCp = cp;
+
+    while (*cp)
+    {
+        if (isupper(*cp))
+            *cp = (char)tolower(*cp);
+        cp++;
+    }
+
+    return oldCp;
+}
+
+
+/**************************************************************************
+                        s t r i n c m p
+** (jws) simplified the code a bit in hopes of appeasing Purify
+**************************************************************************/
+int ficlStrincmp(char *cp1, char *cp2, ficlUnsigned count)
+{
+    int i = 0;
+
+    for (; 0 < count; ++cp1, ++cp2, --count)
+    {
+        i = tolower(*cp1) - tolower(*cp2);
+        if (i != 0)
+            return i;
+        else if (*cp1 == '\0')
+            return 0;
+    }
+    return 0;
+}
+
+/**************************************************************************
+                        s k i p S p a c e
+** Given a string pointer, returns a pointer to the first non-space
+** char of the string, or to the NULL terminator if no such char found.
+** If the pointer reaches "end" first, stop there. Pass NULL to 
+** suppress this behavior.
+**************************************************************************/
+char *ficlStringSkipSpace(char *cp, char *end)
+{
+    FICL_ASSERT(NULL, cp);
+
+    while ((cp != end) && isspace(*cp))
+        cp++;
+
+    return cp;
+}
+
+
+
+
+
+void ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text, ficlCompatibilityOutputFunction outputFunction)
+{
+	char buffer[256];
+	char *bufferStop = buffer + sizeof(buffer) - 1;
+
+	if (text == NULL)
+	{
+		outputFunction(callback->vm, NULL, FICL_FALSE);
+		return;
+	}
+
+	while (*text)
+	{
+		int newline = FICL_FALSE;
+		char *trace = buffer;
+		while ((*text) && (trace < bufferStop))
+		{
+			switch (*text)
+			{
+				/* throw away \r */
+				case '\r':
+					text++;
+					continue;
+				case '\n':
+					text++;
+					newline = FICL_TRUE;
+					break;
+				default:
+					*trace++ = *text++;
+					break;
+			}
+		}
+		
+		*trace = 0;
+		(outputFunction)(callback->vm, buffer, newline);
+	}
+}
--- /dev/null
+++ b/word.c
@@ -1,0 +1,144 @@
+#include "ficl.h"
+
+
+/**************************************************************************
+                        w o r d I s I m m e d i a t e
+** 
+**************************************************************************/
+int ficlWordIsImmediate(ficlWord *word)
+{
+    return ((word != NULL) && (word->flags & FICL_WORD_IMMEDIATE));
+}
+
+
+/**************************************************************************
+                        w o r d I s C o m p i l e O n l y
+** 
+**************************************************************************/
+int ficlWordIsCompileOnly(ficlWord *word)
+{
+    return ((word != NULL) && (word->flags & FICL_WORD_COMPILE_ONLY));
+}
+
+
+/**************************************************************************
+                        f i c l W o r d C l a s s i f y
+** This public function helps to classify word types for SEE
+** and the debugger in tools.c. Given an pointer to a word, it returns
+** a member of WOR
+**************************************************************************/
+ficlWordKind ficlWordClassify(ficlWord *word)
+{
+    ficlPrimitive code;
+    int i;
+	ficlWordKind iType;
+
+	if ( (((ficlInstruction)word) > ficlInstructionInvalid)
+		&& (((ficlInstruction)word) < ficlInstructionLast) )
+		{
+		i = (int)word;
+		iType = FICL_WORDKIND_INSTRUCTION;
+		goto IS_INSTRUCTION;
+		}
+
+    code = word->code;
+
+	if ((ficlInstruction)code < ficlInstructionLast)
+		{
+		i = (int)code;
+		iType = FICL_WORDKIND_INSTRUCTION_WORD;
+		goto IS_INSTRUCTION;
+		}
+
+    return FICL_WORDKIND_PRIMITIVE;
+
+IS_INSTRUCTION:
+
+	switch (i)
+	{
+		case ficlInstructionConstantParen:
+#if FICL_WANT_FLOAT
+		case ficlInstructionFConstantParen:
+#endif /* FICL_WANT_FLOAT */
+			return FICL_WORDKIND_CONSTANT;
+
+		case ficlInstruction2ConstantParen:
+#if FICL_WANT_FLOAT
+		case ficlInstructionF2ConstantParen:
+#endif /* FICL_WANT_FLOAT */
+			return FICL_WORDKIND_2CONSTANT;
+
+#if FICL_WANT_LOCALS
+		case ficlInstructionToLocalParen:
+		case ficlInstructionTo2LocalParen:
+#if FICL_WANT_FLOAT
+		case ficlInstructionToFLocalParen:
+		case ficlInstructionToF2LocalParen:
+#endif /* FICL_WANT_FLOAT */
+			return FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT;
+#endif /* FICL_WANT_LOCALS */
+
+#if FICL_WANT_USER
+		case ficlInstructionUserParen:
+			return FICL_WORDKIND_USER;
+#endif
+
+		case ficlInstruction2LiteralParen:
+			return FICL_WORDKIND_2LITERAL;
+			
+#if FICL_WANT_FLOAT
+		case ficlInstructionFLiteralParen:
+			return FICL_WORDKIND_FLITERAL;
+#endif
+
+		case ficlInstructionCreateParen:
+			return FICL_WORDKIND_CREATE;
+
+		case ficlInstructionCStringLiteralParen:
+			return FICL_WORDKIND_CSTRING_LITERAL;
+
+		case ficlInstructionStringLiteralParen:
+			return FICL_WORDKIND_STRING_LITERAL;
+
+		case ficlInstructionColonParen:
+			return FICL_WORDKIND_COLON;
+
+		case ficlInstructionDoDoes:
+	        return FICL_WORDKIND_DOES;
+
+		case ficlInstructionDoParen:
+	        return FICL_WORDKIND_DO;
+
+		case ficlInstructionQDoParen:
+	        return FICL_WORDKIND_QDO;
+
+		case ficlInstructionVariableParen:
+			return FICL_WORDKIND_VARIABLE;
+
+		case ficlInstructionBranchParenWithCheck:
+		case ficlInstructionBranchParen:
+			return FICL_WORDKIND_BRANCH;
+			
+		case ficlInstructionBranch0ParenWithCheck:
+		case ficlInstructionBranch0Paren:
+			return FICL_WORDKIND_BRANCH0;
+			
+		case ficlInstructionLiteralParen:
+			return FICL_WORDKIND_LITERAL;
+			
+		case ficlInstructionLoopParen:
+			return FICL_WORDKIND_LOOP;
+			
+		case ficlInstructionOfParen:
+			return FICL_WORDKIND_OF;
+			
+		case ficlInstructionPlusLoopParen:
+			return FICL_WORDKIND_PLOOP;
+			
+		default:
+			return iType;
+	}
+}
+
+
+