ref: 8950d9094c61f1c559139cd26abb30894a977d67
parent: 2c4ec5704740c223c847a77d09ba5b35fd6dcf95
author: jsadler <jsadler@ficl.sf.net>
date: Sun Nov 4 20:09:29 CST 2001
ficl release 3.01 fileset. Added Files: ficl/fileaccess.c ficl/unix.c ficl/doc/favicon.ico ficl/softwords/fileaccess.fr ficl/softwords/softcore.py ficl/softwords/softcore.py.bat ----------------------------------------------------------------------
--- a/Makefile.riscos
+++ b/Makefile.riscos
@@ -11,9 +11,9 @@
lib: o.libficl
-ficl: testmain.o ficl.h sysdep.h o.libficl
- $(CC) testmain.o -o ficl -L. -lficl -lm
-
+ficl: testmain.o ficl.h sysdep.h o.libficl
+ $(CC) testmain.o -o ficl -L. -lficl -lm
+
# static library build
o.libficl: $(OBJECTS)
$(LIB) o.libficl $(OBJECTS)
--- a/ReadMe.txt
+++ b/ReadMe.txt
@@ -1,3 +1,22 @@
+rel 3.01 -- 2001
+
+Major contribs by Larry Hastings (larry@hastings.org)
+- FILE wordset
+- ficlEvaluate wrapper for ficlExec
+- ficlInitSystemEx makes it possible to bind selectable properties to VMs at create time
+- softcore.py (python version)
+
+Environment contains ficl-version (double)
+?number handles trailing decimal point per DOUBLE wordset spec
+
+Fixed broken .env (thanks to Leonid Rosin for spotting this goof)
+Fixed broken floating point words that depended on evaluation order of stack pops.
+env-constant
+env-2constant
+dictHashSummary is now commented out unless FICL_WANT_FLOAT (thanks to Leonid Rosin again)
+
+Thanks to David McNab for pointing out that .( should be IMMEDIATE. Now it is.
+
rel 3.00a -- July 2001
- Fixed broken oo.fr by commenting out vcall stuff using FICL_WANT_VCALL.
@@ -8,7 +27,7 @@
- Added pSys parameter to most ficlXXXX functions - multiple system support
dictLookupLoc renamed to ficlLookupLoc after addition of pSys param
- ficlInitSystem returns a FICL_SYSTEM*
+ ficlInibtSystem returns a FICL_SYSTEM*
ficlTermSystem
ficlNewVM
ficlLookup
--- a/dict.c
+++ b/dict.c
@@ -3,7 +3,7 @@
** Forth Inspired Command Language - dictionary methods
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 19 July 1997
-** $Id: dict.c,v 1.11 2001/06/12 08:24:31 jsadler Exp $
+** $Id: dict.c,v 1.12 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** This file implements the dictionary -- FICL's model of
@@ -459,6 +459,7 @@
** addressing scheme (i.e. collisions resolved by searching the
** table for an empty slot) for a given size table.
**************************************************************************/
+#if FICL_WANT_FLOAT
void dictHashSummary(FICL_VM *pVM)
{
FICL_DICT *dp = vmGetDict(pVM);
@@ -522,7 +523,7 @@
return;
}
-
+#endif
/**************************************************************************
d i c t I n c l u d e s
binary files /dev/null b/doc/favicon.ico differ
--- a/doc/ficl.html
+++ b/doc/ficl.html
@@ -85,12 +85,10 @@
</LI>
</UL>
<HR>
- <H2>
- <A name="download"></A>Download
- </H2>
+ <h1><A name="links"></A>Links</H1>
<UL>
<LI>
- <B><A href="http://sourceforge.net/project/showfiles.php?group_id=24441">Download ficl (latest release)</A></B>
+ <B><A name="download" href="http://sourceforge.net/project/showfiles.php?group_id=24441">Download ficl (latest release)</A></B>
</LI>
</UL>
<H2>
@@ -111,7 +109,7 @@
</LI>
</UL>
<H2>
- <A name="links"></A>More information on Ficl and Forth
+ More information on Ficl and Forth
</H2>
<UL>
<LI>
binary files a/doc/ficlddj.PDF b/doc/ficlddj.PDF differ
binary files a/doc/jwsforml.PDF b/doc/jwsforml.PDF differ
--- a/ficl.c
+++ b/ficl.c
@@ -3,7 +3,7 @@
** Forth Inspired Command Language - external interface
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 19 July 1997
-** $Id: ficl.c,v 1.13 2001/06/12 08:24:38 jsadler Exp $
+** $Id: ficl.c,v 1.14 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** This is an ANS Forth interpreter written in C.
@@ -75,6 +75,9 @@
static int defaultDict = FICL_DEFAULT_DICT;
+static void ficlSetVersionEnv(FICL_SYSTEM *pSys);
+
+
/**************************************************************************
f i c l I n i t S y s t e m
** Binds a global dictionary to the interpreter system.
@@ -86,8 +89,9 @@
** precompiled part. Try 1K cells minimum. Use "words" to find
** out how much of the dictionary is used at any time.
**************************************************************************/
-FICL_SYSTEM *ficlInitSystem(int nDictCells)
+FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi)
{
+ int nDictCells = fsi->nDictCells;
FICL_SYSTEM *pSys = ficlMalloc(sizeof (FICL_SYSTEM));
assert(pSys);
@@ -102,6 +106,9 @@
pSys->envp = dictCreate((unsigned)FICL_DEFAULT_ENV);
pSys->envp->pForthWords->name = "environment";
+ pSys->textOut = fsi->textOut;
+ pSys->context = fsi->context;
+
#if FICL_WANT_LOCALS
/*
** The locals dictionary is only searched while compiling,
@@ -114,28 +121,32 @@
#endif
/*
- ** Establish the parse order. Note that prefixes precede numbers -
- ** this allows constructs like "0b101010" which might parse as a
- ** hex value otherwise.
- */
- ficlCompilePrefix(pSys);
- ficlAddPrecompiledParseStep(pSys, "?number", ficlParseNumber);
-
- /*
** 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.
*/
ficlCompileCore(pSys);
+ ficlCompilePrefix(pSys);
#if FICL_WANT_FLOAT
ficlCompileFloat(pSys);
#endif
-
#if FICL_PLATFORM_EXTEND
ficlCompilePlatform(pSys);
#endif
+ ficlSetVersionEnv(pSys);
/*
+ ** Establish the parse order. Note that prefixes precede numbers -
+ ** this allows constructs like "0b101010" which might parse as a
+ ** hex value otherwise.
+ */
+ ficlAddPrecompiledParseStep(pSys, "?prefix", ficlParsePrefix);
+ ficlAddPrecompiledParseStep(pSys, "?number", ficlParseNumber);
+#if FICL_WANT_FLOAT
+ ficlAddPrecompiledParseStep(pSys, ">float", ficlParseFloatNumber);
+#endif
+
+ /*
** Now create a temporary VM to compile the softwords. Since all VMs are
** linked into the vmList of FICL_SYSTEM, we don't have to pass the VM
** to ficlCompileSoftCore -- it just hijacks whatever it finds in the VM list.
@@ -152,6 +163,15 @@
}
+FICL_SYSTEM *ficlInitSystem(int nDictCells)
+{
+ FICL_SYSTEM_INFO fsi;
+ ficlInitInfo(&fsi);
+ fsi.nDictCells = nDictCells;
+ return ficlInitSystemEx(&fsi);
+}
+
+
/**************************************************************************
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
@@ -223,6 +243,7 @@
FICL_VM *pVM = vmCreate(NULL, defaultStack, defaultStack);
pVM->link = pSys->vmList;
pVM->pSys = pSys;
+ vmSetTextOut(pVM, pSys->textOut);
pSys->vmList = pVM;
return pVM;
@@ -279,8 +300,10 @@
**************************************************************************/
int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags)
{
+#if FICL_MULTITHREAD
int err = ficlLockDictionary(TRUE);
if (err) return err;
+#endif /* FICL_MULTITHREAD */
assert(dictCellsAvail(pSys->dp) > sizeof (FICL_WORD) / sizeof (CELL));
dictAppendWord(pSys->dp, name, code, flags);
@@ -291,6 +314,21 @@
/**************************************************************************
+ f i c l E v a l u a t e
+** Wrapper for ficlExec() which sets SOURCE-ID to -1.
+*/
+int ficlEvaluate(FICL_VM *pVM, char *pText)
+{
+ int returnValue;
+ CELL id = pVM->sourceID;
+ pVM->sourceID.i = -1;
+ returnValue = ficlExecC(pVM, pText, -1);
+ pVM->sourceID = id;
+ return returnValue;
+}
+
+
+/**************************************************************************
f i c l E x e c
** Evaluates a block of input text in the context of the
** specified interpreter. Emits any requested output to the
@@ -316,8 +354,7 @@
int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size)
{
FICL_SYSTEM *pSys = pVM->pSys;
- FICL_WORD **pInterp = pSys->pInterp;
- FICL_DICT *dp = pSys->dp;
+ FICL_DICT *dp = pSys->dp;
int except;
jmp_buf vmState;
@@ -324,15 +361,8 @@
jmp_buf *oldState;
TIB saveTib;
- if (!pInterp[0])
- {
- pInterp[0] = ficlLookup(pSys, "interpret");
- pInterp[1] = ficlLookup(pSys, "(branch)");
- pInterp[2] = (FICL_WORD *)(void *)(-2);
- }
-
- assert(pInterp[0]);
assert(pVM);
+ assert(pSys->pInterp[0]);
if (size < 0)
size = strlen(pText);
@@ -356,7 +386,7 @@
}
else
{ /* set VM up to interpret text */
- vmPushIP(pVM, &pInterp[0]);
+ vmPushIP(pVM, &(pSys->pInterp[0]));
}
vmInnerLoop(pVM);
@@ -430,17 +460,13 @@
**************************************************************************/
int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord)
{
- static FICL_WORD *pQuit = NULL;
int except;
jmp_buf vmState;
jmp_buf *oldState;
FICL_WORD *oldRunningWord;
- if (!pQuit)
- pQuit = ficlLookup(pVM->pSys, "exit-inner");
-
assert(pVM);
- assert(pQuit);
+ assert(pVM->pSys->pExitInner);
/*
** Save the runningword so that RESTART behaves correctly
@@ -457,7 +483,7 @@
if (except)
vmPopIP(pVM);
else
- vmPushIP(pVM, &pQuit);
+ vmPushIP(pVM, &(pVM->pSys->pExitInner));
switch (except)
{
@@ -640,4 +666,17 @@
return;
}
+
+/**************************************************************************
+ f i c l S e t V e r s i o n E n v
+** Create a double cell environment constant for the version ID
+**************************************************************************/
+static void ficlSetVersionEnv(FICL_SYSTEM *pSys)
+{
+ int major = 0;
+ int minor = 0;
+ sscanf(FICL_VER, "%d.%d", &major, &minor);
+ ficlSetEnvD(pSys, "ficl-version", major, minor);
+ return;
+}
--- a/ficl.dsp
+++ b/ficl.dsp
@@ -96,6 +96,10 @@
# End Source File
# Begin Source File
+SOURCE=.\fileaccess.c
+# End Source File
+# Begin Source File
+
SOURCE=.\float.c
# End Source File
# Begin Source File
@@ -185,6 +189,10 @@
# End Source File
# Begin Source File
+SOURCE=.\softwords\fileaccess.fr
+# End Source File
+# Begin Source File
+
SOURCE=.\softwords\forml.fr
# End Source File
# Begin Source File
@@ -234,6 +242,10 @@
# Begin Source File
SOURCE=.\doc\ficl_debug.html
+# End Source File
+# Begin Source File
+
+SOURCE=.\ficl_guts.htm
# End Source File
# Begin Source File
--- a/ficl.h
+++ b/ficl.h
@@ -4,7 +4,7 @@
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 19 July 1997
** Dedicated to RHS, in loving memory
-** $Id: ficl.h,v 1.15 2001/06/12 08:24:33 jsadler Exp $
+** $Id: ficl.h,v 1.16 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -220,6 +220,7 @@
#include "sysdep.h"
#include <limits.h> /* UCHAR_MAX */
+#include <stdio.h>
/*
** Forward declarations... read on.
@@ -232,11 +233,13 @@
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;
/*
** the Good Stuff starts here...
*/
-#define FICL_VER "3.00"
+#define FICL_VER "3.01"
#if !defined (FICL_PROMPT)
#define FICL_PROMPT "ok> "
#endif
@@ -471,6 +474,7 @@
struct vm
{
FICL_SYSTEM *pSys; /* Which system this VM belongs to */
+ void *context; /* Not used by FICL--use this for your own data */
FICL_VM *link; /* Ficl keeps a VM list for simple teardown */
jmp_buf *pState; /* crude exception mechanism... */
OUTFUNC textOut; /* Output callback - see sysdep.c */
@@ -485,7 +489,7 @@
#if FICL_WANT_FLOAT
FICL_STACK *fStack; /* float stack (optional) */
#endif
- CELL sourceID; /* -1 if string, 0 if normal input */
+ 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];
@@ -582,10 +586,8 @@
void vmQuit (FICL_VM *pVM);
void vmReset (FICL_VM *pVM);
void vmSetTextOut (FICL_VM *pVM, OUTFUNC textOut);
-#if FICL_WANT_DEBUGGER
-void vmStep (FICL_VM *pVM);
-#endif
void vmTextOut (FICL_VM *pVM, char *text, int fNewline);
+void vmTextOut (FICL_VM *pVM, char *text, int fNewline);
void vmThrow (FICL_VM *pVM, int except);
void vmThrowErr (FICL_VM *pVM, char *fmt, ...);
@@ -759,7 +761,9 @@
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
@@ -806,6 +810,23 @@
void ficlListParseSteps(FICL_VM *pVM);
/*
+** FICL_BREAKPOINT record.
+** origXT - if NULL, this breakpoint is unused. Otherwise it stores the xt
+** that the breakpoint overwrote. This is restored to the dictionary when the
+** BP executes or gets cleared
+** address - the location of the breakpoint (address of the instruction that
+** has been replaced with the breakpoint trap
+** origXT - The original contents of the location with the breakpoint
+** Note: address is NULL when this breakpoint is empty
+*/
+typedef struct FICL_BREAKPOINT
+{
+ void *address;
+ FICL_WORD *origXT;
+} FICL_BREAKPOINT;
+
+
+/*
** F I C L _ S Y S T E M
** The top level data structure of the system - ficl_system ties a list of
** virtual machines with their corresponding dictionaries. Ficl 3.0 will
@@ -813,16 +834,11 @@
** to separate dictionaries with some constraints.
** The present model allows multiple sessions to one dictionary provided
** you implement ficlLockDictionary() as specified in sysdep.h
-**
-** RESTRICTIONS: due to the use of static variables in words.c for compiling
-** comtrol structures faster, if you use multiple ficl systems these variables
-** will point into the most recently initialized dictionary - this is probably
-** not a problem provided the precompiled dictionaries are identical for
-** all systems.
*/
struct ficl_system
{
FICL_SYSTEM *link;
+ void *context; /* Not used by FICL--use this for your own data */
FICL_VM *vmList;
FICL_DICT *dp;
FICL_DICT *envp;
@@ -831,8 +847,55 @@
#endif
FICL_WORD *pInterp[3];
FICL_WORD *parseList[FICL_MAX_PARSE_STEPS];
+ OUTFUNC textOut;
+
+ FICL_WORD *pBranchParen;
+ FICL_WORD *pDoParen;
+ FICL_WORD *pDoesParen;
+ FICL_WORD *pExitInner;
+ FICL_WORD *pExitParen;
+ FICL_WORD *pIfParen;
+ FICL_WORD *pInterpret;
+ FICL_WORD *pLitParen;
+ FICL_WORD *pTwoLitParen;
+ FICL_WORD *pLoopParen;
+ FICL_WORD *pPLoopParen;
+ FICL_WORD *pQDoParen;
+ FICL_WORD *pSemiParen;
+ FICL_WORD *pStore;
+ FICL_WORD *pCStringLit;
+ FICL_WORD *pStringLit;
+
+#if FICL_WANT_LOCALS
+ FICL_WORD *pGetLocalParen;
+ FICL_WORD *pGet2LocalParen;
+ FICL_WORD *pGetLocal0;
+ FICL_WORD *pGetLocal1;
+ FICL_WORD *pToLocalParen;
+ FICL_WORD *pTo2LocalParen;
+ FICL_WORD *pToLocal0;
+ FICL_WORD *pToLocal1;
+ FICL_WORD *pLinkParen;
+ FICL_WORD *pUnLinkParen;
+ FICL_INT nLocals;
+ CELL *pMarkLocals;
+#endif
+
+ FICL_BREAKPOINT bpStep;
};
+struct ficl_system_info
+{
+ int size;
+ int nDictCells;
+ OUTFUNC textOut;
+ void *context;
+};
+
+
+#define ficlInitInfo(x) { memset((x), 0, sizeof(FICL_SYSTEM_INFO)); \
+ (x)->size = sizeof(FICL_SYSTEM_INFO); }
+
/*
** External interface to FICL...
*/
@@ -840,7 +903,8 @@
** f i c l I n i t S y s t e m
** Binds a global dictionary to the interpreter system and initializes
** the dict to contain the ANSI CORE wordset.
-** You specify the address and size of the allocated area.
+** You can specify the address and size of the allocated area.
+** Using ficlInitSystemEx you can also specify the text output function.
** 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.
@@ -848,6 +912,9 @@
** precompiled part. Try 1K cells minimum. Use "words" to find
** out how much of the dictionary is used at any time.
*/
+FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi);
+
+/* Deprecated call */
FICL_SYSTEM *ficlInitSystem(int nDictCells);
/*
@@ -859,6 +926,16 @@
void ficlTermSystem(FICL_SYSTEM *pSys);
/*
+** f i c l E v a l u a t e
+** Evaluates a block of input text in the context of the
+** specified interpreter. Also sets SOURCE-ID properly.
+**
+** PLEASE USE THIS FUNCTION when throwing a hard-coded
+** string to the FICL interpreter.
+*/
+int ficlEvaluate(FICL_VM *pVM, char *pText);
+
+/*
** f i c l E x e c
** Evaluates a block of input text in the context of the
** specified interpreter. Emits any requested output to the
@@ -879,6 +956,10 @@
** commands.
** Preconditions: successful execution of ficlInitSystem,
** Successful creation and init of the VM by ficlNewVM (or equiv)
+**
+** If you call ficlExec() or one of its brothers, you MUST
+** ensure pVM->sourceID was set to a sensible value.
+** ficlExec() explicitly DOES NOT manage SOURCE-ID for you.
*/
int ficlExec (FICL_VM *pVM, char *pText);
int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT nChars);
@@ -955,12 +1036,15 @@
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_PLATFORM_EXTEND
void ficlCompilePlatform(FICL_SYSTEM *pSys);
#endif
+int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si);
/*
** from words.c...
@@ -994,11 +1078,33 @@
PRIMITIVE,
QDO,
STRINGLIT,
+ CSTRINGLIT,
+#if FICL_WANT_USER
USER,
+#endif
VARIABLE,
} WORDKIND;
WORDKIND ficlWordClassify(FICL_WORD *pFW);
+
+
+
+/*
+** Used with File-Access wordset.
+*/
+#define FICL_FAM_READ 1
+#define FICL_FAM_WRITE 2
+#define FICL_FAM_APPEND 4
+#define FICL_FAM_BINARY 8
+
+#define FICL_FAM_OPEN_MODE(fam) ((fam) & (FICL_FAM_READ | FICL_FAM_WRITE | FICL_FAM_APPEND))
+
+
+typedef struct ficlFILE
+{
+ FILE *f;
+ char filename[256];
+} ficlFILE;
#ifdef __cplusplus
}
--- /dev/null
+++ b/fileaccess.c
@@ -1,0 +1,423 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include "ficl.h"
+
+#if FICL_WANT_FILE
+/*
+**
+** fileaccess.c
+**
+** Implements all of the File Access word set that can be implemented in portable C.
+**
+*/
+
+static void pushIor(FICL_VM *pVM, int success)
+{
+ int ior;
+ if (success)
+ ior = 0;
+ else
+ ior = errno;
+ stackPushINT(pVM->pStack, ior);
+}
+
+
+
+static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid ior ) */
+{
+ int fam = stackPopINT(pVM->pStack);
+ int length = stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+ char mode[4];
+ FILE *f;
+
+ char *filename = (char *)_alloca(length + 1);
+ memcpy(filename, address, length);
+ filename[length] = 0;
+
+ *mode = 0;
+
+ switch (FICL_FAM_OPEN_MODE(fam))
+ {
+ case 0:
+ stackPushPtr(pVM->pStack, NULL);
+ stackPushINT(pVM->pStack, EINVAL);
+ return;
+ case FICL_FAM_READ:
+ strcat(mode, "r");
+ break;
+ case FICL_FAM_WRITE:
+ strcat(mode, writeMode);
+ break;
+ case FICL_FAM_READ | FICL_FAM_WRITE:
+ strcat(mode, writeMode);
+ strcat(mode, "+");
+ break;
+ }
+
+ strcat(mode, (fam & FICL_FAM_BINARY) ? "b" : "t");
+
+ f = fopen(filename, mode);
+ if (f == NULL)
+ stackPushPtr(pVM->pStack, NULL);
+ else
+ {
+ ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE));
+ strcpy(ff->filename, filename);
+ ff->f = f;
+ stackPushPtr(pVM->pStack, ff);
+
+ fseek(f, 0, SEEK_SET);
+ }
+ pushIor(pVM, f != NULL);
+}
+
+
+
+static void ficlOpenFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
+{
+ ficlFopen(pVM, "a");
+}
+
+
+static void ficlCreateFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */
+{
+ ficlFopen(pVM, "w");
+}
+
+
+static int closeFiclFILE(ficlFILE *ff) /* ( fileid -- ior ) */
+{
+ FILE *f = ff->f;
+ free(ff);
+ return !fclose(f);
+}
+
+static void ficlCloseFile(FICL_VM *pVM) /* ( fileid -- ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ pushIor(pVM, closeFiclFILE(ff));
+}
+
+static void ficlDeleteFile(FICL_VM *pVM) /* ( c-addr u -- ior ) */
+{
+ int length = stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+
+ char *filename = (char *)_alloca(length + 1);
+ memcpy(filename, address, length);
+ filename[length] = 0;
+
+ pushIor(pVM, !unlink(filename));
+}
+
+static void ficlRenameFile(FICL_VM *pVM) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */
+{
+ int length;
+ void *address;
+ char *from;
+ char *to;
+
+ length = stackPopINT(pVM->pStack);
+ address = (void *)stackPopPtr(pVM->pStack);
+ to = (char *)_alloca(length + 1);
+ memcpy(to, address, length);
+ to[length] = 0;
+
+ length = stackPopINT(pVM->pStack);
+ address = (void *)stackPopPtr(pVM->pStack);
+
+ from = (char *)_alloca(length + 1);
+ memcpy(from, address, length);
+ from[length] = 0;
+
+ pushIor(pVM, !rename(from, to));
+}
+
+static void ficlFileStatus(FICL_VM *pVM) /* ( c-addr u -- x ior ) */
+{
+ struct stat statbuf;
+
+ int length = stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+
+ char *filename = (char *)_alloca(length + 1);
+ memcpy(filename, address, length);
+ filename[length] = 0;
+
+ if (stat(filename, &statbuf) == 0)
+ {
+ /*
+ ** the "x" left on the stack is implementation-defined.
+ ** I push the file's access mode (readable, writeable, is directory, etc)
+ ** as defined by ANSI C.
+ */
+ stackPushINT(pVM->pStack, statbuf.st_mode);
+ stackPushINT(pVM->pStack, 0);
+ }
+ else
+ {
+ stackPushINT(pVM->pStack, -1);
+ stackPushINT(pVM->pStack, ENOENT);
+ }
+}
+
+
+static void ficlFilePosition(FICL_VM *pVM) /* ( fileid -- ud ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ long ud = ftell(ff->f);
+ stackPushINT(pVM->pStack, ud);
+ pushIor(pVM, ud != -1);
+}
+
+
+
+static long fileSize(FILE *f)
+{
+ struct _stat statbuf;
+ statbuf.st_size = -1;
+ if (_fstat(fileno(f), &statbuf) != 0)
+ return -1;
+ return statbuf.st_size;
+}
+
+
+
+static void ficlFileSize(FICL_VM *pVM) /* ( fileid -- ud ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ long ud = fileSize(ff->f);
+ stackPushINT(pVM->pStack, ud);
+ pushIor(pVM, ud != -1);
+}
+
+
+
+#define nLINEBUF 256
+static void ficlIncludeFile(FICL_VM *pVM) /* ( i*x fileid -- j*x ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ CELL id = pVM->sourceID;
+ int result = VM_OUTOFTEXT;
+ long currentPosition, totalSize;
+ long size;
+ pVM->sourceID.p = (void *)ff;
+
+ currentPosition = ftell(ff->f);
+ totalSize = fileSize(ff->f);
+ size = totalSize - currentPosition;
+
+ if ((totalSize != -1) && (currentPosition != -1) && (size > 0))
+ {
+ char *buffer = (char *)malloc(size);
+ long got = fread(buffer, 1, size, ff->f);
+ if (got == size)
+ result = ficlExecC(pVM, buffer, size);
+ }
+
+#if 0
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ CELL id = pVM->sourceID;
+ char cp[nLINEBUF];
+ int nLine = 0;
+ int keepGoing;
+ int result;
+ pVM->sourceID.p = (void *)ff;
+
+ /* feed each line to ficlExec */
+ keepGoing = TRUE;
+ while (keepGoing && fgets(cp, nLINEBUF, ff->f))
+ {
+ int len = strlen(cp) - 1;
+
+ nLine++;
+ if (len <= 0)
+ continue;
+
+ if (cp[len] == '\n')
+ cp[len] = '\0';
+
+ result = ficlExec(pVM, cp);
+
+ switch (result)
+ {
+ case VM_OUTOFTEXT:
+ case VM_USEREXIT:
+ break;
+
+ default:
+ pVM->sourceID = id;
+ keepGoing = FALSE;
+ break;
+ }
+ }
+#endif /* 0 */
+ /*
+ ** Pass an empty line with SOURCE-ID == -1 to flush
+ ** any pending REFILLs (as required by FILE wordset)
+ */
+ pVM->sourceID.i = -1;
+ ficlExec(pVM, "");
+
+ pVM->sourceID = id;
+ closeFiclFILE(ff);
+}
+
+
+
+static void ficlReadFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ int length = stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+ int result;
+
+ clearerr(ff->f);
+ result = fread(address, 1, length, ff->f);
+
+ stackPushINT(pVM->pStack, result);
+ pushIor(pVM, ferror(ff->f) == 0);
+}
+
+
+
+static void ficlReadLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 flag ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ int length = stackPopINT(pVM->pStack);
+ char *address = (char *)stackPopPtr(pVM->pStack);
+ int error;
+ int flag;
+
+ if (feof(ff->f))
+ {
+ stackPushINT(pVM->pStack, -1);
+ stackPushINT(pVM->pStack, 0);
+ stackPushINT(pVM->pStack, 0);
+ return;
+ }
+
+ clearerr(ff->f);
+ *address = 0;
+ fgets(address, length, ff->f);
+
+ error = ferror(ff->f);
+ if (error != 0)
+ {
+ stackPushINT(pVM->pStack, -1);
+ stackPushINT(pVM->pStack, 0);
+ stackPushINT(pVM->pStack, error);
+ return;
+ }
+
+ length = strlen(address);
+ flag = (length > 0);
+ if (length && ((address[length - 1] == '\r') || (address[length - 1] == '\n')))
+ length--;
+
+ stackPushINT(pVM->pStack, length);
+ stackPushINT(pVM->pStack, flag);
+ stackPushINT(pVM->pStack, 0); /* ior */
+}
+
+
+
+static void ficlWriteFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ int length = stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+
+ clearerr(ff->f);
+ fwrite(address, 1, length, ff->f);
+ pushIor(pVM, ferror(ff->f) == 0);
+}
+
+
+
+static void ficlWriteLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ size_t length = (size_t)stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+
+ clearerr(ff->f);
+ if (fwrite(address, 1, length, ff->f) == length)
+ fwrite("\n", 1, 1, ff->f);
+ pushIor(pVM, ferror(ff->f) == 0);
+}
+
+
+
+static void ficlRepositionFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ size_t ud = (size_t)stackPopINT(pVM->pStack);
+
+ pushIor(pVM, fseek(ff->f, ud, SEEK_SET) == 0);
+}
+
+
+
+static void ficlFlushFile(FICL_VM *pVM) /* ( fileid -- ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ pushIor(pVM, fflush(ff->f) == 0);
+}
+
+
+
+#if FICL_HAVE_FTRUNCATE
+
+static void ficlResizeFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */
+{
+ ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack);
+ size_t ud = (size_t)stackPopINT(pVM->pStack);
+
+ pushIor(pVM, ftruncate(fileno(ff->f), ud) == 0);
+}
+
+#endif /* FICL_HAVE_FTRUNCATE */
+
+#endif /* FICL_WANT_FILE */
+
+
+
+void ficlCompileFile(FICL_SYSTEM *pSys)
+{
+#if FICL_WANT_FILE
+ FICL_DICT *dp = pSys->dp;
+ assert(dp);
+
+ dictAppendWord(dp, "create-file", ficlCreateFile, FW_DEFAULT);
+ dictAppendWord(dp, "open-file", ficlOpenFile, FW_DEFAULT);
+ dictAppendWord(dp, "close-file", ficlCloseFile, FW_DEFAULT);
+ dictAppendWord(dp, "include-file", ficlIncludeFile, FW_DEFAULT);
+ dictAppendWord(dp, "read-file", ficlReadFile, FW_DEFAULT);
+ dictAppendWord(dp, "read-line", ficlReadLine, FW_DEFAULT);
+ dictAppendWord(dp, "write-file", ficlWriteFile, FW_DEFAULT);
+ dictAppendWord(dp, "write-line", ficlWriteLine, FW_DEFAULT);
+ dictAppendWord(dp, "file-position", ficlFilePosition, FW_DEFAULT);
+ dictAppendWord(dp, "file-size", ficlFileSize, FW_DEFAULT);
+ dictAppendWord(dp, "reposition-file", ficlRepositionFile, FW_DEFAULT);
+ dictAppendWord(dp, "file-status", ficlFileStatus, FW_DEFAULT);
+ dictAppendWord(dp, "flush-file", ficlFlushFile, FW_DEFAULT);
+
+ dictAppendWord(dp, "delete-file", ficlDeleteFile, FW_DEFAULT);
+ dictAppendWord(dp, "rename-file", ficlRenameFile, FW_DEFAULT);
+
+#ifdef FICL_HAVE_FTRUNCATE
+ dictAppendWord(dp, "resize-file", ficlResizeFile, FW_DEFAULT);
+
+ ficlSetEnv(pSys, "file", FICL_TRUE);
+ ficlSetEnv(pSys, "file-ext", FICL_TRUE);
+#endif /* FICL_HAVE_FTRUNCATE */
+#else
+ &pSys;
+#endif /* FICL_WANT_FILE */
+}
--- a/float.c
+++ b/float.c
@@ -4,7 +4,7 @@
** ANS Forth FLOAT word-set written in C
** Author: Guy Carver & John Sadler (john_sadler@alum.mit.edu)
** Created: Apr 2001
-** $Id: float.c,v 1.5 2001/07/24 05:01:24 jsadler Exp $
+** $Id: float.c,v 1.6 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -62,7 +62,8 @@
vmCheckFStack(pVM, 2, 1);
#endif
- f = POPFLOAT() + GETTOPF().f;
+ f = POPFLOAT();
+ f += GETTOPF().f;
SETTOPF(f);
}
@@ -95,7 +96,8 @@
vmCheckFStack(pVM, 2, 1);
#endif
- f = POPFLOAT() * GETTOPF().f;
+ f = POPFLOAT();
+ f *= GETTOPF().f;
SETTOPF(f);
}
@@ -145,7 +147,8 @@
vmCheckStack(pVM, 1, 0);
#endif
- f = (FICL_FLOAT)POPINT() + GETTOPF().f;
+ f = (FICL_FLOAT)POPINT();
+ f += GETTOPF().f;
SETTOPF(f);
}
@@ -162,7 +165,8 @@
vmCheckStack(pVM, 1, 0);
#endif
- f = GETTOPF().f - (FICL_FLOAT)POPINT();
+ f = GETTOPF().f;
+ f -= (FICL_FLOAT)POPINT();
SETTOPF(f);
}
@@ -179,7 +183,8 @@
vmCheckStack(pVM, 1, 0);
#endif
- f = (FICL_FLOAT)POPINT() * GETTOPF().f;
+ f = (FICL_FLOAT)POPINT();
+ f *= GETTOPF().f;
SETTOPF(f);
}
@@ -196,7 +201,8 @@
vmCheckStack(pVM, 1, 0);
#endif
- f = GETTOPF().f / (FICL_FLOAT)POPINT();
+ f = GETTOPF().f;
+ f /= (FICL_FLOAT)POPINT();
SETTOPF(f);
}
@@ -213,7 +219,8 @@
vmCheckStack(pVM, 1, 0);
#endif
- f = (FICL_FLOAT)POPINT() - GETTOPF().f;
+ f = (FICL_FLOAT)POPINT();
+ f -= GETTOPF().f;
SETTOPF(f);
}
@@ -230,7 +237,8 @@
vmCheckStack(pVM, 1, 0);
#endif
- f = (FICL_FLOAT)POPINT() / GETTOPF().f;
+ f = (FICL_FLOAT)POPINT();
+ f /= GETTOPF().f;
SETTOPF(f);
}
@@ -1034,8 +1042,6 @@
ficlSetEnv(pSys, "floating", FICL_FALSE); /* not all required words are present */
ficlSetEnv(pSys, "floating-ext", FICL_FALSE);
ficlSetEnv(pSys, "floating-stack", FICL_DEFAULT_STACK);
-
- ficlAddPrecompiledParseStep(pSys, ">float", ficlParseFloatNumber);
#endif
return;
}
\ No newline at end of file
--- a/math64.c
+++ b/math64.c
@@ -5,7 +5,7 @@
** Created: 25 January 1998
** Rev 2.03: Support for 128 bit DP math. This file really ouught to
** be renamed!
-** $Id: math64.c,v 1.6 2001/05/16 14:56:16 jsadler Exp $
+** $Id: math64.c,v 1.7 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
--- a/math64.h
+++ b/math64.h
@@ -3,7 +3,7 @@
** Forth Inspired Command Language - 64 bit math support routines
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 25 January 1998
-** $Id: math64.h,v 1.6 2001/05/16 14:56:19 jsadler Exp $
+** $Id: math64.h,v 1.7 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
--- a/prefix.c
+++ b/prefix.c
@@ -4,7 +4,7 @@
** Parser extensions for Ficl
** Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu)
** Created: April 2001
-** $Id: prefix.c,v 1.3 2001/06/12 08:24:38 jsadler Exp $
+** $Id: prefix.c,v 1.4 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -179,7 +179,7 @@
dictAppendWord(dp, "0x", prefixHex, FW_DEFAULT);
dictAppendWord(dp, "0d", prefixTen, FW_DEFAULT);
#if (FICL_EXTENDED_PREFIX)
- pFW = ficlLookup("\\");
+ pFW = ficlLookup(pSys, "\\");
if (pFW)
{
dictAppendWord(dp, "//", pFW->code, FW_DEFAULT);
@@ -187,6 +187,5 @@
#endif
dp->pCompile = pPrevCompile;
- ficlAddPrecompiledParseStep(pSys, "?prefix", ficlParsePrefix);
return;
}
--- a/search.c
+++ b/search.c
@@ -4,7 +4,7 @@
** ANS Forth SEARCH and SEARCH-EXT word-set written in C
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 6 June 2000
-** $Id: search.c,v 1.6 2001/06/12 08:24:34 jsadler Exp $
+** $Id: search.c,v 1.7 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
--- a/softcore.c
+++ b/softcore.c
@@ -4,7 +4,7 @@
** Words from CORE set written in FICL
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 27 December 1997
-** Last update: Sat Jul 21 17:31:36 2001
+** Last update: Sat Aug 4 16:47:07 2001
*******************************************************************/
/*
** DO NOT EDIT THIS FILE -- it is generated by softwords/softcore.pl
@@ -188,6 +188,27 @@
"; "
": debug ' debug-xt ; "
": on-step .\" S: \" .s cr ; "
+ ": strdup "
+ "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 "
+ "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 "
+ "locals| b-u b-addr a-u a-addr | end-locals "
+ "a-addr 0 b-addr b-u strcat "
+ "; "
"previous "
/*
** E N D S O F T C O R E . F R
@@ -317,21 +338,14 @@
*/
"hide "
": ?[if] "
- "2dup 2dup "
- "s\" [if]\" compare 0= >r "
- "s\" [IF]\" compare 0= r> "
- "or "
+ "2dup s\" [if]\" compare-insensitive 0= "
"; "
": ?[else] "
- "2dup 2dup "
- "s\" [else]\" compare 0= >r "
- "s\" [ELSE]\" compare 0= r> "
- "or "
+ "2dup s\" [else]\" compare-insensitive 0= "
"; "
": ?[then] "
- "2dup 2dup "
- "s\" [then]\" compare 0= >r "
- "s\" [THEN]\" compare 0= r> "
+ "2dup s\" [then]\" compare-insensitive 0= >r "
+ "2dup s\" [endif]\" compare-insensitive 0= r> "
"or "
"; "
"set-current "
@@ -356,6 +370,7 @@
": [if] "
"0= if postpone [else] then ; immediate "
": [then] ; immediate "
+ ": [endif] ; immediate "
"previous "
#if FICL_WANT_OOP
/*
@@ -961,6 +976,28 @@
"end-class "
"previous definitions "
#endif
+#if FICL_WANT_FILE
+/*
+**
+** 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 "
+ "locals| f | end-locals "
+ "f include-file "
+ "f close-file drop "
+ "else "
+ "drop "
+ "endif "
+ "; "
+ ": include parse-word included ; immediate "
+#endif
#endif /* WANT_SOFTWORDS */
"quit ";
@@ -968,10 +1005,12 @@
void ficlCompileSoftCore(FICL_SYSTEM *pSys)
{
FICL_VM *pVM = pSys->vmList;
+ CELL id = pVM->sourceID;
int ret = sizeof (softWords);
- assert(pVM);
-
+ assert(pVM);
+ pVM->sourceID.i = -1;
ret = ficlExec(pVM, softWords);
+ pVM->sourceID = id;
if (ret == VM_ERREXIT)
assert(FALSE);
return;
--- /dev/null
+++ b/softwords/fileaccess.fr
@@ -1,0 +1,24 @@
+\ #if FICL_WANT_FILE
+\ **
+\ ** 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
+ locals| f | end-locals
+ f include-file
+ f close-file drop
+ else
+ drop
+ endif
+ ;
+
+: include parse-word included ; immediate
+
+\ #endif
--- a/softwords/ifbrack.fr
+++ b/softwords/ifbrack.fr
@@ -5,23 +5,16 @@
hide
: ?[if] ( c-addr u -- c-addr u flag )
- 2dup 2dup
- s" [if]" compare 0= >r
- s" [IF]" compare 0= r>
- or
+ 2dup s" [if]" compare-insensitive 0=
;
: ?[else] ( c-addr u -- c-addr u flag )
- 2dup 2dup
- s" [else]" compare 0= >r
- s" [ELSE]" compare 0= r>
- or
+ 2dup s" [else]" compare-insensitive 0=
;
: ?[then] ( c-addr u -- c-addr u flag )
- 2dup 2dup
- s" [then]" compare 0= >r
- s" [THEN]" compare 0= r>
+ 2dup s" [then]" compare-insensitive 0= >r
+ 2dup s" [endif]" compare-insensitive 0= r>
or
;
@@ -50,5 +43,6 @@
0= if postpone [else] then ; immediate
: [then] ( -- ) ; immediate
+: [endif] ( -- ) ; immediate
previous
--- a/softwords/makefile
+++ b/softwords/makefile
@@ -1,4 +1,4 @@
-SOURCES = softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr
+SOURCES = softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr fileaccess.fr
softcore.c: softcore.pl $(SOURCES)
./softcore.pl $(SOURCES) >softcore.c
--- a/softwords/oo.fr
+++ b/softwords/oo.fr
@@ -29,8 +29,7 @@
\ A ficl object binds instance storage (payload) to a class.
\ object ( -- instance class )
\ All objects push their payload address and class address when
-\ executed. All objects have this footprint:
-\ cell 0: first payload cell
+\ 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
@@ -42,14 +41,39 @@
\ cell 2: size of instance's payload
\ Methods expect an object couple ( instance class )
-\ on the stack.
+\ 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, though.
+\ 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 August 2001 - 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 !
@@ -57,17 +81,25 @@
\ ** 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...
-\ parse-method compiles the method name so that it pushes
-\ the string base address and count at run-time.
\
hide
+\ 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
+\ 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 }
name class cell+ @ ( c-addr u wid )
search-wordlist ( 0 | xt 1 | xt -1 )
@@ -116,6 +148,11 @@
\ 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 ;
--- a/softwords/softcore.bat
+++ b/softwords/softcore.bat
@@ -1,1 +1,1 @@
-perl softcore.pl softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr >..\softcore.c
+perl softcore.pl softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr fileaccess.fr >..\softcore.c
--- a/softwords/softcore.fr
+++ b/softwords/softcore.fr
@@ -171,6 +171,33 @@
: debug ' debug-xt ;
: on-step ." S: " .s cr ;
+
+\ 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
+ ;
+
+
previous \ lose hidden words from search order
\ ** E N D S O F T C O R E . F R
--- a/softwords/softcore.pl
+++ b/softwords/softcore.pl
@@ -127,10 +127,12 @@
void ficlCompileSoftCore(FICL_SYSTEM *pSys)
{
FICL_VM *pVM = pSys->vmList;
+ CELL id = pVM->sourceID;
int ret = sizeof (softWords);
- assert(pVM);
-
+ assert(pVM);
+ pVM->sourceID.i = -1;
ret = ficlExec(pVM, softWords);
+ pVM->sourceID = id;
if (ret == VM_ERREXIT)
assert(FALSE);
return;
--- /dev/null
+++ b/softwords/softcore.py
@@ -1,0 +1,152 @@
+#! python
+# Convert forth source files to a giant C string
+
+import re;
+import sys;
+import time;
+
+
+print """/*******************************************************************
+** s o f t c o r e . c
+** Forth Inspired Command Language -
+** Words from CORE set written in FICL
+** Author: John Sadler (john_sadler@alum.mit.edu)
+** Created: 27 December 1997
+** Last update: """ + time.ctime(time.time()) + """
+*******************************************************************/
+/*
+** DO NOT EDIT THIS FILE -- it is generated by softwords/softcore.pl
+** Make changes to the .fr files in ficl/softwords instead.
+** This file contains definitions that are compiled into the
+** system dictionary by the first virtual machine to be created.
+** Created automagically by ficl/softwords/softcore.pl
+*/
+/*
+** 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 send
+** 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"
+
+static char softWords[] =
+#if FICL_WANT_SOFTWORDS"""
+
+escapedQuotes = re.compile( r'^"(.*)"$' )
+backslash = re.compile( r'^(.*[^\s])\s+\\(\s+[^\s].*)$' )
+parentheses = re.compile( r'^(.*[^\s])\s+\(\s[^)]+\)(\s+[^\s].*)?$' )
+
+
+commenting = 0;
+
+for a in (sys.argv[1:]):
+ f = open(a)
+ for line in f.readlines():
+
+ # trim all whitespace
+ line = line.strip();
+
+ # remove quotes around quoted lines
+ quoted = escapedQuotes.match(line)
+ if (quoted != None):
+ line = quoted.group(1).strip()
+
+ #
+ # emit lines beginnning with "\ **" as C comments
+ #
+ if (line[0:4] == "\\ **"):
+ if (commenting == 0):
+ print("/*")
+ commenting = 1
+ print(line[2:])
+ continue
+
+ if (commenting == 1):
+ print "*/"
+
+ commenting = 0
+
+ # ignore empty lines
+ if (len(line) == 0):
+ continue
+
+ # pass commented preprocessor directives
+ # == lines starting with "\ #"
+ # (supports single line directives only)
+ if (line[0:3] == "\\ #"):
+ print(line[2:]) # include the leading #!
+ continue
+
+ # ignore remaining lines starting with comments
+ if (line[0] == "\\"):
+ continue
+
+ # remove trailing comments
+ trailingComment = backslash.match(line)
+ if (trailingComment != None):
+ line = trailingComment.group(1)
+
+ # remove ( comments ) in the middle
+ embeddedComment = parentheses.match(line)
+ if (embeddedComment != None):
+ line = embeddedComment.group(1)
+ if (embeddedComment.lastindex >= 2):
+ line = line + " " + embeddedComment.group(2).strip()
+
+ # quote double-quote characters
+ line = line.replace("\"", "\\\"")
+
+ # emit whatever's left as quoted string fragments
+ print(" \"" + line + " \"");
+
+
+print """#endif /* WANT_SOFTWORDS */
+ "quit ";
+
+
+void ficlCompileSoftCore(FICL_SYSTEM *pSys)
+{
+ FICL_VM *pVM = pSys->vmList;
+ CELL id = pVM->sourceID;
+ int ret = sizeof (softWords);
+ assert(pVM);
+ pVM->sourceID.i = -1;
+ ret = ficlExec(pVM, softWords);
+ pVM->sourceID = id;
+ if (ret == VM_ERREXIT)
+ assert(FALSE);
+ return;
+}
+
+
+"""
--- /dev/null
+++ b/softwords/softcore.py.bat
@@ -1,0 +1,1 @@
+python softcore.py softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr fileaccess.fr >..\softcore.c
--- a/stack.c
+++ b/stack.c
@@ -3,7 +3,7 @@
** Forth Inspired Command Language
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 16 Oct 1997
-** $Id: stack.c,v 1.7 2001/06/12 08:24:35 jsadler Exp $
+** $Id: stack.c,v 1.8 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
--- a/sysdep.c
+++ b/sysdep.c
@@ -6,7 +6,7 @@
** Implementations of FICL external interface functions...
**
** (simple) port to Linux, Skip Carter 26 March 1998
-** $Id: sysdep.c,v 1.9 2001/07/24 05:01:24 jsadler Exp $
+** $Id: sysdep.c,v 1.10 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
--- a/sysdep.h
+++ b/sysdep.h
@@ -9,7 +9,7 @@
** FICL_ROBUST is enabled. This may require some consideration
** in firmware systems since assert often
** assumes stderr/stdout.
-** $Id: sysdep.h,v 1.7 2001/05/16 14:56:18 jsadler Exp $
+** $Id: sysdep.h,v 1.8 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -54,11 +54,20 @@
#include <assert.h>
#if defined(_WIN32)
- #define alloca(x) _alloca(x)
+ #include <stdio.h>
+ #ifndef alloca
+ #define alloca(x) _alloca(x)
+ #endif /* alloca */
#define stat _stat
#define getcwd _getcwd
#define chdir _chdir
+ #define unlink _unlink
+ #define fileno _fileno
+
+ #define FICL_HAVE_FTRUNCATE 1
+ extern int ftruncate(int fileno, size_t size);
#elif defined(linux)
+ #define FICL_HAVE_FTRUNCATE 1
#endif /* platform */
#if !defined IGNORE /* Macro to silence unused param warnings */
@@ -88,7 +97,6 @@
#define FICL_UNS unsigned long
#define BITS_PER_CELL 64
#define FICL_ALIGN 3
-
#endif
/*
@@ -177,6 +185,7 @@
#endif
#if (FICL_MINIMAL)
#define FICL_WANT_SOFTWORDS 0
+#define FICL_WANT_FILE 0
#define FICL_WANT_FLOAT 0
#define FICL_WANT_USER 0
#define FICL_WANT_LOCALS 0
@@ -190,9 +199,9 @@
/*
** FICL_PLATFORM_EXTEND
-** Includes words defined in ficlCompilePlatform (see win32.c for example)
+** Includes words defined in ficlCompilePlatform (see win32.c and unix.c for example)
*/
-#ifdef _WIN32
+#if defined (_WIN32)
#if !defined (FICL_PLATFORM_EXTEND)
#define FICL_PLATFORM_EXTEND 1
#endif
@@ -202,7 +211,18 @@
#define FICL_PLATFORM_EXTEND 0
#endif
+
/*
+** FICL_WANT_FILE
+** Includes the FILE and FILE-EXT wordset and associated code. Turn this off if you do not
+** have a file system!
+** Contributed by Larry Hastings
+*/
+#if !defined (FICL_WANT_FILE)
+#define FICL_WANT_FILE 1
+#endif
+
+/*
** FICL_WANT_FLOAT
** Includes a floating point stack for the VM, and words to do float operations.
** Contributed by Guy Carver
@@ -220,6 +240,14 @@
#endif
/*
+** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if
+** included as part of softcore.c)
+*/
+#if !defined FICL_EXTENDED_PREFIX
+#define FICL_EXTENDED_PREFIX 0
+#endif
+
+/*
** User variables: per-instance variables bound to the VM.
** Kinda like thread-local storage. Could be implemented in a
** VM private dictionary, but I've chosen the lower overhead
@@ -339,7 +367,7 @@
#endif
#if !defined FICL_DEFAULT_ENV
-#define FICL_DEFAULT_ENV 260
+#define FICL_DEFAULT_ENV 512
#endif
/*
@@ -362,14 +390,6 @@
#endif
/*
-** FICL_EXTENDED_PREFIX enables a bunch of extra prefixes in prefix.c and prefix.fr (if
-** included as part of softcore.c)
-*/
-#if !defined FICL_EXTENDED_PREFIX
-#define FICL_EXTENDED_PREFIX 0
-#endif
-
-/*
** FICL_ALIGN is the power of two to which the dictionary
** pointer address must be aligned. This value is usually
** either 1 or 2, depending on the memory architecture
@@ -429,5 +449,16 @@
*/
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
+
+
+/*
+** FICL_HAVE_FTRUNCATE indicates whether the current OS supports
+** the ftruncate() function (available on most UNIXes). This
+** function is necessary to provide the complete File-Access wordset.
+*/
+#if !defined (FICL_HAVE_FTRUNCATE)
+#define FICL_HAVE_FTRUNCATE 0
+#endif
+
#endif /*__SYSDEP_H__*/
--- a/test/ficltest.fr
+++ b/test/ficltest.fr
@@ -71,6 +71,7 @@
{ exctest? abort -> -1 }
testing refill
+\ from file loading
0 [if]
.( Error )
[else]
@@ -80,6 +81,11 @@
[then]
[then]
+\ refill from evaluate string
+{ -> }
+{ s" 1 refill 2 " evaluate -> 1 0 2 }
+
+
testing prefixes
{ 0x10 -> decimal 16 }
{ hex 0d10 -> decimal 10 }
@@ -86,4 +92,15 @@
{ hex 100
-> decimal 256 }
+testing number builder
+{ 1 -> 1 }
+{ 3. -> 0 3 }
+
+
+s" ficlwin" environment?
+[if]
+drop
+testing OOP support
load ooptest.fr
+[endif]
+
--- a/testmain.c
+++ b/testmain.c
@@ -1,6 +1,6 @@
/*
** stub main for testing FICL under Win32
-** $Id: testmain.c,v 1.10 2001/06/12 08:24:37 jsadler Exp $
+** $Id: testmain.c,v 1.11 2001/11/05 02:09:28 jsadler Exp $
*/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -326,7 +326,7 @@
buildTestInterface(pSys);
pVM = ficlNewVM(pSys);
- ret = ficlExec(pVM, ".ver .( " __DATE__ " ) cr quit");
+ ret = ficlEvaluate(pVM, ".ver .( " __DATE__ " ) cr quit");
/*
** load file from cmd line...
@@ -336,7 +336,7 @@
sprintf(in, ".( loading %s ) cr load %s\n cr", argv[1], argv[1]);
__try
{
- ret = ficlExec(pVM, in);
+ ret = ficlEvaluate(pVM, in);
}
__except(1)
{
--- a/tools.c
+++ b/tools.c
@@ -3,7 +3,7 @@
** Forth Inspired Command Language - programming tools
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 20 June 2000
-** $Id: tools.c,v 1.8 2001/06/12 08:24:37 jsadler Exp $
+** $Id: tools.c,v 1.9 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -70,30 +70,13 @@
#endif
-/*
-** BREAKPOINT record.
-** origXT - if NULL, this breakpoint is unused. Otherwise it stores the xt
-** that the breakpoint overwrote. This is restored to the dictionary when the
-** BP executes or gets cleared
-** address - the location of the breakpoint (address of the instruction that
-** has been replaced with the breakpoint trap
-** origXT - The original contents of the location with the breakpoint
-** Note: address is NULL when this breakpoint is empty
-*/
-typedef struct breakpoint
-{
- void *address;
- FICL_WORD *origXT;
-} BREAKPOINT;
-static BREAKPOINT bpStep = {NULL, NULL};
-
/**************************************************************************
v m S e t B r e a k
** Set a breakpoint at the current value of IP by
** storing that address in a BREAKPOINT record
**************************************************************************/
-static void vmSetBreak(FICL_VM *pVM, BREAKPOINT *pBP)
+static void vmSetBreak(FICL_VM *pVM, FICL_BREAKPOINT *pBP)
{
FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break");
assert(pStep);
@@ -234,6 +217,13 @@
sprintf(cp, " s\" %.*s\"", sp->count, sp->text);
}
break;
+ case CSTRINGLIT:
+ {
+ FICL_STRING *sp = (FICL_STRING *)(void *)++pc;
+ pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1;
+ sprintf(cp, " c\" %.*s\"", sp->count, sp->text);
+ }
+ break;
case IF:
c = *++pc;
if (c.i > 0)
@@ -320,10 +310,12 @@
vmTextOut(pVM, pVM->pad, 1);
break;
+#if FICL_WANT_USER
case USER:
sprintf(pVM->pad, "user variable %ld (%#lx)", pFW->param->i, pFW->param->u);
vmTextOut(pVM, pVM->pad, 1);
break;
+#endif
case CONSTANT:
sprintf(pVM->pad, "constant = %ld (%#lx)", pFW->param->i, pFW->param->u);
@@ -381,7 +373,7 @@
** Run the colon code and set a breakpoint at the next instruction
*/
vmExecute(pVM, xt);
- vmSetBreak(pVM, &bpStep);
+ vmSetBreak(pVM, &(pVM->pSys->bpStep));
break;
default:
@@ -411,7 +403,7 @@
/*
** Now set a breakpoint at the next instruction
*/
- vmSetBreak(pVM, &bpStep);
+ vmSetBreak(pVM, &(pVM->pSys->bpStep));
return;
}
@@ -442,8 +434,8 @@
** assume that the next cell holds an instruction
** set a breakpoint there and return to the inner interp
*/
- bpStep.address = pVM->ip + 1;
- bpStep.origXT = pVM->ip[1];
+ pVM->pSys->bpStep.address = pVM->ip + 1;
+ pVM->pSys->bpStep.origXT = pVM->ip[1];
pVM->ip[1] = pStep;
break;
@@ -480,15 +472,15 @@
if (!pVM->fRestart)
{
- assert(bpStep.address);
- assert(bpStep.origXT);
+ assert(pVM->pSys->bpStep.address);
+ assert(pVM->pSys->bpStep.origXT);
/*
** Clear the breakpoint that caused me to run
** Restore the original instruction at the breakpoint,
** and restore the IP
*/
- pVM->ip = (IPTYPE)bpStep.address;
- *pVM->ip = bpStep.origXT;
+ pVM->ip = (IPTYPE)(pVM->pSys->bpStep.address);
+ *pVM->ip = pVM->pSys->bpStep.origXT;
/*
** If there's an onStep, do it
@@ -500,7 +492,7 @@
/*
** Print the name of the next instruction
*/
- pFW = bpStep.origXT;
+ pFW = pVM->pSys->bpStep.origXT;
sprintf(pVM->pad, "next: %.*s", pFW->nName, pFW->name);
if (isPrimitive(pFW))
{
@@ -784,7 +776,7 @@
**************************************************************************/
static void listEnv(FICL_VM *pVM)
{
- FICL_DICT *dp = vmGetDict(pVM);
+ FICL_DICT *dp = pVM->pSys->envp;
FICL_HASH *pHash = dp->pForthWords;
FICL_WORD *wp;
unsigned i;
@@ -853,7 +845,6 @@
/*
** TOOLS and TOOLS EXT
*/
- dictAppendWord(dp, "r.s", displayRStack, FW_DEFAULT); /* guy carver */
dictAppendWord(dp, ".s", displayPStack, FW_DEFAULT);
dictAppendWord(dp, "bye", bye, FW_DEFAULT);
dictAppendWord(dp, "forget", forget, FW_DEFAULT);
@@ -869,6 +860,7 @@
/*
** Ficl extras
*/
+ dictAppendWord(dp, "r.s", displayRStack, FW_DEFAULT); /* guy carver */
dictAppendWord(dp, ".env", listEnv, FW_DEFAULT);
dictAppendWord(dp, "env-constant",
envConstant, FW_DEFAULT);
--- /dev/null
+++ b/unix.c
@@ -1,0 +1,21 @@
+#include <string.h>
+#include <netinet/in.h>
+
+#include "ficl.h"
+
+
+
+unsigned long ficlNtohl(unsigned long number)
+{
+ return ntohl(number);
+}
+
+
+
+
+void ficlCompilePlatform(FICL_DICT *dp)
+{
+ return;
+}
+
+
--- a/vm.c
+++ b/vm.c
@@ -3,7 +3,7 @@
** Forth Inspired Command Language - virtual machine methods
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 19 July 1997
-** $Id: vm.c,v 1.10 2001/06/12 08:24:40 jsadler Exp $
+** $Id: vm.c,v 1.11 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** This file implements the virtual machine of FICL. Each virtual
@@ -440,18 +440,6 @@
return;
}
-
-
-/**************************************************************************
- v m S t e p
-** Single step the vm - equivalent to "step into" - used for debugging
-**************************************************************************/
-#if FICL_WANT_DEBUGGER
-void vmStep(FICL_VM *pVM)
-{
- M_VM_STEP(pVM);
-}
-#endif
/**************************************************************************
--- a/win32.c
+++ b/win32.c
@@ -157,6 +157,7 @@
}
+#if 0
//**************************************************************
//Load forth file.
//ENTER: pVM = Pointer to forth virtual machine.
@@ -288,7 +289,36 @@
}
}
+#endif /* 0 */
+
+static void ficlWordGetTickCount(FICL_VM *pVM) /* ( -- ms ) */
+{
+ stackPushINT(pVM->pStack, (int)GetTickCount());
+}
+
+
+static void ficlDebugBreak(FICL_VM *pVM) /* ( -- ) */
+{
+ DebugBreak();
+ pVM = pVM;
+}
+
+
+static void ficlOutputDebugString(FICL_VM *pVM) /* ( c-addr u -- ) */
+{
+ int length = stackPopINT(pVM->pStack);
+ void *address = (void *)stackPopPtr(pVM->pStack);
+
+ char *buf = (char *)_alloca(length + 1);
+ memcpy(buf, address, length);
+ buf[length] = 0;
+
+ OutputDebugString(buf);
+}
+
+
+
/**************************************************************************
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
@@ -306,9 +336,71 @@
callNativeFunction,
FW_DEFAULT);
dictAppendWord(dp, "vcall", VCall, FW_DEFAULT);
+/*
dictAppendWord(dp, "include", include, FW_DEFAULT);
dictAppendWord(dp, "reinclude", reinclude, FW_DEFAULT);
+*/
+ dictAppendWord(dp, "GetTickCount", ficlWordGetTickCount, FW_DEFAULT);
+ dictAppendWord(dp, "debug-break", ficlDebugBreak, FW_DEFAULT);
+ dictAppendWord(dp, "output-debug-string", ficlOutputDebugString, FW_DEFAULT);
+
return;
}
+
+
+
+
+/*
+**
+** 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.
+**
+** --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 ftruncate(int fileno, size_t size)
+{
+ HANDLE hFile = (HANDLE)_osfhnd(fileno);
+ if (SetFilePointer(hFile, size, NULL, FILE_BEGIN) != size)
+ return 0;
+ return !SetEndOfFile(hFile);
+}
+
+#if 0
+unsigned long ficlNtohl(unsigned long number)
+{
+ return ntohl(number);
+}
+#endif
+
+
+
--- a/words.c
+++ b/words.c
@@ -4,7 +4,7 @@
** ANS Forth CORE word-set written in C
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 19 July 1997
-** $Id: words.c,v 1.14 2001/06/12 08:24:31 jsadler Exp $
+** $Id: words.c,v 1.15 2001/11/05 02:09:28 jsadler Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -64,46 +64,9 @@
static char destTag[] = "target";
static char origTag[] = "origin";
-/*
-** Pointers to various words in the dictionary
-** -- initialized by ficlCompileCore, below --
-** for use by compiling words. Colon definitions
-** in ficl are lists of pointers to words. A bit
-** simple-minded...
-*/
-static FICL_WORD *pBranchParen = NULL;
-static FICL_WORD *pDoParen = NULL;
-static FICL_WORD *pDoesParen = NULL;
-static FICL_WORD *pExitParen = NULL;
-static FICL_WORD *pIfParen = NULL;
-static FICL_WORD *pInterpret = NULL;
-static FICL_WORD *pLitParen = NULL;
-static FICL_WORD *pTwoLitParen = NULL;
-static FICL_WORD *pLoopParen = NULL;
-static FICL_WORD *pPLoopParen = NULL;
-static FICL_WORD *pPlusStore = NULL;
-static FICL_WORD *pQDoParen = NULL;
-static FICL_WORD *pSemiParen = NULL;
-static FICL_WORD *pStore = NULL;
-static FICL_WORD *pStringLit = NULL;
-
#if FICL_WANT_LOCALS
-static FICL_WORD *pGetLocalParen= NULL;
-static FICL_WORD *pGet2LocalParen= NULL;
-static FICL_WORD *pGetLocal0 = NULL;
-static FICL_WORD *pGetLocal1 = NULL;
-static FICL_WORD *pToLocalParen = NULL;
-static FICL_WORD *pTo2LocalParen = NULL;
-static FICL_WORD *pToLocal0 = NULL;
-static FICL_WORD *pToLocal1 = NULL;
-static FICL_WORD *pLinkParen = NULL;
-static FICL_WORD *pUnLinkParen = NULL;
-static FICL_INT nLocals = 0;
-static CELL *pMarkLocals = NULL;
-
static void doLocalIm(FICL_VM *pVM);
static void do2LocalIm(FICL_VM *pVM);
-
#endif
@@ -224,6 +187,8 @@
** Attempts to convert the NULL terminated string in the VM's pad to
** a number using the VM's current base. If successful, pushes the number
** onto the param stack and returns TRUE. Otherwise, returns FALSE.
+** (jws 8/01) Trailing decimal point causes a zero cell to be pushed. (See
+** the standard for DOUBLE wordset.
**************************************************************************/
int ficlParseNumber(FICL_VM *pVM, STRINGINFO si)
@@ -230,6 +195,7 @@
{
FICL_INT accum = 0;
char isNeg = FALSE;
+ char hasDP = FALSE;
unsigned base = pVM->base;
char *cp = SI_PTR(si);
FICL_COUNT count= (FICL_COUNT)SI_COUNT(si);
@@ -255,7 +221,13 @@
}
}
- if (count == 0)
+ if ((count > 0) && (cp[count-1] == '.')) /* detect & remove trailing decimal */
+ {
+ hasDP = TRUE;
+ count--;
+ }
+
+ if (count == 0) /* detect "+", "-", ".", "+." etc */
return FALSE;
while ((count--) && ((ch = *cp++) != '\0'))
@@ -274,6 +246,9 @@
accum = accum * base + digit;
}
+ if (hasDP) /* simple (required) DOUBLE support */
+ PUSHINT(0);
+
if (isNeg)
accum = -accum;
@@ -482,7 +457,7 @@
markControlTag(pVM, colonTag);
dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE);
#if FICL_WANT_LOCALS
- nLocals = 0;
+ pVM->pSys->nLocals = 0;
#endif
return;
}
@@ -528,21 +503,21 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pSemiParen);
+ assert(pVM->pSys->pSemiParen);
matchControlTag(pVM, colonTag);
#if FICL_WANT_LOCALS
- assert(pUnLinkParen);
- if (nLocals > 0)
+ assert(pVM->pSys->pUnLinkParen);
+ if (pVM->pSys->nLocals > 0)
{
FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
dictEmpty(pLoc, pLoc->pForthWords->size);
- dictAppendCell(dp, LVALUEtoCELL(pUnLinkParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen));
}
- nLocals = 0;
+ pVM->pSys->nLocals = 0;
#endif
- dictAppendCell(dp, LVALUEtoCELL(pSemiParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pSemiParen));
pVM->state = INTERPRET;
dictUnsmudge(dp);
return;
@@ -567,16 +542,16 @@
static void exitCoIm(FICL_VM *pVM)
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pExitParen);
+ assert(pVM->pSys->pExitParen);
IGNORE(pVM);
#if FICL_WANT_LOCALS
- if (nLocals > 0)
+ if (pVM->pSys->nLocals > 0)
{
- dictAppendCell(dp, LVALUEtoCELL(pUnLinkParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen));
}
#endif
- dictAppendCell(dp, LVALUEtoCELL(pExitParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pExitParen));
return;
}
@@ -696,6 +671,172 @@
/**************************************************************************
+ s t r l e n
+** FICL ( c-string -- length )
+**
+** Returns the length of a C-style (zero-terminated) string.
+**
+** --lch
+**/
+static void ficlStrlen(FICL_VM *ficlVM)
+ {
+ char *address = (char *)stackPopPtr(ficlVM->pStack);
+ stackPushINT(ficlVM->pStack, 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 cell 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 (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 ficlSprintf(FICL_VM *pVM) /* */
+{
+ int bufferLength = stackPopINT(pVM->pStack);
+ char *buffer = (char *)stackPopPtr(pVM->pStack);
+ char *bufferStart = buffer;
+
+ int formatLength = stackPopINT(pVM->pStack);
+ char *format = (char *)stackPopPtr(pVM->pStack);
+ char *formatStop = format + formatLength;
+
+ int base = 10;
+ int unsignedInteger = 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 = stackPopINT(pVM->pStack);
+ format++;
+ if (format == formatStop)
+ break;
+ }
+
+
+ switch (*format)
+ {
+ case 's':
+ case 'S':
+ {
+ actualLength = stackPopINT(pVM->pStack);
+ source = (char *)stackPopPtr(pVM->pStack);
+ break;
+ }
+ case 'x':
+ case 'X':
+ base = 16;
+ case 'u':
+ case 'U':
+ unsignedInteger = TRUE;
+ case 'd':
+ case 'D':
+ {
+ int integer = stackPopINT(pVM->pStack);
+ if (unsignedInteger)
+ ultoa(integer, scratch, base);
+ else
+ ltoa(integer, scratch, base);
+ base = 10;
+ unsignedInteger = 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++;
+ }
+
+ stackPushPtr(pVM->pStack, bufferStart);
+ stackPushINT(pVM->pStack, buffer - bufferStart);
+ stackPushINT(pVM->pStack, append);
+}
+
+
+/**************************************************************************
d u p & f r i e n d s
**
**************************************************************************/
@@ -1081,9 +1222,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pIfParen);
+ assert(pVM->pSys->pIfParen);
- dictAppendCell(dp, LVALUEtoCELL(pIfParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pIfParen));
markBranch(dp, pVM, origTag);
dictAppendUNS(dp, 1);
return;
@@ -1137,9 +1278,9 @@
FICL_INT offset;
FICL_DICT *dp = vmGetDict(pVM);
- assert(pBranchParen);
+ assert(pVM->pSys->pBranchParen);
/* (1) compile branch runtime */
- dictAppendCell(dp, LVALUEtoCELL(pBranchParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
matchControlTag(pVM, origTag);
patchAddr =
(CELL *)stackPopPtr(pVM->pStack); /* (2) pop "if" patch addr */
@@ -1305,7 +1446,7 @@
#endif
#if FICL_WANT_LOCALS
- if (nLocals > 0)
+ if (pVM->pSys->nLocals > 0)
{
tempFW = ficlLookupLoc(pVM->pSys, si);
}
@@ -1440,9 +1581,9 @@
static void literalIm(FICL_VM *pVM)
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pLitParen);
+ assert(pVM->pSys->pLitParen);
- dictAppendCell(dp, LVALUEtoCELL(pLitParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pLitParen));
dictAppendCell(dp, stackPop(pVM->pStack));
return;
@@ -1452,9 +1593,9 @@
static void twoLiteralIm(FICL_VM *pVM)
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pTwoLitParen);
+ assert(pVM->pSys->pTwoLitParen);
- dictAppendCell(dp, LVALUEtoCELL(pTwoLitParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pTwoLitParen));
dictAppendCell(dp, stackPop(pVM->pStack));
dictAppendCell(dp, stackPop(pVM->pStack));
@@ -1625,9 +1766,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pDoParen);
+ assert(pVM->pSys->pDoParen);
- dictAppendCell(dp, LVALUEtoCELL(pDoParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDoParen));
/*
** Allot space for a pointer to the end
** of the loop - "leave" uses this...
@@ -1665,9 +1806,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pQDoParen);
+ assert(pVM->pSys->pQDoParen);
- dictAppendCell(dp, LVALUEtoCELL(pQDoParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pQDoParen));
/*
** Allot space for a pointer to the end
** of the loop - "leave" uses this...
@@ -1735,9 +1876,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pLoopParen);
+ assert(pVM->pSys->pLoopParen);
- dictAppendCell(dp, LVALUEtoCELL(pLoopParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pLoopParen));
resolveBackBranch(dp, pVM, doTag);
resolveAbsBranch(dp, pVM, leaveTag);
return;
@@ -1748,9 +1889,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pPLoopParen);
+ assert(pVM->pSys->pPLoopParen);
- dictAppendCell(dp, LVALUEtoCELL(pPLoopParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pPLoopParen));
resolveBackBranch(dp, pVM, doTag);
resolveAbsBranch(dp, pVM, leaveTag);
return;
@@ -2176,6 +2317,42 @@
}
+static void cstringLit(FICL_VM *pVM)
+{
+ FICL_STRING *sp = (FICL_STRING *)(pVM->ip);
+
+ char *cp = sp->text;
+ cp += sp->count + 1;
+ cp = alignPtr(cp);
+ pVM->ip = (IPTYPE)(void *)cp;
+
+ stackPushPtr(pVM->pStack, sp);
+ return;
+}
+
+
+static void cstringQuoteIm(FICL_VM *pVM)
+{
+ FICL_DICT *dp = vmGetDict(pVM);
+
+ if (pVM->state == INTERPRET)
+ {
+ FICL_STRING *sp = (FICL_STRING *) dp->here;
+ vmGetString(pVM, sp, '\"');
+ stackPushPtr(pVM->pStack, sp);
+ /* move HERE past string so it doesn't get overwritten. --lch */
+ dictAllot(dp, sp->count + sizeof(FICL_COUNT));
+ }
+ else /* COMPILE state */
+ {
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pCStringLit));
+ dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"');
+ dictAlign(dp);
+ }
+
+ return;
+}
+
/**************************************************************************
d o t Q u o t e
** IMMEDIATE word that compiles a string literal for later display
@@ -2211,7 +2388,7 @@
FICL_DICT *dp = vmGetDict(pVM);
FICL_WORD *pType = ficlLookup(pVM->pSys, "type");
assert(pType);
- dictAppendCell(dp, LVALUEtoCELL(pStringLit));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit));
dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"');
dictAlign(dp);
dictAppendCell(dp, LVALUEtoCELL(pType));
@@ -2268,7 +2445,7 @@
u = POPUNS();
cp = POPPTR();
- dictAppendCell(dp, LVALUEtoCELL(pStringLit));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit));
cpDest = (char *) dp->here;
*cpDest++ = (char) u;
@@ -2360,19 +2537,19 @@
{
FICL_DICT *dp = vmGetDict(pVM);
#if FICL_WANT_LOCALS
- assert(pUnLinkParen);
- if (nLocals > 0)
+ assert(pVM->pSys->pUnLinkParen);
+ if (pVM->pSys->nLocals > 0)
{
FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
dictEmpty(pLoc, pLoc->pForthWords->size);
- dictAppendCell(dp, LVALUEtoCELL(pUnLinkParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen));
}
- nLocals = 0;
+ pVM->pSys->nLocals = 0;
#endif
IGNORE(pVM);
- dictAppendCell(dp, LVALUEtoCELL(pDoesParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDoesParen));
return;
}
@@ -2785,9 +2962,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pIfParen);
+ assert(pVM->pSys->pIfParen);
- dictAppendCell(dp, LVALUEtoCELL(pIfParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pIfParen));
resolveBackBranch(dp, pVM, destTag);
return;
}
@@ -2796,9 +2973,9 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pIfParen);
+ assert(pVM->pSys->pIfParen);
- dictAppendCell(dp, LVALUEtoCELL(pIfParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pIfParen));
markBranch(dp, pVM, origTag);
twoSwap(pVM);
dictAppendUNS(dp, 1);
@@ -2809,8 +2986,8 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pBranchParen);
- dictAppendCell(dp, LVALUEtoCELL(pBranchParen));
+ assert(pVM->pSys->pBranchParen);
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
/* expect "begin" branch marker */
resolveBackBranch(dp, pVM, destTag);
@@ -2824,8 +3001,8 @@
{
FICL_DICT *dp = vmGetDict(pVM);
- assert(pBranchParen);
- dictAppendCell(dp, LVALUEtoCELL(pBranchParen));
+ assert(pVM->pSys->pBranchParen);
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
/* expect "begin" branch marker */
resolveBackBranch(dp, pVM, destTag);
@@ -2957,7 +3134,7 @@
vmCheckStack(pVM,2,1);
#endif
- envp = ficlGetEnv(pVM->pSys);
+ envp = pVM->pSys->envp;
len = (FICL_COUNT)POPUNS();
cp = POPPTR();
@@ -3033,7 +3210,7 @@
}
else /* COMPILE state */
{
- dictAppendCell(dp, LVALUEtoCELL(pStringLit));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit));
dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"');
dictAlign(dp);
}
@@ -3202,17 +3379,10 @@
** string, the values returned by FIND while compiling may differ from
** those returned while not compiling.
**************************************************************************/
-static void find(FICL_VM *pVM)
+static void do_find(FICL_VM *pVM, STRINGINFO si, void *returnForFailure)
{
- FICL_STRING *sp;
FICL_WORD *pFW;
- STRINGINFO si;
-#if FICL_ROBUST > 1
- vmCheckStack(pVM,1,2);
-#endif
- sp = POPPTR();
- SI_PFS(si, sp);
pFW = dictLookup(vmGetDict(pVM), si);
if (pFW)
{
@@ -3221,7 +3391,7 @@
}
else
{
- PUSHPTR(sp);
+ PUSHPTR(returnForFailure);
PUSHUNS(0);
}
return;
@@ -3230,6 +3400,52 @@
/**************************************************************************
+ 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 cFind(FICL_VM *pVM)
+{
+ FICL_STRING *sp;
+ STRINGINFO si;
+
+#if FICL_ROBUST > 1
+ vmCheckStack(pVM,1,2);
+#endif
+ sp = POPPTR();
+ SI_PFS(si, sp);
+ do_find(pVM, si, sp);
+}
+
+
+
+/**************************************************************************
+ 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 sFind(FICL_VM *pVM)
+{
+ STRINGINFO si;
+
+#if FICL_ROBUST > 1
+ vmCheckStack(pVM,2,2);
+#endif
+
+ si.count = stackPopINT(pVM->pStack);
+ si.cp = stackPopPtr(pVM->pStack);
+
+ do_find(pVM, si, NULL);
+}
+
+
+
+/**************************************************************************
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.
@@ -3649,19 +3865,19 @@
FICL_WORD *pFW;
#if FICL_WANT_LOCALS
- if ((nLocals > 0) && (pVM->state == COMPILE))
+ if ((pVM->pSys->nLocals > 0) && (pVM->state == COMPILE))
{
FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
pFW = dictLookup(pLoc, si);
if (pFW && (pFW->code == doLocalIm))
{
- dictAppendCell(dp, LVALUEtoCELL(pToLocalParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pToLocalParen));
dictAppendCell(dp, LVALUEtoCELL(pFW->param[0]));
return;
}
else if (pFW && pFW->code == do2LocalIm)
{
- dictAppendCell(dp, LVALUEtoCELL(pTo2LocalParen));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pTo2LocalParen));
dictAppendCell(dp, LVALUEtoCELL(pFW->param[0]));
return;
}
@@ -3668,7 +3884,7 @@
}
#endif
- assert(pStore);
+ assert(pVM->pSys->pStore);
pFW = dictLookup(dp, si);
if (!pFW)
@@ -3683,7 +3899,7 @@
{
PUSHPTR(&pFW->param[0]);
literalIm(pVM);
- dictAppendCell(dp, LVALUEtoCELL(pStore));
+ dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStore));
}
return;
}
@@ -3785,15 +4001,15 @@
if (nLocal == 0)
{
- dictAppendCell(pDict, LVALUEtoCELL(pGetLocal0));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocal0));
}
else if (nLocal == 1)
{
- dictAppendCell(pDict, LVALUEtoCELL(pGetLocal1));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocal1));
}
else
{
- dictAppendCell(pDict, LVALUEtoCELL(pGetLocalParen));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocalParen));
dictAppendCell(pDict, LVALUEtoCELL(nLocal));
}
}
@@ -3826,7 +4042,6 @@
**************************************************************************/
static void localParen(FICL_VM *pVM)
{
- static CELL *pMark = NULL;
FICL_DICT *pDict;
STRINGINFO si;
#if FICL_ROBUST > 1
@@ -3840,38 +4055,38 @@
if (SI_COUNT(si) > 0)
{ /* add a local to the **locals** dict and update nLocals */
FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
- if (nLocals >= FICL_MAX_LOCALS)
+ if (pVM->pSys->nLocals >= FICL_MAX_LOCALS)
{
vmThrowErr(pVM, "Error: out of local space");
}
dictAppendWord2(pLoc, si, doLocalIm, FW_COMPIMMED);
- dictAppendCell(pLoc, LVALUEtoCELL(nLocals));
+ dictAppendCell(pLoc, LVALUEtoCELL(pVM->pSys->nLocals));
- if (nLocals == 0)
+ if (pVM->pSys->nLocals == 0)
{ /* compile code to create a local stack frame */
- dictAppendCell(pDict, LVALUEtoCELL(pLinkParen));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pLinkParen));
/* save location in dictionary for #locals */
- pMarkLocals = pDict->here;
- dictAppendCell(pDict, LVALUEtoCELL(nLocals));
+ pVM->pSys->pMarkLocals = pDict->here;
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
/* compile code to initialize first local */
- dictAppendCell(pDict, LVALUEtoCELL(pToLocal0));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocal0));
}
- else if (nLocals == 1)
+ else if (pVM->pSys->nLocals == 1)
{
- dictAppendCell(pDict, LVALUEtoCELL(pToLocal1));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocal1));
}
else
{
- dictAppendCell(pDict, LVALUEtoCELL(pToLocalParen));
- dictAppendCell(pDict, LVALUEtoCELL(nLocals));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocalParen));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
}
- nLocals++;
+ (pVM->pSys->nLocals)++;
}
- else if (nLocals > 0)
+ else if (pVM->pSys->nLocals > 0)
{ /* write nLocals to (link) param area in dictionary */
- *(FICL_INT *)pMarkLocals = nLocals;
+ *(FICL_INT *)(pVM->pSys->pMarkLocals) = pVM->pSys->nLocals;
}
return;
@@ -3899,7 +4114,7 @@
}
else
{
- dictAppendCell(pDict, LVALUEtoCELL(pGet2LocalParen));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGet2LocalParen));
dictAppendCell(pDict, LVALUEtoCELL(nLocal));
}
return;
@@ -3925,30 +4140,30 @@
if (SI_COUNT(si) > 0)
{ /* add a local to the **locals** dict and update nLocals */
FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
- if (nLocals >= FICL_MAX_LOCALS)
+ if (pVM->pSys->nLocals >= FICL_MAX_LOCALS)
{
vmThrowErr(pVM, "Error: out of local space");
}
dictAppendWord2(pLoc, si, do2LocalIm, FW_COMPIMMED);
- dictAppendCell(pLoc, LVALUEtoCELL(nLocals));
+ dictAppendCell(pLoc, LVALUEtoCELL(pVM->pSys->nLocals));
- if (nLocals == 0)
+ if (pVM->pSys->nLocals == 0)
{ /* compile code to create a local stack frame */
- dictAppendCell(pDict, LVALUEtoCELL(pLinkParen));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pLinkParen));
/* save location in dictionary for #locals */
- pMarkLocals = pDict->here;
- dictAppendCell(pDict, LVALUEtoCELL(nLocals));
+ pVM->pSys->pMarkLocals = pDict->here;
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
}
- dictAppendCell(pDict, LVALUEtoCELL(pTo2LocalParen));
- dictAppendCell(pDict, LVALUEtoCELL(nLocals));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pTo2LocalParen));
+ dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
- nLocals += 2;
+ pVM->pSys->nLocals += 2;
}
- else if (nLocals > 0)
+ else if (pVM->pSys->nLocals > 0)
{ /* write nLocals to (link) param area in dictionary */
- *(FICL_INT *)pMarkLocals = nLocals;
+ *(FICL_INT *)(pVM->pSys->pMarkLocals) = pVM->pSys->nLocals;
}
return;
@@ -3970,7 +4185,7 @@
** lesser numeric value than the corresponding character in the string specified
** by c-addr2 u2 and one (1) otherwise.
**************************************************************************/
-static void compareString(FICL_VM *pVM)
+static void compareInternal(FICL_VM *pVM, int caseInsensitive)
{
char *cp1, *cp2;
FICL_UNS u1, u2, uMin;
@@ -3985,7 +4200,14 @@
uMin = (u1 < u2)? u1 : u2;
for ( ; (uMin > 0) && (n == 0); uMin--)
{
- n = (int)(*cp1++ - *cp2++);
+ char c1 = *cp1++;
+ char c2 = *cp2++;
+ if (caseInsensitive)
+ {
+ c1 = (char)tolower(c1);
+ c2 = (char)tolower(c2);
+ }
+ n = (int)(c1 - c2);
}
if (n == 0)
@@ -4001,7 +4223,31 @@
}
+static void compareString(FICL_VM *pVM)
+{
+ compareInternal(pVM, FALSE);
+}
+
+
+static void compareStringInsensitive(FICL_VM *pVM)
+{
+ compareInternal(pVM, TRUE);
+}
+
+
/**************************************************************************
+ 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 pad(FICL_VM *pVM)
+{
+ stackPushPtr(pVM->pStack, pVM->pad);
+}
+
+
+/**************************************************************************
s o u r c e - i d
** CORE EXT, FILE ( -- 0 | -1 | fileid )
** Identifies the input source as follows:
@@ -4066,8 +4312,6 @@
static void ficlCatch(FICL_VM *pVM)
{
- static FICL_WORD *pQuit = NULL;
-
int except;
jmp_buf vmState;
FICL_VM VM;
@@ -4075,11 +4319,8 @@
FICL_STACK rStack;
FICL_WORD *pFW;
- if (!pQuit)
- pQuit = ficlLookup(pVM->pSys, "exit-inner");
-
assert(pVM);
- assert(pQuit);
+ assert(pVM->pSys->pExitInner);
/*
@@ -4126,7 +4367,7 @@
** the XT
*/
case 0:
- vmPushIP(pVM, &pQuit); /* Open mouth, insert emetic */
+ vmPushIP(pVM, &(pVM->pSys->pExitInner)); /* Open mouth, insert emetic */
vmExecute(pVM, pFW);
vmInnerLoop(pVM);
break;
@@ -4301,8 +4542,11 @@
{LOOP, loopParen},
{PLOOP, plusLoopParen},
{QDO, qDoParen},
+ {CSTRINGLIT, cstringLit},
{STRINGLIT, stringLit},
+#if FICL_WANT_USER
{USER, userParen},
+#endif
{VARIABLE, variableParen},
};
@@ -4331,11 +4575,12 @@
FICL_DICT *dp = pSys->dp;
assert (dp);
+
/*
** CORE word set
** see softcore.c for definitions of: abs bl space spaces abort"
*/
- pStore =
+ pSys->pStore =
dictAppendWord(dp, "!", store, FW_DEFAULT);
dictAppendWord(dp, "#", numberSign, FW_DEFAULT);
dictAppendWord(dp, "#>", numberSignGreater,FW_DEFAULT);
@@ -4388,6 +4633,7 @@
dictAppendWord(dp, "base", base, FW_DEFAULT);
dictAppendWord(dp, "begin", beginCoIm, FW_COMPIMMED);
dictAppendWord(dp, "c!", cStore, FW_DEFAULT);
+ dictAppendWord(dp, "c\"", cstringQuoteIm, FW_IMMEDIATE);
dictAppendWord(dp, "c,", cComma, FW_DEFAULT);
dictAppendWord(dp, "c@", cFetch, FW_DEFAULT);
dictAppendWord(dp, "cell+", cellPlus, FW_DEFAULT);
@@ -4412,7 +4658,7 @@
dictAppendWord(dp, "execute", execute, FW_DEFAULT);
dictAppendWord(dp, "exit", exitCoIm, FW_COMPIMMED);
dictAppendWord(dp, "fill", fill, FW_DEFAULT);
- dictAppendWord(dp, "find", find, FW_DEFAULT);
+ dictAppendWord(dp, "find", cFind, FW_DEFAULT);
dictAppendWord(dp, "fm/mod", fmSlashMod, FW_DEFAULT);
dictAppendWord(dp, "here", here, FW_DEFAULT);
dictAppendWord(dp, "hex", hex, FW_DEFAULT);
@@ -4435,6 +4681,7 @@
dictAppendWord(dp, "negate", negate, FW_DEFAULT);
dictAppendWord(dp, "or", bitwiseOr, FW_DEFAULT);
dictAppendWord(dp, "over", over, FW_DEFAULT);
+ dictAppendWord(dp, "pad", pad, FW_DEFAULT);
dictAppendWord(dp, "postpone", postponeCoIm, FW_COMPIMMED);
dictAppendWord(dp, "quit", quit, FW_DEFAULT);
dictAppendWord(dp, "r>", fromRStack, FW_COMPILE);
@@ -4470,7 +4717,7 @@
** CORE EXT word set...
** see softcore.fr for other definitions
*/
- dictAppendWord(dp, ".(", dotParen, FW_DEFAULT);
+ dictAppendWord(dp, ".(", dotParen, FW_IMMEDIATE);
dictAppendWord(dp, ":noname", colonNoName, FW_DEFAULT);
dictAppendWord(dp, "2>r", twoToR, FW_COMPILE);
dictAppendWord(dp, "2r>", twoRFrom, FW_COMPILE);
@@ -4528,28 +4775,28 @@
** see softcore.c for implementation of locals|
*/
#if FICL_WANT_LOCALS
- pLinkParen =
+ pSys->pLinkParen =
dictAppendWord(dp, "(link)", linkParen, FW_COMPILE);
- pUnLinkParen =
+ pSys->pUnLinkParen =
dictAppendWord(dp, "(unlink)", unlinkParen, FW_COMPILE);
dictAppendWord(dp, "doLocal", doLocalIm, FW_COMPIMMED);
- pGetLocalParen =
+ pSys->pGetLocalParen =
dictAppendWord(dp, "(@local)", getLocalParen, FW_COMPILE);
- pToLocalParen =
+ pSys->pToLocalParen =
dictAppendWord(dp, "(toLocal)", toLocalParen, FW_COMPILE);
- pGetLocal0 =
+ pSys->pGetLocal0 =
dictAppendWord(dp, "(@local0)", getLocal0, FW_COMPILE);
- pToLocal0 =
+ pSys->pToLocal0 =
dictAppendWord(dp, "(toLocal0)",toLocal0, FW_COMPILE);
- pGetLocal1 =
+ pSys->pGetLocal1 =
dictAppendWord(dp, "(@local1)", getLocal1, FW_COMPILE);
- pToLocal1 =
+ pSys->pToLocal1 =
dictAppendWord(dp, "(toLocal1)",toLocal1, FW_COMPILE);
dictAppendWord(dp, "(local)", localParen, FW_COMPILE);
- pGet2LocalParen =
+ pSys->pGet2LocalParen =
dictAppendWord(dp, "(@2local)", get2LocalParen, FW_COMPILE);
- pTo2LocalParen =
+ pSys->pTo2LocalParen =
dictAppendWord(dp, "(to2Local)",to2LocalParen, FW_COMPILE);
dictAppendWord(dp, "(2local)", twoLocalParen, FW_COMPILE);
@@ -4580,9 +4827,18 @@
ficlCompileTools(pSys);
/*
+ ** FILE and FILE EXT
+ */
+#if FICL_WANT_FILE
+ ficlCompileFile(pSys);
+#endif
+
+ /*
** Ficl extras
*/
+#if FICL_WANT_FLOAT
dictAppendWord(dp, ".hash", dictHashSummary,FW_DEFAULT);
+#endif
dictAppendWord(dp, ".ver", ficlVersion, FW_DEFAULT);
dictAppendWord(dp, "-roll", minusRoll, FW_DEFAULT);
dictAppendWord(dp, ">name", toName, FW_DEFAULT);
@@ -4590,6 +4846,7 @@
addParseStep, FW_DEFAULT);
dictAppendWord(dp, "body>", fromBody, FW_DEFAULT);
dictAppendWord(dp, "compare", compareString, FW_DEFAULT); /* STRING */
+ dictAppendWord(dp, "compare-insensitive", compareStringInsensitive, FW_DEFAULT); /* STRING */
dictAppendWord(dp, "compile-only",
compileOnly, FW_DEFAULT);
dictAppendWord(dp, "endif", endifCoIm, FW_COMPIMMED);
@@ -4596,7 +4853,10 @@
dictAppendWord(dp, "last-word", getLastWord, FW_DEFAULT);
dictAppendWord(dp, "hash", hash, FW_DEFAULT);
dictAppendWord(dp, "parse-word",parseNoCopy, FW_DEFAULT);
+ dictAppendWord(dp, "sfind", sFind, FW_DEFAULT);
dictAppendWord(dp, "sliteral", sLiteralCoIm, FW_COMPIMMED); /* STRING */
+ dictAppendWord(dp, "sprintf", ficlSprintf, FW_DEFAULT);
+ dictAppendWord(dp, "strlen", ficlStrlen, FW_DEFAULT);
dictAppendWord(dp, "q@", quadFetch, FW_DEFAULT);
dictAppendWord(dp, "q!", quadStore, FW_DEFAULT);
dictAppendWord(dp, "w@", wFetch, FW_DEFAULT);
@@ -4606,35 +4866,38 @@
dictAppendWord(dp, "(user)", userParen, FW_DEFAULT);
dictAppendWord(dp, "user", userVariable, FW_DEFAULT);
#endif
+
/*
** internal support words
*/
dictAppendWord(dp, "(create)", createParen, FW_COMPILE);
- pExitParen =
+ pSys->pExitParen =
dictAppendWord(dp, "(exit)", exitParen, FW_COMPILE);
- pSemiParen =
+ pSys->pSemiParen =
dictAppendWord(dp, "(;)", semiParen, FW_COMPILE);
- pLitParen =
+ pSys->pLitParen =
dictAppendWord(dp, "(literal)", literalParen, FW_COMPILE);
- pTwoLitParen =
+ pSys->pTwoLitParen =
dictAppendWord(dp, "(2literal)",twoLitParen, FW_COMPILE);
- pStringLit =
+ pSys->pStringLit =
dictAppendWord(dp, "(.\")", stringLit, FW_COMPILE);
- pIfParen =
+ pSys->pCStringLit =
+ dictAppendWord(dp, "(c\")", cstringLit, FW_COMPILE);
+ pSys->pIfParen =
dictAppendWord(dp, "(if)", ifParen, FW_COMPILE);
- pBranchParen =
+ pSys->pBranchParen =
dictAppendWord(dp, "(branch)", branchParen, FW_COMPILE);
- pDoParen =
+ pSys->pDoParen =
dictAppendWord(dp, "(do)", doParen, FW_COMPILE);
- pDoesParen =
+ pSys->pDoesParen =
dictAppendWord(dp, "(does>)", doesParen, FW_COMPILE);
- pQDoParen =
+ pSys->pQDoParen =
dictAppendWord(dp, "(?do)", qDoParen, FW_COMPILE);
- pLoopParen =
+ pSys->pLoopParen =
dictAppendWord(dp, "(loop)", loopParen, FW_COMPILE);
- pPLoopParen =
+ pSys->pPLoopParen =
dictAppendWord(dp, "(+loop)", plusLoopParen, FW_COMPILE);
- pInterpret =
+ pSys->pInterpret =
dictAppendWord(dp, "interpret", interpret, FW_DEFAULT);
dictAppendWord(dp, "lookup", lookup, FW_DEFAULT);
dictAppendWord(dp, "(variable)",variableParen, FW_COMPILE);
@@ -4641,7 +4904,15 @@
dictAppendWord(dp, "(constant)",constantParen, FW_COMPILE);
dictAppendWord(dp, "(parse-step)",
parseStepParen, FW_DEFAULT);
+ pSys->pExitInner =
dictAppendWord(dp, "exit-inner",ficlExitInner, FW_DEFAULT);
+
+ /*
+ ** Set up system's outer interpreter loop - maybe this should be in initSystem?
+ */
+ pSys->pInterp[0] = pSys->pInterpret;
+ pSys->pInterp[1] = pSys->pBranchParen;
+ pSys->pInterp[2] = (FICL_WORD *)(void *)(-2);
assert(dictCellsAvail(dp) > 0);