Index: vendor/ficl/dist/dict.c =================================================================== --- vendor/ficl/dist/dict.c (revision 282802) +++ vendor/ficl/dist/dict.c (nonexistent) @@ -1,836 +0,0 @@ -/******************************************************************* -** d i c t . c -** Forth Inspired Command Language - dictionary methods -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** $Id: dict.c,v 1.12 2001-10-28 10:59:22-08 jsadler Exp jsadler $ -*******************************************************************/ -/* -** This file implements the dictionary -- FICL's model of -** memory management. All FICL words are stored in the -** dictionary. A word is a named chunk of data with its -** associated code. FICL treats all words the same, even -** precompiled ones, so your words become first-class -** extensions of the language. You can even define new -** control structures. -** -** 29 jun 1998 (sadler) added variable sized hash table support -*/ -/* -** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) -** All rights reserved. -** -** Get the latest Ficl release at http://ficl.sourceforge.net -** -** I am interested in hearing from anyone who uses ficl. If you have -** a problem, a success story, a defect, an enhancement request, or -** if you would like to contribute to the ficl release, please -** contact me by email at the address above. -** -** L I C E N S E and D I S C L A I M E R -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -** SUCH DAMAGE. -*/ - -#include -#include /* sprintf */ -#include -#include -#include "ficl.h" - -static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si); - -/************************************************************************** - d i c t A b o r t D e f i n i t i o n -** Abort a definition in process: reclaim its memory and unlink it -** from the dictionary list. Assumes that there is a smudged -** definition in process...otherwise does nothing. -** NOTE: this function is not smart enough to unlink a word that -** has been successfully defined (ie linked into a hash). It -** only works for defs in process. If the def has been unsmudged, -** nothing happens. -**************************************************************************/ -void dictAbortDefinition(FICL_DICT *pDict) -{ - FICL_WORD *pFW; - ficlLockDictionary(TRUE); - pFW = pDict->smudge; - - if (pFW->flags & FW_SMUDGE) - pDict->here = (CELL *)pFW->name; - - ficlLockDictionary(FALSE); - return; -} - - -/************************************************************************** - a l i g n P t r -** Aligns the given pointer to FICL_ALIGN address units. -** Returns the aligned pointer value. -**************************************************************************/ -void *alignPtr(void *ptr) -{ -#if FICL_ALIGN > 0 - char *cp; - CELL c; - cp = (char *)ptr + FICL_ALIGN_ADD; - c.p = (void *)cp; - c.u = c.u & (~FICL_ALIGN_ADD); - ptr = (CELL *)c.p; -#endif - return ptr; -} - - -/************************************************************************** - d i c t A l i g n -** Align the dictionary's free space pointer -**************************************************************************/ -void dictAlign(FICL_DICT *pDict) -{ - pDict->here = alignPtr(pDict->here); -} - - -/************************************************************************** - d i c t A l l o t -** Allocate or remove n chars of dictionary space, with -** checks for underrun and overrun -**************************************************************************/ -int dictAllot(FICL_DICT *pDict, int n) -{ - char *cp = (char *)pDict->here; -#if FICL_ROBUST - if (n > 0) - { - if ((unsigned)n <= dictCellsAvail(pDict) * sizeof (CELL)) - cp += n; - else - return 1; /* dict is full */ - } - else - { - n = -n; - if ((unsigned)n <= dictCellsUsed(pDict) * sizeof (CELL)) - cp -= n; - else /* prevent underflow */ - cp -= dictCellsUsed(pDict) * sizeof (CELL); - } -#else - cp += n; -#endif - pDict->here = PTRtoCELL cp; - return 0; -} - - -/************************************************************************** - d i c t A l l o t C e l l s -** Reserve space for the requested number of cells in the -** dictionary. If nCells < 0 , removes space from the dictionary. -**************************************************************************/ -int dictAllotCells(FICL_DICT *pDict, int nCells) -{ -#if FICL_ROBUST - if (nCells > 0) - { - if (nCells <= dictCellsAvail(pDict)) - pDict->here += nCells; - else - return 1; /* dict is full */ - } - else - { - nCells = -nCells; - if (nCells <= dictCellsUsed(pDict)) - pDict->here -= nCells; - else /* prevent underflow */ - pDict->here -= dictCellsUsed(pDict); - } -#else - pDict->here += nCells; -#endif - return 0; -} - - -/************************************************************************** - d i c t A p p e n d C e l l -** Append the specified cell to the dictionary -**************************************************************************/ -void dictAppendCell(FICL_DICT *pDict, CELL c) -{ - *pDict->here++ = c; - return; -} - - -/************************************************************************** - d i c t A p p e n d C h a r -** Append the specified char to the dictionary -**************************************************************************/ -void dictAppendChar(FICL_DICT *pDict, char c) -{ - char *cp = (char *)pDict->here; - *cp++ = c; - pDict->here = PTRtoCELL cp; - return; -} - - -/************************************************************************** - d i c t A p p e n d W o r d -** Create a new word in the dictionary with the specified -** name, code, and flags. Name must be NULL-terminated. -**************************************************************************/ -FICL_WORD *dictAppendWord(FICL_DICT *pDict, - char *name, - FICL_CODE pCode, - UNS8 flags) -{ - STRINGINFO si; - SI_SETLEN(si, strlen(name)); - SI_SETPTR(si, name); - return dictAppendWord2(pDict, si, pCode, flags); -} - - -/************************************************************************** - d i c t A p p e n d W o r d 2 -** Create a new word in the dictionary with the specified -** STRINGINFO, code, and flags. Does not require a NULL-terminated -** name. -**************************************************************************/ -FICL_WORD *dictAppendWord2(FICL_DICT *pDict, - STRINGINFO si, - FICL_CODE pCode, - UNS8 flags) -{ - FICL_COUNT len = (FICL_COUNT)SI_COUNT(si); - char *pName; - FICL_WORD *pFW; - - ficlLockDictionary(TRUE); - - /* - ** NOTE: dictCopyName advances "here" as a side-effect. - ** It must execute before pFW is initialized. - */ - pName = dictCopyName(pDict, si); - pFW = (FICL_WORD *)pDict->here; - pDict->smudge = pFW; - pFW->hash = hashHashCode(si); - pFW->code = pCode; - pFW->flags = (UNS8)(flags | FW_SMUDGE); - pFW->nName = (char)len; - pFW->name = pName; - /* - ** Point "here" to first cell of new word's param area... - */ - pDict->here = pFW->param; - - if (!(flags & FW_SMUDGE)) - dictUnsmudge(pDict); - - ficlLockDictionary(FALSE); - return pFW; -} - - -/************************************************************************** - d i c t A p p e n d U N S -** Append the specified FICL_UNS to the dictionary -**************************************************************************/ -void dictAppendUNS(FICL_DICT *pDict, FICL_UNS u) -{ - *pDict->here++ = LVALUEtoCELL(u); - return; -} - - -/************************************************************************** - d i c t C e l l s A v a i l -** Returns the number of empty cells left in the dictionary -**************************************************************************/ -int dictCellsAvail(FICL_DICT *pDict) -{ - return pDict->size - dictCellsUsed(pDict); -} - - -/************************************************************************** - d i c t C e l l s U s e d -** Returns the number of cells consumed in the dicionary -**************************************************************************/ -int dictCellsUsed(FICL_DICT *pDict) -{ - return pDict->here - pDict->dict; -} - - -/************************************************************************** - d i c t C h e c k -** Checks the dictionary for corruption and throws appropriate -** errors. -** Input: +n number of ADDRESS UNITS (not Cells) proposed to allot -** -n number of ADDRESS UNITS proposed to de-allot -** 0 just do a consistency check -**************************************************************************/ -void dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int n) -{ - if ((n >= 0) && (dictCellsAvail(pDict) * (int)sizeof(CELL) < n)) - { - vmThrowErr(pVM, "Error: dictionary full"); - } - - if ((n <= 0) && (dictCellsUsed(pDict) * (int)sizeof(CELL) < -n)) - { - vmThrowErr(pVM, "Error: dictionary underflow"); - } - - if (pDict->nLists > FICL_DEFAULT_VOCS) - { - dictResetSearchOrder(pDict); - vmThrowErr(pVM, "Error: search order overflow"); - } - else if (pDict->nLists < 0) - { - dictResetSearchOrder(pDict); - vmThrowErr(pVM, "Error: search order underflow"); - } - - return; -} - - -/************************************************************************** - d i c t C o p y N a m e -** Copy up to nFICLNAME characters of the name specified by si into -** the dictionary starting at "here", then NULL-terminate the name, -** point "here" to the next available byte, and return the address of -** the beginning of the name. Used by dictAppendWord. -** N O T E S : -** 1. "here" is guaranteed to be aligned after this operation. -** 2. If the string has zero length, align and return "here" -**************************************************************************/ -static char *dictCopyName(FICL_DICT *pDict, STRINGINFO si) -{ - char *oldCP = (char *)pDict->here; - char *cp = oldCP; - char *name = SI_PTR(si); - int i = SI_COUNT(si); - - if (i == 0) - { - dictAlign(pDict); - return (char *)pDict->here; - } - - if (i > nFICLNAME) - i = nFICLNAME; - - for (; i > 0; --i) - { - *cp++ = *name++; - } - - *cp++ = '\0'; - - pDict->here = PTRtoCELL cp; - dictAlign(pDict); - return oldCP; -} - - -/************************************************************************** - d i c t C r e a t e -** Create and initialize a dictionary with the specified number -** of cells capacity, and no hashing (hash size == 1). -**************************************************************************/ -FICL_DICT *dictCreate(unsigned nCells) -{ - return dictCreateHashed(nCells, 1); -} - - -FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash) -{ - FICL_DICT *pDict; - size_t nAlloc; - - nAlloc = sizeof (FICL_DICT) + nCells * sizeof (CELL) - + sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *); - - pDict = ficlMalloc(nAlloc); - assert(pDict); - - pDict->size = nCells; - dictEmpty(pDict, nHash); - return pDict; -} - - -/************************************************************************** - d i c t C r e a t e W o r d l i s t -** Create and initialize an anonymous wordlist -**************************************************************************/ -FICL_HASH *dictCreateWordlist(FICL_DICT *dp, int nBuckets) -{ - FICL_HASH *pHash; - - dictAlign(dp); - pHash = (FICL_HASH *)dp->here; - dictAllot(dp, sizeof (FICL_HASH) - + (nBuckets-1) * sizeof (FICL_WORD *)); - - pHash->size = nBuckets; - hashReset(pHash); - return pHash; -} - - -/************************************************************************** - d i c t D e l e t e -** Free all memory allocated for the given dictionary -**************************************************************************/ -void dictDelete(FICL_DICT *pDict) -{ - assert(pDict); - ficlFree(pDict); - return; -} - - -/************************************************************************** - d i c t E m p t y -** Empty the dictionary, reset its hash table, and reset its search order. -** Clears and (re-)creates the hash table with the size specified by nHash. -**************************************************************************/ -void dictEmpty(FICL_DICT *pDict, unsigned nHash) -{ - FICL_HASH *pHash; - - pDict->here = pDict->dict; - - dictAlign(pDict); - pHash = (FICL_HASH *)pDict->here; - dictAllot(pDict, - sizeof (FICL_HASH) + (nHash - 1) * sizeof (FICL_WORD *)); - - pHash->size = nHash; - hashReset(pHash); - - pDict->pForthWords = pHash; - pDict->smudge = NULL; - dictResetSearchOrder(pDict); - return; -} - - -/************************************************************************** - d i c t H a s h S u m m a r y -** Calculate a figure of merit for the dictionary hash table based -** on the average search depth for all the words in the dictionary, -** assuming uniform distribution of target keys. The figure of merit -** is the ratio of the total search depth for all keys in the table -** versus a theoretical optimum that would be achieved if the keys -** were distributed into the table as evenly as possible. -** The figure would be worse if the hash table used an open -** addressing scheme (i.e. collisions resolved by searching the -** table for an empty slot) for a given size table. -**************************************************************************/ -#if FICL_WANT_FLOAT -void dictHashSummary(FICL_VM *pVM) -{ - FICL_DICT *dp = vmGetDict(pVM); - FICL_HASH *pFHash; - FICL_WORD **pHash; - unsigned size; - FICL_WORD *pFW; - unsigned i; - int nMax = 0; - int nWords = 0; - int nFilled; - double avg = 0.0; - double best; - int nAvg, nRem, nDepth; - - dictCheck(dp, pVM, 0); - - pFHash = dp->pSearch[dp->nLists - 1]; - pHash = pFHash->table; - size = pFHash->size; - nFilled = size; - - for (i = 0; i < size; i++) - { - int n = 0; - pFW = pHash[i]; - - while (pFW) - { - ++n; - ++nWords; - pFW = pFW->link; - } - - avg += (double)(n * (n+1)) / 2.0; - - if (n > nMax) - nMax = n; - if (n == 0) - --nFilled; - } - - /* Calc actual avg search depth for this hash */ - avg = avg / nWords; - - /* Calc best possible performance with this size hash */ - nAvg = nWords / size; - nRem = nWords % size; - nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem; - best = (double)nDepth/nWords; - - sprintf(pVM->pad, - "%d bins, %2.0f%% filled, Depth: Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%", - size, - (double)nFilled * 100.0 / size, nMax, - avg, - best, - 100.0 * best / avg); - - ficlTextOut(pVM, pVM->pad, 1); - - return; -} -#endif - -/************************************************************************** - d i c t I n c l u d e s -** Returns TRUE iff the given pointer is within the address range of -** the dictionary. -**************************************************************************/ -int dictIncludes(FICL_DICT *pDict, void *p) -{ - return ((p >= (void *) &pDict->dict) - && (p < (void *)(&pDict->dict + pDict->size)) - ); -} - - -/************************************************************************** - d i c t L o o k u p -** Find the FICL_WORD that matches the given name and length. -** If found, returns the word's address. Otherwise returns NULL. -** Uses the search order list to search multiple wordlists. -**************************************************************************/ -FICL_WORD *dictLookup(FICL_DICT *pDict, STRINGINFO si) -{ - FICL_WORD *pFW = NULL; - FICL_HASH *pHash; - int i; - UNS16 hashCode = hashHashCode(si); - - assert(pDict); - - ficlLockDictionary(1); - - for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i) - { - pHash = pDict->pSearch[i]; - pFW = hashLookup(pHash, si, hashCode); - } - - ficlLockDictionary(0); - return pFW; -} - - -/************************************************************************** - f i c l L o o k u p L o c -** Same as dictLookup, but looks in system locals dictionary first... -** Assumes locals dictionary has only one wordlist... -**************************************************************************/ -#if FICL_WANT_LOCALS -FICL_WORD *ficlLookupLoc(FICL_SYSTEM *pSys, STRINGINFO si) -{ - FICL_WORD *pFW = NULL; - FICL_DICT *pDict = pSys->dp; - FICL_HASH *pHash = ficlGetLoc(pSys)->pForthWords; - int i; - UNS16 hashCode = hashHashCode(si); - - assert(pHash); - assert(pDict); - - ficlLockDictionary(1); - /* - ** check the locals dict first... - */ - pFW = hashLookup(pHash, si, hashCode); - - /* - ** If no joy, (!pFW) --------------------------v - ** iterate over the search list in the main dict - */ - for (i = (int)pDict->nLists - 1; (i >= 0) && (!pFW); --i) - { - pHash = pDict->pSearch[i]; - pFW = hashLookup(pHash, si, hashCode); - } - - ficlLockDictionary(0); - return pFW; -} -#endif - - -/************************************************************************** - d i c t R e s e t S e a r c h O r d e r -** Initialize the dictionary search order list to sane state -**************************************************************************/ -void dictResetSearchOrder(FICL_DICT *pDict) -{ - assert(pDict); - pDict->pCompile = pDict->pForthWords; - pDict->nLists = 1; - pDict->pSearch[0] = pDict->pForthWords; - return; -} - - -/************************************************************************** - d i c t S e t F l a g s -** Changes the flags field of the most recently defined word: -** Set all bits that are ones in the set parameter, clear all bits -** that are ones in the clr parameter. Clear wins in case the same bit -** is set in both parameters. -**************************************************************************/ -void dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr) -{ - assert(pDict->smudge); - pDict->smudge->flags |= set; - pDict->smudge->flags &= ~clr; - return; -} - - -/************************************************************************** - d i c t S e t I m m e d i a t e -** Set the most recently defined word as IMMEDIATE -**************************************************************************/ -void dictSetImmediate(FICL_DICT *pDict) -{ - assert(pDict->smudge); - pDict->smudge->flags |= FW_IMMEDIATE; - return; -} - - -/************************************************************************** - d i c t U n s m u d g e -** Completes the definition of a word by linking it -** into the main list -**************************************************************************/ -void dictUnsmudge(FICL_DICT *pDict) -{ - FICL_WORD *pFW = pDict->smudge; - FICL_HASH *pHash = pDict->pCompile; - - assert(pHash); - assert(pFW); - /* - ** :noname words never get linked into the list... - */ - if (pFW->nName > 0) - hashInsertWord(pHash, pFW); - pFW->flags &= ~(FW_SMUDGE); - return; -} - - -/************************************************************************** - d i c t W h e r e -** Returns the value of the HERE pointer -- the address -** of the next free cell in the dictionary -**************************************************************************/ -CELL *dictWhere(FICL_DICT *pDict) -{ - return pDict->here; -} - - -/************************************************************************** - h a s h F o r g e t -** Unlink all words in the hash that have addresses greater than or -** equal to the address supplied. Implementation factor for FORGET -** and MARKER. -**************************************************************************/ -void hashForget(FICL_HASH *pHash, void *where) -{ - FICL_WORD *pWord; - unsigned i; - - assert(pHash); - assert(where); - - for (i = 0; i < pHash->size; i++) - { - pWord = pHash->table[i]; - - while ((void *)pWord >= where) - { - pWord = pWord->link; - } - - pHash->table[i] = pWord; - } - - return; -} - - -/************************************************************************** - h a s h H a s h C o d e -** -** Generate a 16 bit hashcode from a character string using a rolling -** shift and add stolen from PJ Weinberger of Bell Labs fame. Case folds -** the name before hashing it... -** N O T E : If string has zero length, returns zero. -**************************************************************************/ -UNS16 hashHashCode(STRINGINFO si) -{ - /* hashPJW */ - UNS8 *cp; - UNS16 code = (UNS16)si.count; - UNS16 shift = 0; - - if (si.count == 0) - return 0; - - /* changed to run without errors under Purify -- lch */ - for (cp = (UNS8 *)si.cp; si.count && *cp; cp++, si.count--) - { - code = (UNS16)((code << 4) + tolower(*cp)); - shift = (UNS16)(code & 0xf000); - if (shift) - { - code ^= (UNS16)(shift >> 8); - code ^= (UNS16)shift; - } - } - - return (UNS16)code; -} - - - - -/************************************************************************** - h a s h I n s e r t W o r d -** Put a word into the hash table using the word's hashcode as -** an index (modulo the table size). -**************************************************************************/ -void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW) -{ - FICL_WORD **pList; - - assert(pHash); - assert(pFW); - - if (pHash->size == 1) - { - pList = pHash->table; - } - else - { - pList = pHash->table + (pFW->hash % pHash->size); - } - - pFW->link = *pList; - *pList = pFW; - return; -} - - -/************************************************************************** - h a s h L o o k u p -** Find a name in the hash table given the hashcode and text of the name. -** Returns the address of the corresponding FICL_WORD if found, -** otherwise NULL. -** Note: outer loop on link field supports inheritance in wordlists. -** It's not part of ANS Forth - ficl only. hashReset creates wordlists -** with NULL link fields. -**************************************************************************/ -FICL_WORD *hashLookup(FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode) -{ - FICL_UNS nCmp = si.count; - FICL_WORD *pFW; - UNS16 hashIdx; - - if (nCmp > nFICLNAME) - nCmp = nFICLNAME; - - for (; pHash != NULL; pHash = pHash->link) - { - if (pHash->size > 1) - hashIdx = (UNS16)(hashCode % pHash->size); - else /* avoid the modulo op for single threaded lists */ - hashIdx = 0; - - for (pFW = pHash->table[hashIdx]; pFW; pFW = pFW->link) - { - if ( (pFW->nName == si.count) - && (!strincmp(si.cp, pFW->name, nCmp)) ) - return pFW; -#if FICL_ROBUST - assert(pFW != pFW->link); -#endif - } - } - - return NULL; -} - - -/************************************************************************** - h a s h R e s e t -** Initialize a FICL_HASH to empty state. -**************************************************************************/ -void hashReset(FICL_HASH *pHash) -{ - unsigned i; - - assert(pHash); - - for (i = 0; i < pHash->size; i++) - { - pHash->table[i] = NULL; - } - - pHash->link = NULL; - pHash->name = NULL; - return; -} - - Property changes on: vendor/ficl/dist/dict.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: vendor/ficl/dist/ficl.c =================================================================== --- vendor/ficl/dist/ficl.c (revision 282802) +++ vendor/ficl/dist/ficl.c (nonexistent) @@ -1,691 +0,0 @@ -/******************************************************************* -** f i c l . c -** Forth Inspired Command Language - external interface -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 19 July 1997 -** $Id: ficl.c,v 1.17 2001-12-04 17:58:11-08 jsadler Exp jsadler $ -*******************************************************************/ -/* -** 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 -#include -#include "ficl.h" - - -/* -** System statics -** Each FICL_SYSTEM 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_MULTITHREAD 1 -** and supply your own version of ficlLockDictionary. -*/ -static int defaultStack = FICL_DEFAULT_STACK; - - -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. -** 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. -**************************************************************************/ -FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi) -{ - int nDictCells; - int nEnvCells; - FICL_SYSTEM *pSys = ficlMalloc(sizeof (FICL_SYSTEM)); - - assert(pSys); - assert(fsi->size == sizeof (FICL_SYSTEM_INFO)); - - memset(pSys, 0, sizeof (FICL_SYSTEM)); - - nDictCells = fsi->nDictCells; - if (nDictCells <= 0) - nDictCells = FICL_DEFAULT_DICT; - - nEnvCells = fsi->nEnvCells; - if (nEnvCells <= 0) - nEnvCells = FICL_DEFAULT_DICT; - - pSys->dp = dictCreateHashed((unsigned)nDictCells, HASHSIZE); - pSys->dp->pForthWords->name = "forth-wordlist"; - - pSys->envp = dictCreate((unsigned)nEnvCells); - pSys->envp->pForthWords->name = "environment"; - - pSys->textOut = fsi->textOut; - pSys->pExtend = fsi->pExtend; - -#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... - */ - pSys->localp = dictCreate((unsigned)FICL_MAX_LOCALS * CELLS_PER_WORD); -#endif - - /* - ** 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. - ** 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... - */ - ficlNewVM(pSys); - ficlCompileSoftCore(pSys); - ficlFreeVM(pSys->vmList); - - - return pSys; -} - - -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 -** FICL_PARSE_STEP notes in ficl.h for details). Returns 0 if successful, -** nonzero if there's no more room in the list. -**************************************************************************/ -int ficlAddParseStep(FICL_SYSTEM *pSys, FICL_WORD *pFW) -{ - int i; - for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) - { - if (pSys->parseList[i] == NULL) - { - pSys->parseList[i] = pFW; - return 0; - } - } - - return 1; -} - - -/* -** Compile a word into the dictionary that invokes the specified FICL_PARSE_STEP -** 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 ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep) -{ - FICL_DICT *dp = pSys->dp; - FICL_WORD *pFW = dictAppendWord(dp, name, parseStepParen, FW_DEFAULT); - dictAppendCell(dp, LVALUEtoCELL(pStep)); - ficlAddParseStep(pSys, pFW); -} - - -/* -** This word lists the parse steps in order -*/ -void ficlListParseSteps(FICL_VM *pVM) -{ - int i; - FICL_SYSTEM *pSys = pVM->pSys; - assert(pSys); - - vmTextOut(pVM, "Parse steps:", 1); - vmTextOut(pVM, "lookup", 1); - - for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) - { - if (pSys->parseList[i] != NULL) - { - vmTextOut(pVM, pSys->parseList[i]->name, 1); - } - else break; - } - return; -} - - -/************************************************************************** - 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. -**************************************************************************/ -FICL_VM *ficlNewVM(FICL_SYSTEM *pSys) -{ - FICL_VM *pVM = vmCreate(NULL, defaultStack, defaultStack); - pVM->link = pSys->vmList; - pVM->pSys = pSys; - pVM->pExtend = pSys->pExtend; - vmSetTextOut(pVM, pSys->textOut); - - pSys->vmList = pVM; - return pVM; -} - - -/************************************************************************** - 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 ficlFreeVM(FICL_VM *pVM) -{ - FICL_SYSTEM *pSys = pVM->pSys; - FICL_VM *pList = pSys->vmList; - - assert(pVM != 0); - - if (pSys->vmList == pVM) - { - pSys->vmList = pSys->vmList->link; - } - else for (; pList != NULL; pList = pList->link) - { - if (pList->link == pVM) - { - pList->link = pVM->link; - break; - } - } - - if (pList) - vmDelete(pVM); - return; -} - - -/************************************************************************** - f i c l B u i l d -** Builds a word into the dictionary. -** Preconditions: system must be initialized, and there must -** be enough space for the new word's header! Operation is -** controlled by ficlLockDictionary, so any initialization -** required by your version of the function (if you overrode -** it) must be complete at this point. -** Parameters: -** name -- duh, the name of the word -** code -- code to execute when the word is invoked - must take a single param -** pointer to a FICL_VM -** flags -- 0 or more of F_IMMEDIATE, F_COMPILE, use bitwise OR! -** -**************************************************************************/ -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); - - ficlLockDictionary(FALSE); - return 0; -} - - -/************************************************************************** - 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 -** interpreter's output function. -** -** Contains the "inner interpreter" code in a tight loop -** -** Returns one of the VM_XXXX codes defined in ficl.h: -** VM_OUTOFTEXT is the normal exit condition -** VM_ERREXIT means that the interp encountered a syntax error -** and the vm has been reset to recover (some or all -** of the text block got ignored -** VM_USEREXIT means that the user executed the "bye" command -** to shut down the interpreter. This would be a good -** time to delete the vm, etc -- or you can ignore this -** signal. -**************************************************************************/ -int ficlExec(FICL_VM *pVM, char *pText) -{ - return ficlExecC(pVM, pText, -1); -} - -int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size) -{ - FICL_SYSTEM *pSys = pVM->pSys; - FICL_DICT *dp = pSys->dp; - - int except; - jmp_buf vmState; - jmp_buf *oldState; - TIB saveTib; - - assert(pVM); - assert(pSys->pInterp[0]); - - if (size < 0) - size = strlen(pText); - - vmPushTib(pVM, pText, size, &saveTib); - - /* - ** Save and restore VM's jmp_buf to enable nested calls to ficlExec - */ - oldState = pVM->pState; - pVM->pState = &vmState; /* This has to come before the setjmp! */ - except = setjmp(vmState); - - switch (except) - { - case 0: - if (pVM->fRestart) - { - pVM->runningWord->code(pVM); - pVM->fRestart = 0; - } - else - { /* set VM up to interpret text */ - vmPushIP(pVM, &(pSys->pInterp[0])); - } - - vmInnerLoop(pVM); - break; - - case VM_RESTART: - pVM->fRestart = 1; - except = VM_OUTOFTEXT; - break; - - case VM_OUTOFTEXT: - vmPopIP(pVM); - if ((pVM->state != COMPILE) && (pVM->sourceID.i == 0)) - ficlTextOut(pVM, FICL_PROMPT, 0); - break; - - case VM_USEREXIT: - case VM_INNEREXIT: - case VM_BREAK: - break; - - case VM_QUIT: - if (pVM->state == COMPILE) - { - dictAbortDefinition(dp); -#if FICL_WANT_LOCALS - dictEmpty(pSys->localp, pSys->localp->pForthWords->size); -#endif - } - vmQuit(pVM); - break; - - case VM_ERREXIT: - case VM_ABORT: - case VM_ABORTQ: - default: /* user defined exit code?? */ - if (pVM->state == COMPILE) - { - dictAbortDefinition(dp); -#if FICL_WANT_LOCALS - dictEmpty(pSys->localp, pSys->localp->pForthWords->size); -#endif - } - dictResetSearchOrder(dp); - vmReset(pVM); - break; - } - - pVM->pState = oldState; - vmPopTib(pVM, &saveTib); - return (except); -} - - -/************************************************************************** - f i c l E x e c X T -** Given a pointer to a FICL_WORD, push an inner interpreter and -** execute the word to completion. This is in contrast with vmExecute, -** which does not guarantee that the word will have completed when -** the function returns (ie in the case of colon definitions, which -** need an inner interpreter to finish) -** -** Returns one of the VM_XXXX exception codes listed in ficl.h. Normal -** exit condition is VM_INNEREXIT, ficl's private signal to exit the -** inner loop under normal circumstances. If another code is thrown to -** exit the loop, this function will re-throw it if it's nested under -** itself or ficlExec. -** -** NOTE: this function is intended so that C code can execute ficlWords -** given their address in the dictionary (xt). -**************************************************************************/ -int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord) -{ - int except; - jmp_buf vmState; - jmp_buf *oldState; - FICL_WORD *oldRunningWord; - - assert(pVM); - assert(pVM->pSys->pExitInner); - - /* - ** Save the runningword so that RESTART behaves correctly - ** over nested calls. - */ - oldRunningWord = pVM->runningWord; - /* - ** Save and restore VM's jmp_buf to enable nested calls - */ - oldState = pVM->pState; - pVM->pState = &vmState; /* This has to come before the setjmp! */ - except = setjmp(vmState); - - if (except) - vmPopIP(pVM); - else - vmPushIP(pVM, &(pVM->pSys->pExitInner)); - - switch (except) - { - case 0: - vmExecute(pVM, pWord); - vmInnerLoop(pVM); - break; - - case VM_INNEREXIT: - case VM_BREAK: - break; - - case VM_RESTART: - case VM_OUTOFTEXT: - case VM_USEREXIT: - case VM_QUIT: - case VM_ERREXIT: - case VM_ABORT: - case VM_ABORTQ: - default: /* user defined exit code?? */ - if (oldState) - { - pVM->pState = oldState; - vmThrow(pVM, except); - } - break; - } - - pVM->pState = oldState; - pVM->runningWord = oldRunningWord; - return (except); -} - - -/************************************************************************** - 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 FICL_WORD. Otherwise -** return NULL. -**************************************************************************/ -FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name) -{ - STRINGINFO si; - SI_PSZ(si, name); - return dictLookup(pSys->dp, si); -} - - -/************************************************************************** - f i c l G e t D i c t -** Returns the address of the system dictionary -**************************************************************************/ -FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys) -{ - return pSys->dp; -} - - -/************************************************************************** - f i c l G e t E n v -** Returns the address of the system environment space -**************************************************************************/ -FICL_DICT *ficlGetEnv(FICL_SYSTEM *pSys) -{ - return pSys->envp; -} - - -/************************************************************************** - f i c l S e t E n v -** Create an environment variable with a one-CELL payload. ficlSetEnvD -** makes one with a two-CELL payload. -**************************************************************************/ -void ficlSetEnv(FICL_SYSTEM *pSys, char *name, FICL_UNS value) -{ - STRINGINFO si; - FICL_WORD *pFW; - FICL_DICT *envp = pSys->envp; - - SI_PSZ(si, name); - pFW = dictLookup(envp, si); - - if (pFW == NULL) - { - dictAppendWord(envp, name, constantParen, FW_DEFAULT); - dictAppendCell(envp, LVALUEtoCELL(value)); - } - else - { - pFW->param[0] = LVALUEtoCELL(value); - } - - return; -} - -void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, FICL_UNS hi, FICL_UNS lo) -{ - FICL_WORD *pFW; - STRINGINFO si; - FICL_DICT *envp = pSys->envp; - SI_PSZ(si, name); - pFW = dictLookup(envp, si); - - if (pFW == NULL) - { - dictAppendWord(envp, name, twoConstParen, FW_DEFAULT); - dictAppendCell(envp, LVALUEtoCELL(lo)); - dictAppendCell(envp, LVALUEtoCELL(hi)); - } - else - { - pFW->param[0] = LVALUEtoCELL(lo); - pFW->param[1] = LVALUEtoCELL(hi); - } - - return; -} - - -/************************************************************************** - f i c l G e t L o c -** Returns the address of the system locals dictionary. This dict is -** only used during compilation, and is shared by all VMs. -**************************************************************************/ -#if FICL_WANT_LOCALS -FICL_DICT *ficlGetLoc(FICL_SYSTEM *pSys) -{ - return pSys->localp; -} -#endif - - - -/************************************************************************** - f i c l S e t S t a c k S i z e -** Set the stack sizes (return and parameter) to be used for all -** subsequently created VMs. Returns actual stack size to be used. -**************************************************************************/ -int ficlSetStackSize(int nStackCells) -{ - if (nStackCells >= FICL_DEFAULT_STACK) - defaultStack = nStackCells; - else - defaultStack = FICL_DEFAULT_STACK; - - return defaultStack; -} - - -/************************************************************************** - 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 ficlTermSystem(FICL_SYSTEM *pSys) -{ - if (pSys->dp) - dictDelete(pSys->dp); - pSys->dp = NULL; - - if (pSys->envp) - dictDelete(pSys->envp); - pSys->envp = NULL; - -#if FICL_WANT_LOCALS - if (pSys->localp) - dictDelete(pSys->localp); - pSys->localp = NULL; -#endif - - while (pSys->vmList != NULL) - { - FICL_VM *pVM = pSys->vmList; - pSys->vmList = pSys->vmList->link; - vmDelete(pVM); - } - - ficlFree(pSys); - pSys = NULL; - 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); - ficlSetEnv (pSys, "ficl-robust", FICL_ROBUST); - return; -} - Property changes on: vendor/ficl/dist/ficl.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: vendor/ficl/dist/sysdep.c =================================================================== --- vendor/ficl/dist/sysdep.c (revision 282802) +++ vendor/ficl/dist/sysdep.c (nonexistent) @@ -1,409 +0,0 @@ -/******************************************************************* -** s y s d e p . c -** Forth Inspired Command Language -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 16 Oct 1997 -** Implementations of FICL external interface functions... -** -** (simple) port to Linux, Skip Carter 26 March 1998 -** $Id: sysdep.c,v 1.9 2001-07-23 22:01:24-07 jsadler Exp jsadler $ -*******************************************************************/ -/* -** 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 -#include - -#include "ficl.h" - -/* -******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith -*/ -#if defined (FREEBSD_ALPHA) - -#if PORTABLE_LONGMULDIV == 0 -DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) -{ - DPUNS q; - u_int64_t qx; - - qx = (u_int64_t)x * (u_int64_t) y; - - q.hi = (u_int32_t)( qx >> 32 ); - q.lo = (u_int32_t)( qx & 0xFFFFFFFFL); - - return q; -} - -UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) -{ - UNSQR result; - u_int64_t qx, qh; - - qh = q.hi; - qx = (qh << 32) | q.lo; - - result.quot = qx / y; - result.rem = qx % y; - - return result; -} -#endif - -void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) -{ - IGNORE(pVM); - - while(*msg != 0) - putchar(*(msg++)); - if (fNewline) - putchar('\n'); - - return; -} - -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); -} - - -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** is guaranteed to be bracketed as follows: -** ficlLockDictionary(TRUE); -** -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** befor timeout (optional - could also block forever) -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock) -{ - IGNORE(fLock); - return 0; -} -#endif /* FICL_MULTITHREAD */ - -/* -******************* P C / W I N 3 2 P O R T B E G I N S H E R E *********************** -*/ -#elif defined (_M_IX86) - -#if PORTABLE_LONGMULDIV == 0 -DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) -{ - DPUNS q; - - __asm - { - mov eax,x - mov edx,y - mul edx - mov q.hi,edx - mov q.lo,eax - } - - return q; -} - -UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) -{ - UNSQR result; - - __asm - { - mov eax,q.lo - mov edx,q.hi - div y - mov result.quot,eax - mov result.rem,edx - } - - return result; -} - -#endif - -#if !defined (_WINDOWS) - -void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) -{ - IGNORE(pVM); - - if (fNewline) - puts(msg); - else - fputs(msg, stdout); - - return; -} - -#endif - -void *ficlMalloc (size_t size) -{ - return malloc(size); -} - - -void ficlFree (void *p) -{ - free(p); -} - - -void *ficlRealloc(void *p, size_t size) -{ - return realloc(p, size); -} - -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** is guaranteed to be bracketed as follows: -** ficlLockDictionary(TRUE); -** -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** befor timeout (optional - could also block forever) -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock) -{ - IGNORE(fLock); - return 0; -} -#endif /* FICL_MULTITHREAD */ - -/* -******************* 6 8 K C P U 3 2 P O R T B E G I N S H E R E ******************** -*/ -#elif defined (MOTO_CPU32) - -#if PORTABLE_LONGMULDIV == 0 -DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) -{ - DPUNS q; - IGNORE(q); /* suppress goofy compiler warnings */ - IGNORE(x); - IGNORE(y); - -#pragma ASM - move.l (S_x,a6),d1 - mulu.l (S_y,a6),d0:d1 - move.l d1,(S_q+4,a6) - move.l d0,(S_q+0,a6) -#pragma END_ASM - - return q; -} - -UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) -{ - UNSQR result; - IGNORE(result); /* suppress goofy compiler warnings */ - IGNORE(q); - IGNORE(y); - -#pragma ASM - move.l (S_q+0,a6),d0 ; hi 32 --> d0 - move.l (S_q+4,a6),d1 ; lo 32 --> d1 - divu.l (S_y,a6),d0:d1 ; d0 <-- rem, d1 <-- quot - move.l d1,(S_result+0,a6) - move.l d0,(S_result+4,a6) -#pragma END_ASM - - return result; -} - -#endif - -void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) -{ - return; -} - -void *ficlMalloc (size_t size) -{ -} - -void ficlFree (void *p) -{ -} - - -void *ficlRealloc(void *p, size_t size) -{ - void *pv = malloc(size); - if (p) - { - memcpy(pv, p, size) - free(p); - } - - return pv; -} - - - -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** is guaranteed to be bracketed as follows: -** ficlLockDictionary(TRUE); -** -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** befor timeout (optional - could also block forever) -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock) -{ - IGNORE(fLock); - return 0; -} -#endif /* FICL_MULTITHREAD */ - -#endif /* MOTO_CPU32 */ - -/* -******************* Linux P O R T B E G I N S H E R E ******************** Skip Carter, March 1998 -*/ - -#if defined(linux) || defined(riscos) - -#if PORTABLE_LONGMULDIV == 0 - -typedef unsigned long long __u64; -typedef unsigned long __u32; - -DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y) -{ - DPUNS q; - __u64 qx; - - qx = (__u64)x * (__u64) y; - - q.hi = (__u32)( qx >> 32 ); - q.lo = (__u32)( qx & 0xFFFFFFFFL); - - return q; -} - -UNSQR ficlLongDiv(DPUNS q, FICL_UNS y) -{ - UNSQR result; - __u64 qx, qh; - - qh = q.hi; - qx = (qh << 32) | q.lo; - - result.quot = qx / y; - result.rem = qx % y; - - return result; -} - -#endif - -void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline) -{ - IGNORE(pVM); - - if (fNewline) - puts(msg); - else - fputs(msg, stdout); - - return; -} - -void *ficlMalloc (size_t size) -{ - return malloc(size); -} - -void ficlFree (void *p) -{ - free(p); -} - -void *ficlRealloc(void *p, size_t size) -{ - return realloc(p, size); -} - - -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** is guaranteed to be bracketed as follows: -** ficlLockDictionary(TRUE); -** -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** befor timeout (optional - could also block forever) -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock) -{ - IGNORE(fLock); - return 0; -} -#endif /* FICL_MULTITHREAD */ - -#endif /* linux */ - - Property changes on: vendor/ficl/dist/sysdep.c ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: vendor/ficl/dist/sysdep.h =================================================================== --- vendor/ficl/dist/sysdep.h (revision 282802) +++ vendor/ficl/dist/sysdep.h (nonexistent) @@ -1,465 +0,0 @@ -/******************************************************************* - s y s d e p . h -** Forth Inspired Command Language -** Author: John Sadler (john_sadler@alum.mit.edu) -** Created: 16 Oct 1997 -** Ficl system dependent types and prototypes... -** -** Note: Ficl also depends on the use of "assert" when -** FICL_ROBUST is enabled. This may require some consideration -** in firmware systems since assert often -** assumes stderr/stdout. -** $Id: sysdep.h,v 1.11 2001-11-11 12:25:46-08 jsadler Exp jsadler $ -*******************************************************************/ -/* -** 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. -*/ - -#if !defined (__SYSDEP_H__) -#define __SYSDEP_H__ - -#include /* size_t, NULL */ -#include -#include - -#if defined(_WIN32) - #include - #ifndef alloca - #define alloca(x) _alloca(x) - #endif /* alloca */ - #define fstat _fstat - #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 */ -#define IGNORE(x) &x -#endif - -/* -** TRUE and FALSE for C boolean operations, and -** portable 32 bit types for CELLs -** -*/ -#if !defined TRUE -#define TRUE 1 -#endif -#if !defined FALSE -#define FALSE 0 -#endif - -/* -** FreeBSD Alpha (64 bit) data types -*/ -#if defined (FREEBSD_ALPHA) - -#define INT32 int -#define UNS32 unsigned int -#define FICL_INT long -#define FICL_UNS unsigned long -#define BITS_PER_CELL 64 -#define FICL_ALIGN 3 -#endif - -/* -** System dependent data type declarations... -*/ -#if !defined INT32 -#define INT32 long -#endif - -#if !defined UNS32 -#define UNS32 unsigned long -#endif - -#if !defined UNS16 -#define UNS16 unsigned short -#endif - -#if !defined UNS8 -#define UNS8 unsigned char -#endif - -#if !defined NULL -#define NULL ((void *)0) -#endif - -/* -** FICL_UNS and FICL_INT must have the same size as a void* on -** the target system. A CELL is a union of void*, FICL_UNS, and -** FICL_INT. -** (11/2000: same for FICL_FLOAT) -*/ -#if !defined FICL_INT -#define FICL_INT INT32 -#endif - -#if !defined FICL_UNS -#define FICL_UNS UNS32 -#endif - -#if !defined FICL_FLOAT -#define FICL_FLOAT float -#endif - -/* -** Ficl presently supports values of 32 and 64 for BITS_PER_CELL -*/ -#if !defined BITS_PER_CELL -#define BITS_PER_CELL 32 -#endif - -#if ((BITS_PER_CELL != 32) && (BITS_PER_CELL != 64)) - Error! -#endif - -typedef struct -{ - FICL_UNS hi; - FICL_UNS lo; -} DPUNS; - -typedef struct -{ - FICL_UNS quot; - FICL_UNS rem; -} UNSQR; - -typedef struct -{ - FICL_INT hi; - FICL_INT lo; -} DPINT; - -typedef struct -{ - FICL_INT quot; - FICL_INT rem; -} INTQR; - - -/* -** B U I L D C O N T R O L S -*/ - -#if !defined (FICL_MINIMAL) -#define FICL_MINIMAL 0 -#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 -#define FICL_WANT_DEBUGGER 0 -#define FICL_WANT_OOP 0 -#define FICL_PLATFORM_EXTEND 0 -#define FICL_MULTITHREAD 0 -#define FICL_ROBUST 0 -#define FICL_EXTENDED_PREFIX 0 -#endif - -/* -** FICL_PLATFORM_EXTEND -** Includes words defined in ficlCompilePlatform (see win32.c and unix.c for example) -*/ -#if defined (_WIN32) -#if !defined (FICL_PLATFORM_EXTEND) -#define FICL_PLATFORM_EXTEND 1 -#endif -#endif - -#if !defined (FICL_PLATFORM_EXTEND) -#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 -*/ -#if !defined (FICL_WANT_FLOAT) -#define FICL_WANT_FLOAT 1 -#endif - -/* -** FICL_WANT_DEBUGGER -** Inludes a simple source level debugger -*/ -#if !defined (FICL_WANT_DEBUGGER) -#define FICL_WANT_DEBUGGER 1 -#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 -** approach of an array of CELLs instead. -*/ -#if !defined FICL_WANT_USER -#define FICL_WANT_USER 1 -#endif - -#if !defined FICL_USER_CELLS -#define FICL_USER_CELLS 16 -#endif - -/* -** FICL_WANT_LOCALS controls the creation of the LOCALS wordset and -** a private dictionary for local variable compilation. -*/ -#if !defined FICL_WANT_LOCALS -#define FICL_WANT_LOCALS 1 -#endif - -/* Max number of local variables per definition */ -#if !defined FICL_MAX_LOCALS -#define FICL_MAX_LOCALS 16 -#endif - -/* -** FICL_WANT_OOP -** Inludes object oriented programming support (in softwords) -** OOP support requires locals and user variables! -*/ -#if !(FICL_WANT_LOCALS) || !(FICL_WANT_USER) -#if !defined (FICL_WANT_OOP) -#define FICL_WANT_OOP 0 -#endif -#endif - -#if !defined (FICL_WANT_OOP) -#define FICL_WANT_OOP 1 -#endif - -/* -** FICL_WANT_SOFTWORDS -** Controls inclusion of all softwords in softcore.c -*/ -#if !defined (FICL_WANT_SOFTWORDS) -#define FICL_WANT_SOFTWORDS 1 -#endif - -/* -** FICL_MULTITHREAD enables dictionary mutual exclusion -** wia the ficlLockDictionary system dependent function. -** Note: this implementation is experimental and poorly -** tested. Further, it's unnecessary unless you really -** intend to have multiple SESSIONS (poor choice of name -** on my part) - that is, threads that modify the dictionary -** at the same time. -*/ -#if !defined FICL_MULTITHREAD -#define FICL_MULTITHREAD 0 -#endif - -/* -** PORTABLE_LONGMULDIV causes ficlLongMul and ficlLongDiv to be -** defined in C in sysdep.c. Use this if you cannot easily -** generate an inline asm definition -*/ -#if !defined (PORTABLE_LONGMULDIV) -#define PORTABLE_LONGMULDIV 0 -#endif - -/* -** INLINE_INNER_LOOP causes the inner interpreter to be inline code -** instead of a function call. This is mainly because MS VC++ 5 -** chokes with an internal compiler error on the function version. -** in release mode. Sheesh. -*/ -#if !defined INLINE_INNER_LOOP -#if defined _DEBUG -#define INLINE_INNER_LOOP 0 -#else -#define INLINE_INNER_LOOP 1 -#endif -#endif - -/* -** FICL_ROBUST enables bounds checking of stacks and the dictionary. -** This will detect stack over and underflows and dictionary overflows. -** Any exceptional condition will result in an assertion failure. -** (As generated by the ANSI assert macro) -** FICL_ROBUST == 1 --> stack checking in the outer interpreter -** FICL_ROBUST == 2 also enables checking in many primitives -*/ - -#if !defined FICL_ROBUST -#define FICL_ROBUST 2 -#endif - -/* -** FICL_DEFAULT_STACK Specifies the default size (in CELLs) of -** a new virtual machine's stacks, unless overridden at -** create time. -*/ -#if !defined FICL_DEFAULT_STACK -#define FICL_DEFAULT_STACK 128 -#endif - -/* -** FICL_DEFAULT_DICT specifies the number of CELLs to allocate -** for the system dictionary by default. The value -** can be overridden at startup time as well. -** FICL_DEFAULT_ENV specifies the number of cells to allot -** for the environment-query dictionary. -*/ -#if !defined FICL_DEFAULT_DICT -#define FICL_DEFAULT_DICT 12288 -#endif - -#if !defined FICL_DEFAULT_ENV -#define FICL_DEFAULT_ENV 512 -#endif - -/* -** FICL_DEFAULT_VOCS specifies the maximum number of wordlists in -** the dictionary search order. See Forth DPANS sec 16.3.3 -** (file://dpans16.htm#16.3.3) -*/ -#if !defined FICL_DEFAULT_VOCS -#define FICL_DEFAULT_VOCS 16 -#endif - -/* -** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure -** that stores pointers to parser extension functions. I would never expect to have -** more than 8 of these, so that's the default limit. Too many of these functions -** will probably exact a nasty performance penalty. -*/ -#if !defined FICL_MAX_PARSE_STEPS -#define FICL_MAX_PARSE_STEPS 8 -#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 -** of the target system; 2 is safe on any 16 or 32 bit -** machine. 3 would be appropriate for a 64 bit machine. -*/ -#if !defined FICL_ALIGN -#define FICL_ALIGN 2 -#define FICL_ALIGN_ADD ((1 << FICL_ALIGN) - 1) -#endif - -/* -** System dependent routines -- -** edit the implementations in sysdep.c to be compatible -** with your runtime environment... -** ficlTextOut sends a NULL terminated string to the -** default output device - used for system error messages -** ficlMalloc and ficlFree have the same semantics as malloc and free -** in standard C -** ficlLongMul multiplies two UNS32s and returns a 64 bit unsigned -** product -** ficlLongDiv divides an UNS64 by an UNS32 and returns UNS32 quotient -** and remainder -*/ -struct vm; -void ficlTextOut(struct vm *pVM, char *msg, int fNewline); -void *ficlMalloc (size_t size); -void ficlFree (void *p); -void *ficlRealloc(void *p, size_t size); -/* -** Stub function for dictionary access control - does nothing -** by default, user can redefine to guarantee exclusive dict -** access to a single thread for updates. All dict update code -** must be bracketed as follows: -** ficlLockDictionary(TRUE); -** -** ficlLockDictionary(FALSE); -** -** Returns zero if successful, nonzero if unable to acquire lock -** before timeout (optional - could also block forever) -** -** NOTE: this function must be implemented with lock counting -** semantics: nested calls must behave properly. -*/ -#if FICL_MULTITHREAD -int ficlLockDictionary(short fLock); -#else -#define ficlLockDictionary(x) 0 /* ignore */ -#endif - -/* -** 64 bit integer math support routines: multiply two UNS32s -** to get a 64 bit product, & divide the product by an UNS32 -** to get an UNS32 quotient and remainder. Much easier in asm -** on a 32 bit CPU than in C, which usually doesn't support -** the double length result (but it should). -*/ -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__*/ Property changes on: vendor/ficl/dist/sysdep.h ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property Deleted: svn:keywords ## -1 +0,0 ## -FreeBSD=%H \ No newline at end of property Deleted: svn:mime-type ## -1 +0,0 ## -text/plain \ No newline at end of property Index: vendor/ficl/dist/softwords/softcore.bat =================================================================== --- vendor/ficl/dist/softwords/softcore.bat (revision 282802) +++ vendor/ficl/dist/softwords/softcore.bat (nonexistent) @@ -1 +0,0 @@ -perl softcore.pl softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr fileaccess.fr >..\softcore.c Index: vendor/ficl/dist/softwords/string.fr =================================================================== --- vendor/ficl/dist/softwords/string.fr (revision 282802) +++ vendor/ficl/dist/softwords/string.fr (nonexistent) @@ -1,148 +0,0 @@ -\ #if (FICL_WANT_OOP) -\ ** 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 Index: vendor/ficl/dist/softwords/softcore.py.bat =================================================================== --- vendor/ficl/dist/softwords/softcore.py.bat (revision 282802) +++ vendor/ficl/dist/softwords/softcore.py.bat (nonexistent) @@ -1 +0,0 @@ -python softcore.py softcore.fr jhlocal.fr marker.fr prefix.fr ifbrack.fr oo.fr classes.fr string.fr fileaccess.fr >..\softcore.c Index: vendor/ficl/dist/softwords/ifbrack.fr =================================================================== --- vendor/ficl/dist/softwords/ifbrack.fr (revision 282802) +++ vendor/ficl/dist/softwords/ifbrack.fr (nonexistent) @@ -1,48 +0,0 @@ -\ ** 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 Index: vendor/ficl/dist/softwords/softcore.fr =================================================================== --- vendor/ficl/dist/softwords/softcore.fr (revision 282802) +++ vendor/ficl/dist/softwords/softcore.fr (nonexistent) @@ -1,207 +0,0 @@ -\ ** ficl/softwords/softcore.fr -\ ** FICL soft extensions -\ ** John Sadler (john_sadler@alum.mit.edu) -\ ** September, 1998 - -\ ** Ficl USER variables -\ ** See words.c for primitive def'n of USER -.( loading ficl soft extensions ) cr -\ #if FICL_WANT_USER -variable nUser 0 nUser ! -: user \ name ( -- ) - nUser dup @ user 1 swap +! ; - -\ #endif - -\ ** 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< ; - - -\ ** LOCAL EXT word set -\ #if FICL_WANT_LOCALS -: 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 - -\ #endif - -\ ** 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 -\ -\ set-current -\
\n" +?> + + + + + + +A Ficl dictionary is equivalent to the FORTH "dictionary"; it is where words are stored. +A single dictionary has a single HERE pointer. +

+ +A Ficl system information structure is used to change default values used +in initializing a Ficl system. +

+ +A Ficl system contains a single dictionary, and one or more virtual machines. +

+ +A Ficl stack is equivalent to a FORTH "stack". Ficl has three stacks: +

    + +
  • +The data stack, where integer arguments are stored. + +
  • +The return stack, where locals and return addresses for subroutine returns are stored. + +
  • +The float stack, where floating-point arguments are stored. (This stack +is only enabled when FICL_WANT_FLOAT is nonzero.) +
+ +

+ +A Ficl virtual machine (or vm) represents a single running instance of the Ficl interpreter. +All virtual machines in a single Ficl system see the same dictionary. +

+ + + +Though Ficl's API offers a great deal of flexibility, most programs +incorporating Ficl simply use it as follows: + +

    + +
  1. +Create a single ficlSystem using ficlSystemCreate(NULL). + +
  2. +Add native functions as necessary with ficlDictionarySetPrimitive(). + +
  3. +Add constants as necessary with ficlDictionarySetConstant(). + +
  4. +Create one (or more) virtual machine(s) with ficlSystemCreateVm(). + +
  5. +Add one or more scripted functions with ficlVmEvaluate(). + +
  6. +Execute code in a Ficl virtual machine, usually with ficlVmEvaluate(), +but perhaps with ficlVmExecuteXT(). + +
  7. +At shutdown, call ficlSystemDestroy() on the single Ficl system. + +
+ + + + +The following is a partial listing of functions that interface your +system or program to Ficl. For a complete listing, see ficl.h +(which is heavily commented). For a simple example, see main.c. +

+ +Note that as of Ficl 4, the API is internally consistent. +Every external entry point starts with the word +ficl, and the word after that also corresponds +with the first argument. For instance, a word that operates +on a ficlSystem * will be called ficlSystemSomething(). + + + + +

+ + + +Resets a ficlSystemInformation structure to all zeros. +(Actually implemented as a macro.) Use this to initialize a ficlSystemInformation +structure before initializing its members and passing it +into ficlSystemCreate() (below). + + + +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()). If you pass in a NULL +pointer, you will recieve a ficlSystem using the default +sizes for the dictionary and stacks. + + + + +Reclaims memory allocated for the Ficl system including all +dictionaries and all virtual machines created by +ficlSystemCreateVm(). Note that this will not +automatically free memory allocated by the FORTH memory allocation +words (ALLOCATE and RESIZE). + + + +Adds a new word to the dictionary with the given +name, code pointer, and flags. To add +

+ +The flags parameter is a bitfield. The valid +flags are:

    + +
  • +FICL_WORD_IMMEDIATE +
  • +FICL_WORD_COMPILE_ONLY +
  • +FICL_WORD_SMUDGED +
  • +FICL_WORD_OBJECT +
  • +FICL_WORD_INSTRUCTION + +
+ +For more information on these flags, see ficl.h. + + + + +Creates a new virtual machine in the specified system. + + + + + 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 ficlVmEvaluate() +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). + + + + +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—you +save the dictionary search and outer interpreter overhead. + + + +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. + + + +Create, initialize, and return a VM from the heap using +ficlMalloc. Links the VM into the system VM list for later reclamation +by ficlTermSystem. + + + +Returns the address of the specified word in the main dictionary. +If no such word is found, it returns NULL. +The address is also a valid execution token, and can be used in a call to ficlVmExecuteXT(). + +ficlDictionary *ficlVmGetDictionary(ficlVm *system)") ?> + +Returns a pointer to the main system dictionary. + + + + +Returns a pointer to the environment dictionary. This dictionary +stores information that describes this implementation as required by the +Standard. + + + + + + +Returns a pointer to the locals dictionary. This function is +defined only if FICL_WANT_LOCALS is non-zero (see ficl.h). +The locals dictionary is the symbol table for +local variables. + + +
+ + + + +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 +(FICL_PLATFORM_HAS_2INTEGER); +some are optional, such as telling Ficl whether or not to use the +extended set of "prefixes" (FICL_WANT_EXTENDED_PREFIXES). +

+ +The best way to find out more about these constants is to read ficl.h +yourself. The settings that turn on or off Ficl modules all start with +FICL_WANT. The settings relating to functionality available +on the current platform all start with FICL_PLATFORM. +

+ + + +ficllocal.h") ?> + +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 ficllocal.h, 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 ficl.h +or editing the makefile. That should make it much easier to integrate +future Ficl releases into your product—all you need do is preserve +your tweaked copy of ficllocal.h and replace the rest. + + + + Index: vendor/ficl/dist/doc/source/debugger.ht =================================================================== --- vendor/ficl/dist/doc/source/debugger.ht (nonexistent) +++ vendor/ficl/dist/doc/source/debugger.ht (revision 282803) @@ -0,0 +1,157 @@ + + +

Ficl includes a simple step debugger for colon definitions +and DOES> words. + + + + + +To debug a word, set up the stack with any parameters the word requires, +then execute: +

DEBUG your-word-name-here
+

+ +If the word is unnamed, or all you have is an execution token, +you can instead use DEBUG-XT +

+ +The debugger invokes SEE 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: + +

+ +
+I (step In) +
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. + +
+O (step Over) +
+Executes the next instruction in its entirety. + +
+G (Go) +
+Run the word to completion and exit the debugger. + +
+L (List) +
+Lists the source code of the word presently being stepped. + +
+Q (Quit) +
+Abort the word and exit the debugger, clearing the stacks. + +
+X (eXecute) +
+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: +
+X DROP 3 \ change top argument on stack to 3
+
+ +
+ + +Any other character will prints a list of available debugger commands. + + +ON-STEP
Event") ?> + +If there is a defined word named ON-STEP 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 ON-STEP is: +

+ +

+: ON-STEP  ." S: " .S-SIMPLE CR ;
+
+ +If you redefine ON-STEP, we recommend you ensure the word has no +side-effects (for instance, adding or removing values from any stack). + + + +ON-STEP
") ?> + +
+ +
+.ENV ( -- ) +
+Prints all environment settings non-destructively. + +
+.S ( -- ) +
+Prints the parameter stack non-destructively in a verbose format. + +
+.S-SIMPLE ( -- ) +
+Prints the parameter stack non-destructively in a simple single-line format. + +
+F.S ( -- ) +
+Prints the float stack non-destructively (only available if FICL_WANT_FLOAT is enabled). + +
+R.S ( -- ) +
+Prints a represention of the state of the return stack non-destructively. + + + +
+ + + +

+The debugger words are mostly located in source file tools.c. There are +supporting words (DEBUG and ON-STEP) in softcore.fr as well. +There are two main words that make the debugger go: debug-xt and step-break. +debug-xt takes the execution token of a word to debug (as returned by ' for example) , +checks to see if it is debuggable (not a primitive), sets a breakpoint at its +first instruction, and runs see on it. To set a breakpoint, +debug-xt +replaces the instruction at the breakpoint with the execution token of step-break, and +stores the original instruction and its address in a static breakpoint +record. To clear the breakpoint, step-break simply replaces the original +instruction and adjusts the target virtual machine's instruction pointer +to run it. + +

+ +step-break is responsible for processing debugger commands and setting +breakpoints at subsequent instructions. + + + + +

+ +
  • +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?) + +
  • Add user-set breakpoints. + +
  • Add "step out" command. +
  • + + + Index: vendor/ficl/dist/doc/source/dpans.ht =================================================================== --- vendor/ficl/dist/doc/source/dpans.ht (nonexistent) +++ vendor/ficl/dist/doc/source/dpans.ht (revision 282803) @@ -0,0 +1,589 @@ + + + +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. + +
    + + + + + +Providing names from the Core Extensions word set +
    + +Providing names from the Double-Number word set +
    + +Providing the Exception word set +
    + +Providing the Exception Extensions word set +
    + +Providing the File-Access word set +
    + +Providing the File-Access Extensions word set +
    + +Providing names from the Floating-Point word set +
    + +Providing the Locals word set +
    + +Providing the Locals Extensions word set +
    + +Providing the Memory Allocation word set +
    + +Providing the Programming-Tools word set +
    + +Providing names from the Programming-Tools Extensions word set +
    + +Providing the Search-Order word set +
    + +Providing the Search-Order Extensions word set +
    + +Providing names from the String Extensions word set +
    + +
    + + +\n" + heading + "\n
    \n" + +?> + + + + +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. + +
    + + + +System dependent. You can change the default address alignment by +defining FICL_ALIGN on your compiler's command line, +or in platform.h. +The default value is set to 2 in ficl.h. +This causes dictionary entries and ALIGN and +ALIGNED to align on 4 byte +boundaries. To align on 2n byte boundaries, +set FICL_ALIGN to n. + + + + +Depends on target system, C runtime library, and your +implementation of ficlTextOut(). + + + + +None implemented in the versions supplied in primitives.c. +Because ficlEvaluate() is supplied a text buffer +externally, it's up to your system to define how that buffer will +be obtained. + + + + +Depends on target system and implementation of ficlTextOut(). + + + + +Ficl characters are one byte each. There are no alignment requirements. + + + + +No special processing is performed on characters beyond case-folding. Therefore, +extended characters will not match their unaccented counterparts. + + + + +Ficl uses the Standard C function isspace() to distinguish space characters. + + + + +Uses the data stack. + + + + +The maximum supported value of BASE is 36. +Ficl will fail via assertion in function ltoa() of utility.c +if the base is found to be larger than 36 or smaller than 2. There will be no effect +if NDEBUG is defined, however, other than possibly unexpected behavior. + + + + +Target system dependent. + + + + +Calls ABORT to exit. + + + + +Target system dependent (implementation of outer loop that calls ficlEvaluate()). + + + + +Counted strings are limited to 255 characters. + + + + +Limited by available memory and the maximum unsigned value that can fit in a cell (232-1). + + + + +Ficl stores the first 31 characters of a definition name. + + + + +Same as maximum definition name length. + + + + +None supported. This is up to the target system. + + + + +None supported. This is up to the target system. + + + + +Okay, we don't know what this means. If you understand what they're asking for here, +please call the home office. + + + + +Target system dependent, either 32 or 64 bits. + + + + +System dependent. Ficl represents a CELL internally as a union that can hold a ficlInteger32 +(a signed 32 bit scalar value), a ficlUnsigned32 (32 bits unsigned), +and an untyped pointer. No specific byte ordering is assumed. + + + + +System dependent. +Assuming a 32 bit implementation, range for signed single-cell values is [-231, 231-1]. +Range for unsigned single cell values is [0, 232-1]. +Range for signed double-cell values is [-263, 263-1]. +Range for unsigned double cell values is [0, 264-1]. + + + + +None. + + + + +Default is 255. Depends on the setting of FICL_PAD_SIZE in ficl.h. + + + + +System dependent, generally 4. + + + + +System dependent, generally 1. + + + + +This buffer is supplied by the host program. Ficl imposes no practical limit. + + + + +Default is 255. Depends on the setting of FICL_PAD_SIZE in ficl.h. + + + + +Default is 255. Depends on the setting of FICL_PAD_SIZE in ficl.h. + + + + +The Ficl dictionary is not case-sensitive. + + + + +ok> + + + + +Symmetric. + + + + +1. + + + + +System dependent. Ficl makes no special checks for overflow. + + + +No. Definitions are unsmudged after ; only, and only then if no control structure matching problems have been detected. + +
    + + + + +
    + + + +Ficl calls ABORT then prints the name followed by not found. + + + + +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. + + + + +No problem: all addresses in Ficl are absolute. You can reach any 32 bit address in Ficl's address space. + + + + +Ficl makes no check for argument type compatibility. Effects of a mismatch vary widely depending on the specific problem and operands. + + + + +Ficl returns a valid token, but the result of executing that token while interpreting may be undesirable. + + + + +Results are target procesor dependent. Generally, Ficl makes no check for divide-by-zero. The target processor will probably throw an exception. + + + + +With FICL_ROBUST (defined in ficl.h) set to a value of 2 or greater, +most data, float, and return stack operations are checked for underflow and overflow. + + + + +This is not checked, and bad things will happen. + + + + +Ficl generates an error message if the dictionary is too full to create +a definition header. It checks ALLOT as well, but it is possible +to make an unchecked allocation request that will overflow the dictionary. + + + + +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 EXECUTE though. + + + + +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. + + + + +In the unlikely event you are able to construct a pictured numeric string of more +than FICL_PAD_LENGTH 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. + + + + +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 SLITERAL, you need to have enough +room for the string, otherwise bad things may happen. This is usually not a problem. + + + + +Value will be truncated. + + + + +Most stack underflows are detected and prevented if FICL_ROBUST (defined in sysdep.h) is set to 2 or greater. +Otherwise, the stack pointer and size are likely to be trashed. + + + + +Ficl returns for a new input buffer until a non-empty one is supplied. + + +
    + + +The following specific ambiguous conditions are noted in the glossary entries of the relevant words: + +
    + + + +Memory corruption will occur—the exact behavior is unpredictable +because the input buffer is supplied by the host program's outer loop. + + + + +It finds the address of the definition before DOES> + + + + +Not implemented. + + + + +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. + + + + +Target processor dependent. Consequences include: none (Intel), address error exception (68K). + + + + +See above on data space read/write alignment. + + + +If FICL_ROBUST is two or larger, Ficl will detect a stack underflow, report it, and execute ABORT to +exit execution. Otherwise the error will not be detected, and memory corruption will occur. + + + + +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 2 or greater. +Note however that Ficl only checks for return stack underflows at the end of each line of text. + + + +No problem. + + + + +Ficl's version of TO works correctly with words defined with: +
      + +
    • VALUE +
    • 2VALUE +
    • FVALUE +
    • F2VALUE +
    • CONSTANT +
    • FCONSTANT +
    • 2CONSTANT +
    • F2CONSTANT +
    • VARIABLE +
    • 2VARIABLE +
    +as well as with all "local" variables. + + + +Ficl prints an error message and executes ABORT + + + +Not detected. Results vary depending on the specific problem. + + + + +The word is postponed correctly. + + + + +Ficl stores the first FICL_COUNTED_STRING_MAX - 1 characters in the +destination buffer. +(The extra character is the trailing space required by the standard. Yuck.) + + + +Depends on target process or and C runtime library implementations of the << and >> operators +on unsigned values. For I386, the processor appears to shift modulo the number of bits in a cell. + + + + + +Undefined. CREATE reserves a field in words it builds for DOES> to fill in. +If you use DOES> on a word not made by CREATE 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. + + +
    + + + +
    + + + +Default is 64—unused locals are cheap. Change by redefining FICL_MAX_LOCALS (defined in ficl.h). + +
    + + + + +
    + + + +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. + + + +See the CORE ambiguous conditions, above (no change). + +
    + + + + + +
    + + + +SEE de-compiles definitions from the dictionary. Ficl words are stored as a combination +of things: +
      + +
    1. bytecodes (identified as "instructions"), +
    2. addresses of native Ficl functions, and +
    3. arguments to both of the above. + +
    +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. + +
    + + + + + +
    + + + +Defaults to 16. Can be changed by redefining FICL_MAX_WORDLISTS (declared in ficl.h). + + + + +Equivalent to FORTH-WORDLIST 1 SET-ORDER + +
    + + + + + + +
    + + +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 new compile wordlist. + + + + +Ficl prints an error message if the search order underflows, and resets the order to its default state. + + + + +Ficl prints an error message if the search order overflows, and resets the order to its default state. + +
    + + + Index: vendor/ficl/dist/doc/source/ficl.ht =================================================================== --- vendor/ficl/dist/doc/source/ficl.ht (nonexistent) +++ vendor/ficl/dist/doc/source/ficl.ht (revision 282803) @@ -0,0 +1,1257 @@ + + + + + + + + + Ficl - Embedded Scripting + + + + +

    Ficl Documentation

    + + + +

    What is Ficl?

    +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: + +
      + +
    • +typically takes under 2 hours to port to a new system—much +less if the target operating system is one of several already supported +(Win32, Linux, FreeBSD, RiscOS, and more) + +
    • +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 + +
    • +is relatively quick thanks to its "switch-threaded" virtual +machine design and just in time compiling + +
    • +is a complete and powerful programming language + +
    • +is interactive + +
    • +has object oriented programming features that can be used to wrap +data structures or classes of the host system without altering them—even +if the host is mainly written in a non-OO language + +
    + +

    + +Ficl syntax is based on ANS Forth and the code is ANSI C. See +below for examples of software and products +that include ficl. Ficl stands for "Forth inspired command language". + + +

    Ficl Versus Other Forth Interpreters

    + +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 adapter +for code written in C (or asm, Forth, C++...). + + +

    Ficl Design Goals

    +
      + +
    • +Target 32- and 64-bit processors + +
    • +Scripting, prototyping, and extension language for systems +written also in C + +
    • +Supportable—code is as transparent as I can make it + +
    • +Interface to functions written in C + +
    • +Conformant to the 1994 ANSI Standard for Forth (DPANS94) + +
    • +Minimize porting effort—require an ANSI C runtime environment +and minimal glue code + +
    • +Provide object oriented extensions + +
    + +
    + +

    Download

    + + + +

    More information on Ficl and Forth

    + + + +

    Some software that uses Ficl

    + + + + +
    +

    License And Disclaimer

    + +Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) +
    +All rights reserved. +

    + + +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. + +

    + +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 me email. +

    + + +

    Ficl Features

    + +
      + +
    • +Simple to integrate into existing systems: the sample +implementation requires three Ficl function calls (see the example +program in main.c). + +
    • +Written in ANSI C for portability. + +
    • +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. + +
    • +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) + +
    • +Ficl and C/C++ can interact in two ways: Ficl can wrap C code, +and C functions can invoke Ficl code. + +
    • +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. +Note: +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. + +
    • +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. + +
    • +Written in ANSI C to be as simple as I can make it to understand, +support, debug, and port. Compiles without complaint at /Az /W4 (require +ANSI C, max. warnings) under Microsoft Visual C++, and -ansi +under GCC. Ports to several other toolchains and operating systems +(notably FreeBSD and Linux flavors) exist. + +
    • Does full 32 bit math (but you need to implement two mixed +precision math primitives (see sysdep.c))
    • + +
    + +
    + +

    Porting Ficl

    + +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 sysdep.h and sysdep.c and edit them to suit +your system. For example, INT16 is a short on some +compilers and an int on others. Check the default CELL +alignment controlled by FICL_ALIGN. If necessary, add new +definitions of ficlMalloc, ficlFree, ficlRealloc, and ficlTextOut +to work with your operating system. Finally, use testmain.c as +a guide to installing the ficl system and one or more virtual machines +into your code. You do not need to include testmain.c in your +build. +

    +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. +

    + +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. + + +

    Build Controls

    + +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. + +

    Softcore

    +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 softcore. 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 +make.bat to change the list of files that contribute to +softcore.c. + +

    To-Do List (target system dependent words)

    + +
      + +
    • +Unimplemented system dependent CORE word: KEY +(implement this yourself if you need it) + +
    • +Kludged CORE word: ACCEPT (implement this +better if you need to) + +
    + +

    Application Programming Interface

    + +The following is a partial listing of functions that interface your +system or program to Ficl. For a complete listing, see ficl.h +(which is heavily commented). For examples, see main.c and the +FiclWin sources (below). + +
    +
    FICL_SYSTEM *ficlInitSystem(int nDictCells)
    +
    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)
    +
    void ficlTermSystem(FICL_SYSTEM *pSys)
    +
    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.
    +
    int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, +char flags)
    +
    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)
    +
    int ficlExec(FICL_VM *pVM, char *text)
    +
    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).
    +
    int ficlExecC(FICL_VM *pVM, char *text, int nChars)
    +
    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).
    +
    int ficlExecXT(FICL_VM *pVM, FICL_WORD *pFW)
    +
    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.
    +
    void ficlFreeVM(FICL_VM *pVM)
    +
    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.
    +
    FICL_VM *ficlNewVM(FICL_SYSTEM *pSys)
    +
    Create, initialize, and return a VM from the heap using +ficlMalloc. Links the VM into the system VM list for later reclamation +by ficlTermSystem.
    +
    FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name)
    +
    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.
    +
    FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys)
    +
    Returns a pointer to the main system dictionary, or NULL if the +system is uninitialized.
    +
    FICL_DICT *ficlGetEnv(FICL_SYSTEM *pSys)
    +
    Returns a pointer to the environment dictionary. This dictionary +stores information that describes this implementation as required by the +Standard.
    +
    void ficlSetEnv(FICL_SYSTEM *pSys, char *name, UNS32 value)
    +
    Enters a new constant into the environment dictionary, with the +specified name and value.
    +
    void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, UNS32 hi, +UNS32 lo)
    +
    Enters a new double-cell constant into the environment dictionary +with the specified name and value.
    +
    FICL_DICT *ficlGetLoc(FICL_SYSTEM *pSys)
    +
    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 local +variables.
    +
    void ficlCompileCore(FICL_SYSTEM *pSys)
    +
    Defined in words.c, this function builds ficl's primitives.  +
    +
    void ficlCompileSoftCore(FICL_SYSTEM *pSys)
    +
    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. 
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    Ficl Source Files

    +
    ficl.h Declares most public functions and all data structures. +Includes sysdep.h and math.h
    sysdep.h Declares system dependent functions and contains build +control macros. Edit this file to port to another system.
    math.h Declares functions for 64 bit math
    dict.c Dictionary
    ficl.c System initialization, termination, and ficlExec
    float.c Adds precompiled definitions from the optional FLOAT word +set. Most of the file is conditioned on FICL_WANT_FLOAT
    math64.c Implementation of 64 bit math words (except the two unsigned +primitives declared in sysdep.h and implemented in sysdep.c)
    prefix.c 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.
    search.c Contains C implementations of several of the SEARCH and +SEARCH EXT words
    softcore.c 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.
    softwords/ 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.
    stack.c Stack methods
    sysdep.c Implementation of system dependent functions declared in +sysdep.h
    testmain.c 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.
    tools.c Contains C implementations of TOOLS and TOOLS EXT words, the +debugger, and debugger support words.
    vm.c Virtual Machine methods
    win32.c & unix.c Platform extensions words loaded in ficl.c by +ficlCompilePlatform() - conditioned on FICL_WANT_PLATFORM
    words.c Exports ficlCompileCore(), the run-time dictionary builder, +and contains most precompiled CORE and CORE-EXT words.
    +
    +

    Ficl extras

    +

    Number syntax

    +You can precede a number with "0x", as in C, and it will be interpreted +as a hex value regardless of the value of BASE. Likewise, +numbers prefixed with "0d" will be interpreted as decimal values. +Example: +
    ok> decimal 123 . cr
    123
    ok> 0x123 . cr
    291
    ok> 0x123 x. cr
    123
    +Note: ficl2.05 and later - this behavior is controlled by the prefix parser defined in prefix.c. +You can add other prefixes by defining handlers for them in ficl +or C. +

    The SEARCH wordset and Ficl +extensions

    +

    Ficl implements many of the search order words in terms of two +primitives called >SEARCH and SEARCH>. As their names +suggest (assuming you're familiar with Forth), they push and pop the +search order stack.

    +

    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 ABORT happens. This includes +stack underflows and overflows. QUIT does not affect the search +order. The minimum search order (set by ONLY) is equivalent +to

    +
    FORTH-WORDLIST 1 SET-ORDER
    +

    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).

    +

    Note: Ficl resets the search order whenever it does ABORT. +If you don't like this behavior, just comment out the +dictResetSearchOrder() lines in ficlExec().

    +
    +
    >search ( wid -- )
    +
    Push wid onto the search order. Many of the other search +order words are written in terms of the SEARCH> and >SEARCH +primitives. This word can be defined in ANS Forth as follows
    +
    : >search   >r get-order 1+ r> swap +set-order ;
    +
    search>   ( -- wid )
    +
    Pop wid off the search order (can be coded in ANS Forth +as : search>  get-order nip 1- set-order ; )
    +
    ficl-set-current   ( +wid -- old-wid )
    +
    Set wid as compile wordlist, leaving the previous compile +wordlist on the stack
    +
    ficl-vocabulary   ( +nBins "name" -- )
    +
    Creates a ficl-wordlist with the specified number of +hash table bins, binds it to the name, and associates the semantics of vocabulary +with it (replaces the top wid in the search order list with +its own wid when executed)
    +
    ficl-wordlist   ( nBins +-- wid )
    +
    Creates a wordlist with the specified number of hash table bins, +and leaves the address of the wordlist on the stack. A ficl-wordlist +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. ficl-named-wordlist takes a name for the +wordlist and creates a word that pushes the wid. This is by +contrast to VOCABULARY, which also has a name, but replaces +the top of the search order with its wid.
    +
    forget-wid   ( wid -- )
    +
    Iterates through the specified wordlist and unlinks all +definitions whose xt addresses are greater than or equal to the value of HERE, +the dictionary fill pointer. 
    +
    hide   ( -- current-wid-was +)
    +
    Push the hidden wordlist onto the search order, and set +it as the current compile wordlist (unsing ficl-set-current). +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  previous set-current
    +
    hidden   ( -- wid )
    +
    Wordlist for storing implementation factors of ficl provided +words. To see what's in there, try:  hide words previous +set-current
    +
    wid-get-name   ( wid -- +c-addr u )
    +
    Ficl wordlists (2.05 and later) have a name property that can be +assigned. This is used by ORDER to list the names of wordlists +in the search order. 
    +
    wid-set-name   ( c-addr +wid -- )
    +
    Ficl wordlists (2.05 and later) have a name property that can be +assigned. This is used by ORDER 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.  See softwords/softcore.fr definition of brand-wordlist 
    +
    wid-set-super   ( wid +-- )
    +
    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 SEARCH-WORDLIST 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.
    +
    +

    User variables

    +
    +
    user   ( -- ) name
    +
    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 VARIABLEs +in all other respects (you use @ and ! on them, for example). +Example:
    +
    +
    +
    user current-class
    +
    0 current-class !
    +
    +
    +
    +

    Miscellaneous

    +
    +
    -roll   ( xu xu-1 ... x0 u -- x0 xu-1 ... x1 +) 
    +
    Rotate u+1 items on top of the stack after removing u. Rotation +is in the opposite sense to ROLL
    +
    +
    +
    -rot   ( a b c -- c a b )
    +
    Rotate the top three stack entries, moving the top of stack to +third place. I like to think of this as 11/2swap +because it's good for tucking a single cell value behind a +cell-pair (like an object). 
    +
    +
    +
    .env   ( -- )
    +
    List all environment variables of the system
    +
    .hash   ( -- )
    +
    List hash table performance statistics of the wordlist that's +first in the search order
    +
    .ver   ( -- )
    +
    Display ficl version ID
    +
    >name   ( xt -- c-addr u )
    +
    Convert a word's execution token into the address and length of +its name
    +
    body>   ( a-addr -- xt )
    +
    Reverses the effect of CORE word >body +(converts a parameter field address to an execution token)
    +
    compile-only
    +
    Mark the most recently defined word as being executable only +while in compile state. Many immediate words have this +property.
    +
    empty   ( -- ) 
    +
    Empty the parameter stack
    +
    endif
    +
    Synonym for THEN
    +
    last-word   ( -- xt )
    +
    Pushes the xt address of the most recently defined word. This +applies to colon definitions, constants, variables, and words that use create. +You can print the name of the most recently defined word +with 
    +
    last-word >name type 
    +
    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. (From the Standard)
    +
    q@   ( addr -- x )
    +
    Fetch a 32 bit quantity from the specified address
    +
    q!   ( x addr -- )
    +
    Store a 32 bit quantity to the specified address 
    +
    w@   ( addr -- x )
    +
    Fetch a 16 bit quantity from the specified address
    +
    w!   ( x addr -- )
    +
    Store a 16 bit quantity to the specified address (the low 16 bits +of the given value)
    +
    x.   ( x -- )
    +
    Pop and display the value in hex format, regardless of the +current value of BASE
    +
    +

    Extra words defined in testmain.c (Win32 +and POSIX versions)

    +
    +
    break   ( -- )
    +
    Does nothing - just a handy place to set a debugger breakpoint
    +
    cd      ( +"directory-name<newline>" -- )
    +
    Executes the Win32 chdir() function, changing the program's +logged directory.
    +
    clock   ( -- now )
    +
    Wrapper for the ANSI C clock() function. Returns the number of +clock ticks elapsed since process start.
    +
    clocks/sec   ( -- +clocks_per_sec )
    +
    Pushes the number of ticks in a second as returned by clock
    +
    load    ( +"filename<newline>" -- )
    +
    Opens the Forth source file specified and loads it one line at a +time, like INCLUDED (FILE)
    +
    pwd     ( -- )
    +
    Prints the current working directory as set by cd
    +
    system  ( "command<newline>" -- )
    +
    Issues a command to a shell; implemented with the Win32 system() +call.
    +
    spewhash   ( "filename<newline>" -- )
    +
    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.
    +
    +

    Words defined in FiclWin only

    +
    +
    !oreg   ( c -- )
    +
    Set the value of the simulated LED register as specified (0..255) +
    +
    @ireg   ( -- c )
    +
    Gets the value of the simulated switch block (0..255)
    +
    !dac    ( c -- )
    +
    Sets the value of the bargraph control as specified. Valid values +range from 0..255
    +
    @adc    ( -- c )
    +
    Fetches the current position of the slider control. Range is +0..255
    +
    status"   ( "ccc<quote>" -- )
    +
    Set the mainframe window's status line to the text specified, up +to the first trailing quote character.
    +
    ms   +( u -- )
    +
    Causes the running virtual machine to sleep() for the number of +milliseconds specified by the top-of-stack value.
    +
    +
    +

    ANS Required Information

    +ANS Forth System
    +Providing names from the Core Extensions word set 
    +Providing the Exception word set
    +Providing names from the Exception Extensions word set
    +Providing the Locals word set 
    +Providing the Locals Extensions word set 
    +Providing the Memory Allocation word set
    +Providing the Programming-Tools word set
    +Providing names from the Programming-Tools Extensions word set
    +Providing the Search-Order word set
    +Providing the Search-Order Extensions word set +

    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.  +
      +
    • aligned address requirements (3.1.3.3 Addresses); 
    • +

    • + 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 ALIGN and ALIGNED to align on 4 +byte boundaries. To align on 2n byte boundaries, set +FICL_ALIGN to n
    • +
    • behavior of 6.1.1320 EMIT for non-graphic characters
    • +

    • + Depends on target system, C runtime library, +and your implementation of ficlTextOut().
    • +
    • character editing of 6.1.0695 ACCEPT and 6.2.1390 EXPECT
    • +

    • + 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.
    • +
    • character set (3.1.2 Character types, 6.1.1320 EMIT, 6.1.1750 +KEY)
    • +

    • + Depends on target system and implementation +of ficlTextOut()
    • +
    • character-aligned address requirements (3.1.3.3 Addresses)
    • +

    • + Ficl characters are one byte each. There are +no alignment requirements.
    • +
    • 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.
    • +
    • conditions under which control characters match a space +delimiter (3.4.1.1 Delimiters); 
    • +

    • + Ficl uses the Standard C function isspace() +to distinguish space characters. The rest is up to your library vendor.
    • +
    • format of the control-flow stack (3.2.3.2 Control-flow stack)
    • +

    • + Uses the data stack
    • +
    • conversion of digits larger than thirty-five (3.2.1.2 Digit +conversion)
    • +

    • + The maximum supported value of BASE +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, however, other than possibly +unexpected behavior. 
    • +
    • display after input terminates in 6.1.0695 ACCEPT and +6.2.1390 EXPECT
    • +

    • + Target system dependent
    • +
    • exception abort sequence (as in 6.1.0680 ABORT")
    • +

    • + Does ABORT
    • +
    • input line terminator (3.2.4.1 User input device); 
    • +

    • + Target system dependent (implementation of +outer loop that calls ficlExec)
    • +
    • maximum size of a counted string, in characters (3.1.3.4 +Counted strings, 6.1.2450 WORD)
    • +

    • + 255
    • +
    • 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 (232-1). 
    • +
    • maximum size of a definition name, in characters (3.3.1.2 +Definition names)
    • +

    • + Ficl stores the first 31 characters of a +definition name.
    • +
    • maximum string length for 6.1.1345 ENVIRONMENT?, in characters
    • +

    • + Same as maximum definition name length
    • +
    • method of selecting 3.2.4.1 User input device
    • +

    • +None supported. This is up to the target system 
    • +
    • method of selecting 3.2.4.2 User output device
    • +

    • +None supported. This is up to the target system 
    • +
    • methods of dictionary compilation (3.3 The Forth dictionary)
    • +
    • number of bits in one address unit (3.1.3.3 Addresses)
    • +

    • + Target system dependent. Ficl generally +supports processors that can address 8 bit quantities, but there is no +dependency that I'm aware of.
    • +
    • number representation and arithmetic (3.2.1.1 Internal number +representation)
    • +

    • +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. 
    • +
    • ranges for n, +n, u, d, +d, and ud (3.1.3 Single-cell types, +3.1.4 Cell-pair types)
    • +

    • +Assuming a 32 bit implementation, range for signed single-cell values +is -231..231-1. Range for unsigned single cell +values is 0..232-1. Range for signed double-cell +values is -263..263-1. Range for unsigned single +cell values is 0..264-1. 
    • +
    • read-only data-space regions (3.3.3 Data space);
    • +

    • +None 
    • +
    • size of buffer at 6.1.2450 WORD (3.3.3.6 Other transient +regions)
    • +

    • +Default is 255. Depends on the setting of nPAD in ficl.h. 
    • +
    • size of one cell in address units (3.1.3 Single-cell types)
    • +

    • + System dependent, generally four.
    • +
    • size of one character in address units (3.1.2 Character types)
    • +

    • + System dependent, generally one.
    • +
    • 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.
    • +
    • size of the pictured numeric output string buffer (3.3.3.6 +Other transient regions)
    • +

    • +Default is 255 characters. Depends on the setting of nPAD in +ficl.h. 
    • +
    • size of the scratch area whose address is returned by +6.2.2000 PAD (3.3.3.6 Other transient regions)
    • +

    • +Not presently supported 
    • +
    • system case-sensitivity characteristics (3.4.2 Finding +definition names)
    • +

    • + Ficl is not case sensitive
    • +
    • system prompt (3.4 The Forth text interpreter, 6.1.2050 QUIT)
    • +

    • + "ok>"
    • +
    • 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
    • +
    • values of 6.1.2250 STATE when true
    • +

    • + One (no others)
    • +
    • values returned after arithmetic overflow (3.2.2.2 Other +integer operations)
    • +

    • +System dependent. Ficl makes no special checks for overflow. 
    • +
    • whether the current definition can be found after 6.1.1250 +DOES> (6.1.0450 :)
    • +

    • + No. Definitions are unsmudged after ; only, +and only then if no control structure matching problems have been +detected.
    • +
    +

    Ambiguous Conditions

    +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.  +

    The following general ambiguous conditions could occur because of a +combination of factors: 

    +
      +
    • a name is neither a valid definition name nor a valid number +during text interpretation (3.4 The Forth text interpreter)
    • +

    • + Ficl does ABORT and prints the name +followed by " not found".
    • +
    • 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.
    • +
    • 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.
    • +
    • 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.
    • +
    • 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.
    • +
    • 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.
    • +
    • insufficient data-stack space or return-stack space (stack +overflow)
    • +

    • + With FICL_ROBUST (sysdep.h) set >= 2, most +parameter stack operations are checked for underflow and overflow. Ficl +does not check the return stack.
    • +
    • insufficient space for loop-control parameters
    • +

    • + No check - Evil results.
    • +
    • insufficient space in the dictionary
    • +

    • + Ficl generates an error message if the +dictionary is too full to create a definition header. It checks ALLOT +as well, but it is possible to make an unchecked allocation +request that overflows the dictionary.
    • +
    • 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 EXECUTE, though.
    • +
    • 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.
    • +
    • overflow of a pictured numeric output string;
    • +

    • +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. 
    • +
    • 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 SLITERAL, you +need to have enough room for the string, otherwise bad things may +happen. This is not usually a problem. 
    • +
    • 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 +>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
    • +
    • reading from an empty data stack or return stack (stack +underflow)
    • +

    • + 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.
    • +
    • 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.
    • +
    +The following specific ambiguous conditions are noted in the glossary +entries of the relevant words:  +
      +
    • >IN greater than size of input buffer (3.4.1 Parsing)
    • +

    • +Bad Things occur - unpredictable bacause the input buffer is supplied +by the host program's outer loop. 
    • +
    • 6.1.2120 RECURSE appears after 6.1.1250 DOES>
    • +

    • +It finds the address of the definition before DOES>
    • +
    • argument input source different than current input source for +6.2.2148 RESTORE-INPUT
    • +

    • +Not implemented 
    • +
    • data space containing definitions is de-allocated (3.3.3.2 +Contiguous regions)
    • +

    • +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. 
    • +
    • data space read/write with incorrect alignment (3.3.3.1 +Address alignment)
    • +

    • +Target processor dependent. Consequences include: none (Intel), address +error exception (68K). 
    • +
    • data-space pointer not properly aligned (6.1.0150 ,, 6.1.0860 +C,)
    • +

    • +See above on data space read/write alignment 
    • +
    • less than u+2 stack items (6.2.2030 PICK, 6.2.2150 ROLL)
    • +

    • +Ficl detects a stack underflow and reports it, executing ABORT, +as long as FICL_ROBUST is two or larger. 
    • +
    • 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 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. 
    • +
    • most recent definition does not have a name (6.1.1710 +IMMEDIATE)
    • +

    • +No problem. 
    • +
    • name not defined by 6.2.2405 VALUE used by 6.2.2295 TO
    • +

    • +Ficl's version of TO works correctly with VALUEs, CONSTANTs +and VARIABLEs. 
    • +
    • name not found (6.1.0070 ', 6.1.2033 POSTPONE, 6.1.2510 ['], +6.2.2530 [COMPILE])
    • +

    • +Ficl prints an error message and does ABORT
    • +
    • parameters are not of the same type (6.1.1240 DO, 6.2.0620 +?DO, 6.2.2440 WITHIN)
    • +

    • +No check. Results vary depending on the specific problem. 
    • +
    • 6.1.2033 POSTPONE or 6.2.2530 [COMPILE] applied to 6.2.2295 TO
    • +

    • +The word is postponed correctly. 
    • +
    • string longer than a counted string returned by 6.1.2450 WORD
    • +

    • +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.) 
    • +
    • 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 << and >> operators on unsigned values. For I386, the +processor appears to shift modulo the number of bits in a +cell. 
    • +
    • word not defined via 6.1.1000 CREATE (6.1.0550 >BODY, +6.1.1250 DOES>)
    • +

    • + words improperly used outside 6.1.0490 <# and 6.1.0040 #> +(6.1.0030 #, 6.1.0050 #S, 6.1.1670 HOLD, 6.1.2210 SIGN)
      +Don't. CREATE reserves a field in words it builds for DOES>to +fill in. If you use DOES> on a word not made by CREATE, +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.
    • +
    +

    Locals Implementation-defined options

    +
      +
    • maximum number of locals in a definition (13.3.3 Processing +locals, 13.6.2.1795 LOCALS|)
    • +

    • +Default is 16. Change by redefining FICL_MAX_LOCALS, defined in +sysdep.h
    • +
    +

    Locals Ambiguous conditions

    +
      +
    • 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. 
    • +
    • name not defined by VALUE or LOCAL (13.6.1.2295 TO)
    • +

    • +See the CORE ambiguous conditions, above (no change)
    • +
    +

    Programming Tools Implementation-defined options

    +
      +
    • source and format of display by 15.6.1.2194 SEE
    • +

    • +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.
    • +
    +

    Search Order Implementation-defined options

    +
      +
    • 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 FICL_DEFAULT_VOCS, +declared in sysdep.h 
    • +
    • minimum search order (16.6.1.2197 SET-ORDER, 16.6.2.1965 ONLY) 
    • +

    • +Equivalent to FORTH-WORDLIST 1 SET-ORDER
    • +
    +

    Search Order Ambiguous conditions

    +
      +
    • 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 new compile wordlist. 
    • +
    • 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. 
    • +
    • 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.
    • +
    + + + Index: vendor/ficl/dist/doc/source/generate.py =================================================================== --- vendor/ficl/dist/doc/source/generate.py (nonexistent) +++ vendor/ficl/dist/doc/source/generate.py (revision 282803) @@ -0,0 +1,244 @@ +import cStringIO +import os +import re +import shutil +import string +import sys + + +outputStart = None +navBarEntries = {} + + + +def ficlLinkEntry(file, title): + print("" + title + "

    \n") + + + +currentNavBarName = None + +def ficlAddToNavBarAs(name): + global currentNavBarName + currentNavBarName = name + + +def ficlPageHeader(heading): + outputStart.write(""" + + + + + +""" + heading + """ +\n + + + +\n + + + + + +\n + +
    + + + +""" + heading + """ + +
    +

    +Index

    +""") + + print("

    \n") + + + +def ficlPageFooter(): + print("\n

    \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(""" +

    +

    + + +
    +") + print("") + print(heading) + print("

    \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("
  • " + name + "\n") + if len(section[1]) != 0: + f.write("
      \n") + dump(f, section[1]) + f.write("
    \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("") + 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("


    \n") + keys = navBarEntries.keys() + keys.sort() + for name in keys: + filename = navBarEntries[name] + f.write("") + name = name.replace(" ", " ") + f.write("" + name + "") + f.write("
    \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("

      \n") +# dump(f, sections[0]) +# f.write("
    \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) + + Property changes on: vendor/ficl/dist/doc/source/generate.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/doc/source/index.ht =================================================================== --- vendor/ficl/dist/doc/source/index.ht (nonexistent) +++ vendor/ficl/dist/doc/source/index.ht (revision 282803) @@ -0,0 +1,244 @@ +
    \n" + preamble + " " + keyfeature + " " + postscript + "\n
    \n" + +?> + + + + + +Ficl is a programming language interpreter designed to be embedded +into other systems as a command, macro, and development prototyping +language. +

    + +Ficl is an acronym for "Forth Inspired Command Language". + + + + +

    + + + + +
      + +
    • +It typically takes under 2 hours to port to a new platform. + +
    • +Ficl is written in strict ANSI C. + +
    • +Ficl can run natively on 32- and 64-bit processors. + +
    + + + + + +A fully featured Win32 console version takes less than 100K +of memory, and a minimal version is less +than half that. + + + + + +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. + + + + + +Thanks to its +"switch-threaded" +virtual machine design, Ficl 4 is faster than ever—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. + + + + + +Ficl is an implementation of the FORTH language, a language providing +a wide range of standard programming language features: +
      + +
    • +Integer and floating-point numbers, with a rich set of operators. + +
    • +Arrays. + +
    • +File I/O. + +
    • +Flow control (if/then/else and many looping structures). + +
    • +Subroutines with named arguments. + +
    • +Language extensibility. + +
    • +Powerful code pre-processing features. + +
    + + + + + +Ficl conforms to the 1994 ANSI Standard for FORTH (DPANS94). +See ANS Required Information for +more detail. + + + + +Ficl is extensible both at compile-time and at run-time. +You can add new script functions, new native functions, +even new control structures. + + + + + + +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.) + + + + + +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. + + + + +Ficl is designed to work in RAM based and ROM code / RAM +data environments. + + + + + +Ficl is reentrant and thread-safe. After initialization, +it does not write to any global data. + + + + +The Ficl licence is a BSD-style +license, requiring only that you document that you are +using Ficl. There are no licensing costs for using Ficl. + + +
    + + + + + + +Ficl 4.0 is a major change for Ficl. Ficl 4.0 is smaller, +faster, more powerful, and easier to use +than ever before. (Or your money back!) +

    + +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 three times as fast as Ficl 3.03. +

    + +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! +

    + +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 FICL_HAVE_NATIVE_2INTEGER +to 1, and create typedefs for ficl2Integer +and ficl2Unsigned. +

    + +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 +FICL_WANT_COMPATIBILITY. +

    + +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 TO always does the right thing. +

    + +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 +

      + +
    • +a static library (.LIB), + +
    • +a dynamic library (.DLL, with a .LIB import library), and + +
    • +a standalone executable (.EXE). + +
    + +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 +/objects/common nonsense is gone!) +

    + + +Finally, Ficl 4.0 adds a contrib +directory, a repository for user-contributed code that isn't +part of the standard Ficl release. The only package there +right now is XClasses, 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 XClasses you can write your class once, and use it +immediately from both C++ and Ficl. + + + + +You can download Ficl from the + +Ficl download page at Sourceforge. + + + Index: vendor/ficl/dist/doc/source/license.ht =================================================================== --- vendor/ficl/dist/doc/source/license.ht (nonexistent) +++ vendor/ficl/dist/doc/source/license.ht (revision 282803) @@ -0,0 +1,47 @@ + + + +Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) +
    +All rights reserved. +
    +

    + + +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. + + + Index: vendor/ficl/dist/doc/source/links.ht =================================================================== --- vendor/ficl/dist/doc/source/links.ht (nonexistent) +++ vendor/ficl/dist/doc/source/links.ht (revision 282803) @@ -0,0 +1,156 @@ +
    \n" + href + "\n
    \n" + +?> + + + +
    + + +The official web home of Ficl. + + +The Ficl download page. + + +
    + + + + + +
    + + +An excellent Forth primer, by Julian Nobel. + + +Another excellent Forth primer, by Hans Bezemer. + + +An Introduction To Forth Using Stack Flow by Gordon Charton. +Mr. Charton's stack-flow diagrams make it easy to understand how +to manipulate the FORTH stacks. + + +Phil Burk's Forth Tutorial. + +
    + + + + + +
    + + +Manuscript of John Sadler's article on Ficl for January 1999 Dr. Dobb's Journal. + + +1998 FORML Conference paper: OO Programming in Ficl, written and presented by John Sadler. + + + +Anton Ertl's description of threaded code techniques. (The FORTH-related definition +of "threaded code" is different from—and predates—the common modern +usage dealing with light-weight processes.) Ficl 4 uses what Ertl calls +"switch threading". + + +1994 Draft Proposed American National Standard for Forth. +And surprisingly readable, as language standards go. + + +Forth literature index on Taygeta, a web clearinghouse of Forth links. + +
    + + + +
    + + +The Forth Interest Group. + + +FORTH, Incorporated. Thirty years old and going strong. +You might be surprised to learn that they wrote software for +the FedEx +"SuperTracker" bar code scanners / package trackers. + +
    + +
    +Forth Webring Logo + + +Previous 5 Sites
    +Previous
    +Next
    +Next 5 Sites
    +Random Site
    +List Sites +
    + + + + + + + +(Contact us if you'd like your name and product listed here.) + + + Index: vendor/ficl/dist/doc/source/locals.ht =================================================================== --- vendor/ficl/dist/doc/source/locals.ht (nonexistent) +++ vendor/ficl/dist/doc/source/locals.ht (revision 282803) @@ -0,0 +1,133 @@ +\n" + definition + "\n\n" + description + "\n\n" + +?> + + + + + + +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). +

    + +Ficl provides excellent support +for local variables, and the purists be damned—we use 'em all the time. +

    + +Local variables can only be declared inside a definition, +and are only visible in that definition. Please refer to + +the ANS standard for FORTH + for more general information on local variables. + + + + +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. + +

    + +Here's the basic syntax of a JH-local variable declaration: +

    +{ arguments +| locals +-- ignored +} +
    +(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: + +
      + +
    • +The arguments 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. +

      + +

    • +The locals section lists local variables which are set to zero when the word executes. +You can have zero or more locals. +

      + +

    • +Any characters between -- and } are treated as a comment, and ignored. + +
    + +(The | and -- sections are optional, +but they must appear in the order shown if they appear at all.) +

    + + + + +Every time you specify a local variable (in either the arguments or the locals section), +you can also specify the type 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. +

    + +To specify the type of a local, specify one or more of the following single-character specifiers, +followed by a colon (:). + + + + + + + + + + + + + + + +
    + +For instance, the argument f2:foo would specify a double-width floating-point +number. +

    + +The type specifiers are read right-to left, and when two specifiers conflict, the rightmost +one takes priority. So 2is1f2:foo would still specifiy a double-width floating-point +number. +

    + +Note that this syntax only works for Ficl's JH-locals. Locals +defined in some other way (say, with the FORTH standard word LOCALS|) +will ignore this syntax, and the entire string will be used as the name of +the local (type and all). + + + +

    +: DEMONSTRATE-JH-LOCALS { c b a  f:float -- a+b f:float*2 }
    +	a b +
    +	2.0e float f*
    +	;
    +
    + + \ No newline at end of file Index: vendor/ficl/dist/doc/source/oop.ht =================================================================== --- vendor/ficl/dist/doc/source/oop.ht (nonexistent) +++ vendor/ficl/dist/doc/source/oop.ht (revision 282803) @@ -0,0 +1,1224 @@ +" + name + " " + description + "
    \n" + +?> + + + + +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. +

    + +Some design points of Ficl's OOP system: + +

      + +
    • +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. + +
    • +Ficl OOP supports single inheritance, aggregation, and arrays of objects. + +
    • +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. + +
    • +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. + +
    • +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 ref object +can then manipulate the structure directly. This lets you wrap data structures +written and instantiated in C. + +
    + + + +If you're not familiar with object-oriented programming, you +can click here +or here for +a general-purpose overview. +Or click here for a short review of object-oriented ideas, +terms, and implementations in C. + + + +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 (below) 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. + + + + +All classes in Ficl are derived from the common base class +OBJECT +as shown in the figure below. All classes are instances +of METACLASS. This means that classes +are objects, too. METACLASS 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: + +
      + +
    1. +The address (named .CLASS ) of a parent class, or zero if it's +a base class (only OBJECT and METACLASS have this property). + +
    2. +The size (named .SIZE ) in address units of an instance of the +class. + +
    3. +A wordlist ID (named .WID ) for the methods of the class. + +
    + +In the figure below, METACLASS and OBJECT 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. +

    + +Note for the curious: METACLASS behaves like a class—it responds +to class messages and has the same properties as any other class. If you +want to twist your brain in knots, you can think of METACLASS +as an instance of itself. +

    + + + +
    + + + + +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 web-based +Forth tutorial. If you're comfortable with both OO and Forth, you can +jump ahead. +

    + +A Ficl object associates a class +with an instance (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: +

    ( INSTANCE-address CLASS-address )
    + +The INSTANCE-address is the address of the object's storage, and the CLASS-address +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 vtable +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. +

    + +Whenever you create an object in Ficl, you specify its class. +After that, the object always pushes its class and the address of its +payload +(instance variable space) when invoked by name. +

    + +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 METACLASS, +and all classes inherit from class OBJECT. This is confusing at +first, but it means that Ficl has a very simple syntax for constructing +and using objects. Class methods include subclassing (SUB), creating +initialized and uninitialized instances (NEW and INSTANCE), +and creating reference instances (REF), described later. Classes +also have methods for disassembling their methods (SEE), identifying +themselves (ID), and listing their pedigree (PEDIGREE). +All objects inherit (from OBJECT) methods for initializing instances +and arrays of instances, for performing array operations, and for getting +information about themselves. + + + +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 polymorphically. +(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 --> that sends messages +to objects at run-time, and an early-binding operator => +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. + + + + + +(Finally!) +

    + +This is a tutorial. It works best if you follow along by pasting the examples +into ficlWin, the Win32 version of Ficl included with the release sources +(or some other build that includes the OO part of softcore.c). If you're +not familiar with Forth, please see one of these references. +Ficl's OOP words are in vocabulary OOP. To put OOP in +the search order and make it the compilation wordlist, type: +

    +ONLY
    +ALSO OOP DEFINITIONS
    +
    + +Note for beginners: To see the effect of the commands above, type +ORDER +after each line. You can repeat the sequence above if you like. +

    + +To start, we'll work with the two base classes OBJECT and METACLASS. +Try this: +

    +METACLASS --> METHODS
    +
    + +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 METACLASS, METACLASS 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 METHODS. +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. +
    +OBJECT --> SUB C-LED
    +
    +Causes the base-class OBJECT to derive from itself a new class +called C-LED. Now we'll add some instance variables and methods to the new class. +

    + +Note: I like to prefix the names of classes with c- and the +names of member variables with a period, but this is just a convention. +If you don't like it, pick your own. +

    +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
    +
    +The first line adds an instance variable called .STATE to the +class. This particular instance variable is an object—it will be an instance +of C-BYTE, one of Ficl's stock classes (the source for which can be found +in the distribution in softcore/classes.fr). +

    + +Next we've defined a method called INIT. This line also declares +a local variable called THIS +(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 INIT when it's called. +It first calls its superclass's version of INIT (which in this +case is "OBJECT => INIT"—this default implementation clears all +instance variables). The rest displays some text and causes the instance +to print its class name (THIS --> CLASS --> ID). +

    + +The INIT> method is special for Ficl objects: whenever +you create an initialized instance using NEW or NEW-ARRAY, +Ficl calls the class's INIT method for you on that instance. The +default INIT method supplied by OBJECT clears the instance, +so we didn't really need to override it in this case (see the source code +in softcore/oo.fr). +

    + +The ON and OFF methods defined above hide the details +of turning LEDs on and off. The interface to FiclWin's simulated hardware +is handled by !OREG. The class keeps the LED state in a shadow +variable (.STATE) so that ON and OFF can work +in terms of LED number rather than a bitmask. +

    + +Now make an instance of the new class: +

    +C-LED --> NEW LED
    +
    + +And try a few things... +
    +LED --> METHODS
    +LED --> PEDIGREE
    +1 LED --> ON
    +1 LED --> OFF
    +
    + +Or you could type this with the same effect: +
    +LED  2DUP  --> METHODS  --> PEDIGREE
    +
    + +Notice (from the output of METHODS) that we've overridden the +INIT method supplied by object, and added two more methods for the member +variables. If you type WORDS, you'll see that these methods are +not visible outside the context of the class that contains them. The method +finder --> uses the class to look up methods. You can use +this word in a definition, as we did in INIT, 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: +
    +C-LED --> SEE INIT
    +
    + +or +
    +LED --> CLASS --> SEE INIT
    +
    + + + +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. +

    + +Here's an example that illustrates a potential problem: +

    +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)
    +
    + +Even though we overrode method M1 in class C2, the definition of M2 with +early binding forced the use of M1 as defined in C1. If that's what you +want, great, but more often you'll want the flexibility of overriding parent +class behaviors appropriately. + +
      + +
    1. +MY=> binds early to a method in the class being defined, +as in the example above. + +
    2. +MY=[ ] binds a sequence of methods in the current class. +Useful when the class has object members. Lines like +THIS --> STATE --> SET in the definition of C-LED above can be replaced with +THIS MY=[ STATE SET ] to use early binding. + +
    3. +=> (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 MY=> or MY=[ ] instead. + +
    + +Early binding using => 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 INIT 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 METACLASS. Here's an example from the definition of METACLASS +in oo.fr (don't paste this into ficlWin—it's already there): +
    +: NEW   \ ( class metaclass "name" -- )
    +    METACLASS => INSTANCE --> INIT ;
    +
    + +Try this: +
    +METACLASS --> SEE NEW
    +
    + +Decompiling the method with SEE 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. +

    + +Notice that the primitive early-binding operator => requires +a class at compile time. For this reason, classes are IMMEDIATE, +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. + + + +Untyped instance variable methods (created by CELL: CELLS: CHAR: +and CHARS:) 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. +

    + +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 ref from this class, +supplying the address of the structure. After that, the ref instance +behaves as a Ficl object, but its instance variables take on the values +in the existing structure. Example (from softcore/ficlclass.fr): +

    +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
    +
    + +In this case, C-WORDLIST describes Ficl's wordlist structure; +NAMED-WID creates a wordlist and binds it to a ref instance of +C-WORDLIST. +The fancy footwork with POSTPONE and early binding is required +because classes are immediate. An equivalent way to define NAMED-WID with +late binding is: +
    +: NAMED-WID   ( c-address u -- )
    +    WORDLIST   POSTPONE C-WORDLIST --> REF
    +    ;
    +
    + +To do the same thing at run-time (and call it MY-WORDLIST): + +
    wordlist  c-wordlist --> ref  my-wordlist
    + +Now you can deal with the wordlist through the ref instance: +
    +MY-WORDLIST --> PUSH
    +MY-WORDLIST --> SET-CURRENT
    +ORDER
    +
    + +Ficl can also model linked lists and other structures that contain pointers +to structures of the same or different types. The class constructor word +REF: +makes an aggregate reference to a particular class. See the instance +variable glossary for an example. +

    + +Ficl can make arrays of instances, and aggregate arrays into class descripions. +The class methods ARRAY and NEW-ARRAY +create uninitialized and initialized arrays, respectively, of a class. +In order to initialize an array, the class must define (or inherit) a reasonable +INIT method. NEW-ARRAY invokes it on each member of the array +in sequence from lowest to highest. Array instances and array members use +the object methods INDEX, NEXT, and PREV +to navigate. Aggregate a member array of objects using ARRAY:. +The objects are not automatically initialized in this case—your class +initializer has to call ARRAY-INIT explicitly if you want +this behavior. +

    + +For further examples of OOP in Ficl, please see the source file softcore/ficlclass.fr. +This file wraps several Ficl internal data structures in objects and gives +use examples. + + + + + +C-STRING is a reasonably useful dynamic string class. +Source code for the class is located in softcore/string.fr. +Features: +dynamic creation and resizing; deletion, char cout, concatenation, output, +comparison; creation from quoted string constant (S"). +

    +Examples of use: +

    +C-STRING --> NEW HOMER
    +S" In this house, " HOMER --> SET
    +S" we obey the laws of thermodynamics!" HOMER --> CAT
    +HOMER --> TYPE
    +
    + + + + + + +Note: With the exception of the binding operators (the first two definitions +here), all of the words in this section are internal factors that you don't +need to worry about. These words provide method binding for all classes +and instances. Also described are supporting words and execution factors. +All are defined in softcore/oo.fr. + +
    + +", "( 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. + +", "( instance class \"method-name\" -- xn exc )") ?> + +Late binding with CATCH: looks up and CATCHes the given +method in the context of the class on top of the stack, pushes zero or +exception code upon return. + +", "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 --> SUB .. END-CLASS +class definition. + + + +Early binding: compiles code to execute a chain of methods of the class +being defined. Only visible and valid in the scope of a --> SUB +.. END-CLASS class definition. + +", "compilation: ( class metaclass \"method-name\" -- ) execution: ( instance class -- xn )") ?> + +Early binding: compiles code to execute the method of the class specified +at compile time. + + + +When executed, causes the instance to push its ( INSTANCE CLASS ) stack +signature. Implementation factor of METACLASS --> SUB . +Compiles .DO-INSTANCE in the context of a class; .DO-INSTANCE +implements the DOES> part of a named instance. + + + +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. + + + +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. + + + +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. + + + +Parse "method-name" from the input stream and compile code to push its length +and address when the enclosing definition runs. +
    + + + + +Note:: These words are only visible when creating a subclass! To +create a subclass, use the SUB method on OBJECT or any +class derived from it (not METACLASS). Source code for +Ficl OOP is in softcore/oo.fr. +

    + +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 instance variable 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: + +

    +OBJECT SUBCLASS C-EXAMPLE
    +  CELL:            .CELL0
    +  C-4BYTE     OBJ: .NCELLS
    +  4 C-4BYTE ARRAY: .QUAD
    +  CHAR:            .LENGTH
    +  79 CHARS:        .NAME
    +END-CLASS
    +
    + +This class only defines instance variables, and it inherits some methods +from OBJECT. Each untyped instance variable (.CELL0, .LENGTH, +.NAME) pushes its address when executed. Each object instance variable +pushes the address and class of the aggregate object. Similar to C, an +array instance variable leaves its base address (and its class) when executed. +The word SUBCLASS is shorthand for --> sub . + +
    + + + +Create an untyped instance variable one cell wide. The instance variable +leaves its payload's address when executed. + + + +Create an untyped instance variable nCells cells wide. + + + +Create an untyped member variable one character wide. + + + +Create an untyped member variable nChars characters wide. + + + +Aggregate an uninitialized instance of CLASS as a member variable +of the class under construction. + + + + +Aggregate an uninitialized array of instances of the class specified as +a member variable of the class under construction. + + + +Aggregate a reference to a class instance. There is no way to set the value +of an aggregated ref—it's meant as a way to manipulate existing data +structures with a Ficl OO model. For example, if your system contains a +linked list of 4 byte quantities, you can make a class that represents +a list element like this: + +
    +OBJECT SUBCLASS C-4LIST
    +  C-4LIST REF: .LINK
    +  C-4BYTE OBJ: .PAYLOAD
    +END-CLASS
    +
    +ADDRESS-OF-EXISTING-LIST C-4LIST --> REF MYLIST
    +
    + +
    +The last line binds the existing structure to an instance of the class +we just created. The link method pushes the link value and the class C_4LIST, +so that the link looks like an object to Ficl and like a struct to C (it +doesn't carry any extra baggage for the object model—the Ficl methods +alone take care of storing the class information). +

    + +Note: Since a REF: aggregate can only support one class, it's good for +modeling static structures, but not appropriate for polymorphism. If you +want polymorphism, aggregate a C_REF (see softcore/classes.fr for source) +into your class—it has methods to set and get an object. +

    + +By the way, it is also possible to construct a pair of classes that contain +aggregate pointers to each other. Here's an example: + +

    +OBJECT SUBCLASS AKBAR
    +  SUSPEND-CLASS         \ put akbar on hold while we define jeff
    +
    +OBJECT SUBCLASS JEFF
    +  AKBAR REF: .SIGNIFICANT-OTHER
    +  ( ... your additional methods here ... )
    +END-CLASS               \ done with jeff
    +
    +AKBAR --> RESUME-CLASS  \ resume defining akbar
    +  JEFF REF: .SIGNIFICANT-OTHER
    +  ( ... your additional methods here ... )
    +END-CLASS               \ done with akbar
    +
    + +
    + + + + +These words are methods of METACLASS. 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 softcore/oo.fr. + +
    + + + +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: + +
    +C_REF --> INSTANCE UNINIT-REF  2DROP
    +
    + + + +Create an initialized instance of class, giving it the name specified. +This method calls INIT to perform initialization. + + + +Create an array of nObjects instances of the specified class. +Instances are not initialized. Example: + +
    +10 C_4BYTE --> ARRAY 40-RAW-BYTES  2DROP DROP
    +
    + + + + +Creates an initialized array of nObjects instances of the class. +Same syntax as ARRAY. + + + + +Creates an anonymous instance of CLASS from the heap (using a call +to ficlMalloc() to get the memory). Leaves the payload and class addresses +on the stack. Usage example: + +
    +C-REF --> ALLOC  2CONSTANT INSTANCE-OF-REF
    +
    +

    + +Creates a double-cell constant that pushes the payload and class address +of a heap instance of C-REF. + + + + +Same as NEW-ARRAY, but creates anonymous instances from the heap using +a call to ficlMalloc(). Each instance is initialized using the class's +INIT method. + + + + +Creates an anonymous instance of CLASS from the dictionary. Leaves +the payload and class addresses on the stack. Usage example: + +

    +C-REF --> ALLOT  2CONSTANT INSTANCE-OF-REF
    +
    + +

    + +Creates a double-cell constant that pushes the payload and class address +of a heap instance of C-REF. + + + + +Same as NEW-ARRAY, but creates anonymous instances from the dictionary. +Each instance is initialized using the class's INIT method. + + + +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. + + + + +Derive a subclass. You can add or override methods, and add instance variables. +Alias: SUBCLASS. Examples: +

    + +

    +C_4BYTE --> SUB C_SPECIAL4BYTE
    +  ( ... your new methods and instance variables here ... )
    +END-CLASS
    +
    + +or + +
    +C_4BYTE SUBCLASS C_SPECIAL4BYTE
    +  ( ... your new methods and instance variables here ... )
    +END-CLASS
    +
    + + + +Returns address of the class's instance size field, in address units. This +is a metaclass member variable. + + + +Returns address of the class's superclass field. This is a metaclass member +variable. + + + +Returns the address of the class's wordlist ID field. This is a metaclass +member variable. + + + +Returns the size of an instance of the class in address units. Imeplemented +as follows: + +
    +: GET-SIZE   METACLASS => .SIZE @ ;
    +
    + + + +Returns the wordlist ID of the class. Implemented as: + +
    +: GET-WID   METACLASS => .WID @ ;
    +
    + + + +Returns the class's superclass. Implemented as + +
    +: GET-SUPER   METACLASS => .super @ ;
    +
    + + + + +Returns the address and length of a string that names the class. + + + + +Lists methods of the class and all its superclasses. + + + + +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: + +
    +metaclass --> offset-of .wid
    +
    + + + + + +Lists the pedigree of the class (inheritance trail). + + + +Decompiles the specified method—obect version of SEE, from the +TOOLS wordset. + +
    + +OBJECT Base-Class Methods Glossary") ?> + + +These are methods that are defined for all instances by the base class +OBJECT. +The methods include default initialization, array manipulations, aliases +of class methods, upcasting, and programming tools. + +
    + + + +Default initializer, called automatically for all instances created with +NEW +or NEW-ARRAY. Zero-fills the instance. You do not normally need +to invoke INIT explicitly. + + + +Applies INIT to an array of objects created by NEW-ARRAY. +Note that ARRAY: does not cause aggregate arrays to be initialized +automatically. You do not normally need to invoke ARRAY-INIT explicitly. + + + +Releases memory used by an instance previously created with ALLOC +or ALLOC-ARRAY. Note: This method is not presently protected +against accidentally deleting something from the dictionary. If you do +this, Bad Things are likely to happen. Be careful for the moment to apply +free only to instances created with ALLOC or ALLOC-ARRAY. + + + +Convert an object signature into that of its class. Useful for calling +class methods that have no object aliases. + + + +Upcast an object to its parent class. The parent class of OBJECT +is zero. Useful for invoking an overridden parent class method. + + + +Display an object's pedigree—its chain of inheritance. This is an alias +for the corresponding class method. + + + +Returns the size, in address units, of one instance. Does not know about +arrays! This is an alias for the class method GET-SIZE. + + + +Class method alias. Displays the list of methods of the class and all superclasses +of the instance. + + + +Convert array-of-objects base signature into signature for array element +n. No check for bounds overflow. Index is zero-based, like C, so + +
    +0 MY-OBJ --> INDEX
    +
    + +is equivalent to + +
    +MY-OBJ
    +
    + +Check out the description of -ROT for +help in dealing with indices on the stack. + + + +Convert an array-object signature into the signature of the next +object in the array. No check for bounds overflow. + + + +Convert an object signature into the signature of the previous object +in the array. No check for bounds underflow. + +
    + + + + + +For more information on theses classes, see softcore/classes.fr. + +
    + + + +Describes all classes of Ficl. Contains class methods. Should never be +directly instantiated or subclassed. Defined in softcore/oo.fr. Methods described +above. + + + +Mother of all Ficl objects. Defines default initialization and array indexing +methods. Defined in softcore/oo.fr. Methods described above. + + + +Holds the signature of another object. Aggregate one of these into a data +structure or container class to get polymorphic behavior. Methods and members: + +
    + + +Push the referenced object value on the stack. + + +Set the referenced object being held. + + +Cell member that holds the instance. + + +Cell member that holds the class. + +
    + + + +Primitive class derived from OBJECT, with a 1-byte payload. SET +and GET methods perform correct width fetch and store. Methods and members: + +
    + + +Push the object's value on the stack. + + +Set the object's value from the stack. + + +Member holds instance's value. + +
    + + + +Primitive class derived from OBJECT, with a 2-byte payload. SET +and GET methods perform correct width fetch and store. Methods and members: + +
    + + +Push the object's value on the stack. + + +Set the object's value from the stack. + + +Member holds instance's value. + +
    + + +Primitive class derived from object, with a 4-byte payload. SET +and GET methods perform correct width fetch and store. Methods and members: + +
    + + +Push the object's value on the stack. + + +Set the object's value from the stack. + + +Member holds instance's value. + +
    + + + +Primitive class derived from OBJECT, with a cell payload (equivalent +to C-4BYTE on 32 bit platforms, 64 bits wide on Alpha and other +64-bit platforms). SET +and GET methods perform correct width fetch and store. Methods and members: + +
    + + +Push the object's value on the stack. + + +Set the object's value from the stack. + + +Member holds instance's value. + +
    + + + +Base class derived from OBJECT for pointers to non-object types. +This class is not complete by itself: several methods depend on a derived +class definition of @SIZE. Methods and members: + +
    + + +Member variable, holds the pointer address. + + +Pushes the pointer address. + + +Sets the pointer address. + + +Adds @SIZE to the pointer address. + + +Subtracts @SIZE to the pointer address. + + +Adds i * @SIZE to the pointer address. + +
    + + + +Pointer to byte derived from C-PTR. Methods and members: + +
    + + +Push size of the pointed-to object. + + +Pushes the pointer's referent byte. + + +Stores byte at the pointer address. + +
    + + + + + +Pointer to 2byte derived from C-PTR. Methods and members: + +
    + + +Push size of the pointed-to object. + + +Pushes the pointer's referent 2byte. + + +Stores 2byte at the pointer address. + +
    + + + + + +Pointer to 4byte derived from C-PTR. Methods and members: + +
    + + +Push size of the pointed-to object. + + +Pushes the pointer's referent 4byte. + + +Stores 4byte at the pointer address. + +
    + + + + +Pointer to cell derived from C-PTR. Methods and members: + +
    + + +Push size of the pointed-to object. + + +Pushes the pointer's referent cell. + + +Stores cell at the pointer address. + +
    + + + + + +Dynamically allocated string, similar to MFC's CString. +For more information, see softcore/string.fr. +Partial list of methods and members: + +
    + + +Pushes the string buffer's contents as a C-ADDR U style string. + + +Sets the string buffer's contents to a new value. + + +Concatenates a string to the string buffer's contents. + + +Lexical compiration of a string to the string buffer's contents. +Return value is the same as the FORTH function COMPARE. + + +Prints the contents of the string buffer to the output stream. + + +Returns a computed hash based on the contents of the string buffer. + + +Releases the internal buffer. + +
    + + + + +Subclass of C-STRING, which adds a member variable to store a hashcode. +For more information, see softcore/string.fr. + +
    + + Index: vendor/ficl/dist/doc/source/parsesteps.ht =================================================================== --- vendor/ficl/dist/doc/source/parsesteps.ht (nonexistent) +++ vendor/ficl/dist/doc/source/parsesteps.ht (revision 282803) @@ -0,0 +1,234 @@ +\n" + definition + "\n
    \n" + +?> + + + + +Unlike every other FORTH we know of, Ficl features an extensible +parser chain. The Ficl parser is not a monolithic function; instead, +it is comprised of a simple tokenizer and a series of parse steps. +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". +

    + +The Ficl parser works like this: +

      + +
    1. +Read in a new token (string of text with no internal whitespace). + +
    2. +For each parse step in the chain, call the parse step, passing in the token. +If the parse step returns FICL_TRUE, that parse step must have +handled the token appropriately; move on to the next token. + +
    3. +If the parser tries all the parse steps and none of them return +FICL_TRUE, the token is illegal—print an error +and reset the virtual machine. + +
    + +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. + + + + +These is the default Ficl parser chain, shown in order. + +
    + + + +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 FICL_TRUE. +

    + +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 FICL_TRUE. + + +This parse step is only active if prefix support is enabled, setting FICL_WANT_PREFIX +in ficl.h 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 FICL_TRUE. + + +Attempt to convert the token to a number in the present BASE. If successful, push the +value onto the stack if interpreting, otherwise compile it, then return FICL_TRUE. + + +This parse step is only active if floating-point number support is enabled, +setting FICL_WANT_FLOAT in ficl.h 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 FICL_TRUE. + +

    + + + + + + +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: +
    +MY-PARSE-STEP   ( c-addr u -- x*i flag )
    +
    +where c-addr u are the address and length of the incoming token, +and flag is FICL_TRUE if the parse step processed +the token and FICL_FALSE otherwise. +

    + +Install the parse step using add-parse-step. +A trivial example: +

    +: ?silly   ( c-addr u -- flag )
    +   ." Oh no! Not another  " type cr  true ;
    +' ?silly add-parse-step
    +parse-order
    +
    + + + +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: + +
    +void ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name, ficlParseStep step);
    +
    + +name is the display name of the parse step in the parse chain +(as displayed by the Ficl word PARSE-ORDER). step +is a pointer to the code for the parse step itself, +and must match the following declaration: +
    +typedef int (*ficlParseStep)(ficlVm *vm, ficlString s);
    +
    +

    + +When a native parse step is run, si points to the incoming token. +The parse step must return FICL_TRUE if it succeeds in handling the +token, and FICL_FALSE otherwise. +See ficlVmParseNumber() in system.c for an example. + + + + +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 0x, which causes digits following +it to be converted to hex regardless of the current value of BASE. +

    + +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. +

    + +Each prefix is a Ficl word stored in a special wordlist called <PREFIXES>. When the +prefix parse step (?prefix, implemented in C as ficlVmParsePrefix()) is +executed, it searches each word in <PREFIXES> 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). +

    + +Prefixes are defined in prefix.c and in softcore/prefix.fr. +The best way to add prefixes is by defining them in your own code, bracketed with the special +words START-PREFIXES and END-PREFIXES. For example, the following +code would make .( a prefix. + +

    +start-prefixes
    +: .(  .( ;
    +end-prefixes
    +
    +

    + +The compile-time constant FICL_EXTENDED_PREFIX 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. + + + + +

      + +
    • +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. +

      + +

    • +The number of parse steps that can be added to the system is limited by the value of +FICL_MAX_PARSE_STEPS (defined in sysdep.h). The default +maximum number is 8. +

      + +

    • +The compile-time constant FICL_EXTENDED_PREFIX 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. +

      + + +

    + + + +
    + + + +Prints the list of parse steps, in the order in which they are called. + + + +Appends a parse step to the parse chain. xt is the address +(execution token) of a Ficl word to use as the parse step. The word must be a +legal Ficl parse step (see above). + + + +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. + + + +Declares the beginning of a series of prefix definitions. +Should be followed, eventually, by END-PREFIXES. +(All START-PREFIXES does is tell the Ficl virtual machine +to compile into the <PREFIXES> wordlist.) + + + +Declares the end of a series of prefix definitions. +Should only be used after calling START-PREFIXES. +(All END-PREFIXES does is tell the Ficl virtual machine +to switch back to the wordlist that was in use before START-PREFIXES was called.) + +
    + + + \ No newline at end of file Index: vendor/ficl/dist/doc/source/releases.ht =================================================================== --- vendor/ficl/dist/doc/source/releases.ht (nonexistent) +++ vendor/ficl/dist/doc/source/releases.ht (revision 282803) @@ -0,0 +1,1003 @@ + + + +
      + +
    • +First official release of new engine as Ficl 4! Hooray! + +
    • +ficlDictionarySee() now takes a ficlCallback, +so it knows where to print to. This is because ficlWin only +sets a per-VM callback, which should work. + +
    • +ficlSystemCreate() now passes in the system correctly +into the dictionaries it creates, which lets dictionaries know what +system they're a part of. + +
    • +ficlCompatibility: Forgot to add the errorTextOut to the +ficl_system structure (though I'd remembered to add it to +the ficl_vm structure). This caused the ficl_system +members after textOut to not line up with their equivalent +ficlSystem members, which did bad things. (The bad thing +in particular was calling ficlDictionaryResetSearchOrder() +resulted in diddling the vm->link member, which strangely +enough resulted in double-freeing the stacks.) + +
    • +Added ficlStackWalk(), 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. + +
    • +Changed MULTICALL so you can explicitly specify the vtable. + +
    • +Changed XClasses so it explicitly specifies the vtable for +non-virtual classes. This means you can now call a virtual +method when you've SUPERed an object and you'll +get the method you wanted. + +
    • +XClasses improvement: when removing a thunked method, remove +the thunk variable too. Added xClass.removeMember() +to support this. + +
    • +XClasses now generates runtime stack-check code (_DEBUG +only) for functions thunked from C to Ficl. + +
    • +FICL_WANT_PLATFORM is now 0 by default. +It is now set to 1 in the appropriate ficlplatform/*.h. + +
    • +softcore/win32.fr ENVIRONMENT? COMPARE needed to be case-insensitive. + +
    • +Whoops! Setting FICL_PLATFORM_2INTEGER to 0 +didn't compile. It now does, and works fine, as proved by +the ansi platform. + +
    • +Another whoops: contrib/xclasses/xclasses.py assumed that " (a prefix +version of S") defined. Switched to S", which is safer. + +
    + + + +
      + +
    • +Cleaned up some FICL_ definitions. Now all FICL_HAVE_* constants +(and some other odds and ends) have been moved to FICL_PLATFORM_. + +
    • +Whoops! Setting FICL_PLATFORM_2INTEGER to 0 didn't +compile. It now does, and works fine, as proved by +the "ansi" platform. + +
    • +Another whoops: contrib/xclasses/xclasses.py assumed that " (a prefix +version of S") defined. Switched to S", which is safer. + +
    • +Added ficlDictionarySetConstantString(). 'Cause I needed it for: + +
    • +Removed the "WIN32" ENVIRONMENT? setting, and added "FICL_PLATFORM_OS" +and "FICL_PLATFORM_ARCHITECTURE" in its place. These are both strings. +Updated softcore/win32.fr to match. + +
    • +Compatibility: improved ficlTextOut() behavior. It makes life slightly +less convenient for some users, but should be an improvement overall. +The change: ficlTextOut() is now a compatibility-layer function that +calls straight through to vmTextOut(). Lots of old code calls ficlTextOut() +(naughty!). It's now explicit that you must set the textOut function +by hand if you use a custom one... which is a good habit to get in to anyway. + +
    • +Improved the documentation regarding upgrading, ficllocals.h, and compile-time +constants. + +
    • +Fixed doc/source/generate.py so it gracefully fails to copy over read-only +files. + +
    • +Got rid of every #ifdef in the sources. We now consistently use #if defined() +everywhere. Similarly, got rid of all platform-switched #if code (except for the +compatibility layer, sigh). + +
    + + + +
      + +
    • +Documentation totally reworked and updated. + +
    • +oldnames renamed to compatibility. +And improved, so that now Ficl 4 is basically a drop-in +replacement for Ficl 3. + +
    + + + +
      + +
    • +Did backwards-compatibility testing. Ficl now drops in, more or less, +with all the old Ficl-3.03-using projects I had handy. + +
    • +Got Ficl compiling and running fine on Linux. + +
    • +Weaned LZ77 code from needing htonl()/ntohl(). + +
    • +Moved all the primitives defined in "testmain.c" to their own file, +"extras.c", and gave it its own global entry point. + +
    • +Renamed "testmain.c" to just plain "main.c". + +
    • +Renamed "softwords" directory to "softcore". More symmetrical. + +
    • +Renamed "softcore\softcore.bat" to "make.bat". Added support for "CLEAN". + +
    + + +
      + +
    • +Added runtime jump-to-jump peephole optimization in the new +switch-threaded VM. + +
    • +Fixed INCLUDE-FILE so it rethrows an exception in the +subordinate evaluation. + +
    • +Added a separate errorOut function to +ficlCallback(), +so under Windows you can have a jolly popup window to +rub your nose in your failings. + +
    + + +
      + +
    • +Namespace policing complete. There are now no external symbols +which do not start with the word ficl. + +
    • +Removed ficlVmExec(), renamed ficlVmExecC() to +ficlVmExecuteString(), changed it to take a ficlString(). +This is deliberate subterfuge on my part; I suspect most +people who currently call ficlVmExec() / ficlVmExecC() +should be calling ficlVmEvaluate(). +
    + + +
      + +
    • +First pass at support for "oldnames", and namespace policing. + +
    + + +First alpha release of Ficl 4.0 rewrite. Coded, for better +or for worse, by Larry Hastings. +Ficl is smaller, faster, more powerful, +and easier to use than ever before. (Or your money back!) +
      +
    • +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. + +
    • +Renamed most (probably all) external Ficl functions and data structures. +They now make sense and are (gasp!) consistent. + +
    • +Retooled double-cell number support to take advantage of platforms +which natively support double-cell-sized integers. (Like most modern +32-bit platforms.) + +
    • +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. + +
    • +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. + +
    • +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). + +
    • +There's very likely other wonderful things that I've long forgotten +about. If you notice them, feel free to remind me :) + +
    + + +
      +
    • +Bugfix for floating-point numbers. Floats in compiled code were simply broken. + +
    • +New words: random and seed-random + +
    • +Bugfix: included never closed its file. + +
    • +Bugfix: include was not IMMEDIATE. + +
    • +Un-hid the OO words parse-method, lookup-method, and find-method-xt, as there are perfectly legitimate reasons why you might want to use them. + +
    • +Changed the prefix version of .( to be IMMEDIATE too. + +
    • +Fixed comment in Python softcore builder. + +
    • +Put the doc directory back in to the distribution. (It was missing from 3.02... where'd it go?) + +
    + + + + +
      +
    • +Added support for nEnvCells (number of environment cells) to FICL_SYSTEM_INFO. + +
    • +Consolidated context and pExtend pointers of FICL_SYSTEM—VM's pExtend pointer is initialized from the copy in FICL_SYSTEM upon VM creation. + +
    • +Added ficl-robust environment variable. + +
    • +Added FW_ISOBJECT word type. + +
    • +Bugfix: environment? was ignoring the length of the supplied string. + +
    • +Portability cleanup in fileaccess.c. + +
    • +Bugfix in ficlParsePrefix: if the prefix dictionary isn't in the wordlist, the word being examined cannot be a prefix, so return failure. + +
    • +SEE improvements: SEE (and consequently DEBUG) have improved source listings with instruction offsets. + +
    • +It's turned off with the preprocessor, but we have the beginnings of a switch-threaded implementation of the inner loop. + +
    • +Added objectify and ?object for use by OO infrastructure. + +
    • +my=[ detects object members (using ?object) and assumes all other members leave class unchanged. + +
    • +Removed MEMORY-EXT environment variable (there is no such wordset). + +
    • +Ficlwin changes: +
        +
      • +Ficlwin character handling is more robust + +
      • +Ficlwin uses multi-system constructs (see ficlthread.c) + +
      + +
    • +Documentation changes: +
        +
      • +Corrected various bugs in docs. + +
      • +Added ficl-ized version of JV Noble's Forth Primer + +
      • +Ficl OO tutorial expanded and revised. Thanks to David McNab for his demo and suggestions. + +
      + + +
    + + +
      +
    • +Major contributionss by Larry Hastings (larry@hastings.org): +
        +
      • +FILE wordset (fileaccess.c) + +
      • +ficlEvaluate wrapper for ficlExec + +
      • +ficlInitSystemEx makes it possible to bind selectable properties to VMs at create time + +
      • +Python version of softcore builder ficl/softwords/softcore.py + +
      + +
    • +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. + +
    + + + +
      +
    • +Fixed broken oo.fr by commenting out vcall stuff using FICL_WANT_VCALL. Vcall is still broken. + +
    + + + +
      +
    • +Added pSys parameter to most ficlXXXX functions for multiple system support. Affected functions: +
        +
      • dictLookupLoc renamed to ficlLookupLoc after addition of pSys param +
      • ficlInitSystem returns a FICL_SYSTEM* +
      • ficlTermSystem +
      • ficlNewVM +
      • ficlLookup +
      • ficlGetDict +
      • ficlGetEnv +
      • ficlSetEnv +
      • ficlSetEnvD +
      • ficlGetLoc +
      • ficlBuild +
      + + +
    • Fixed off-by-one bug in ficlParsePrefix +
    • Ficl parse-steps now work correctly - mods to interpret() +
    • Made tools.c:isAFiclWord more selective +
    • Tweaked makefiles and code to make gcc happy under linux +
    • Vetted all instances of LVALUEtoCELL to make sure they're working on CELL sized operands +(for 64 bit compatibility) +
    + + +
      +
    • Debugger changes: +
        +
      • New debugger command "x" to execute the rest of the command line as ficl +
      • New debugger command "l" lists the source of the innermost word being debugged +
      • If you attempt to debug a primitive, it gets executed rather than doing nothing +
      • R.S displays the stack contents symbolically +
      • Debugger now operates correctly under ficlwin, although ficlwin's key handling leaves a lot to be desired. +
      • SEE listing enhanced for use with the debugger +
      +
    • Added Guy Carver's changes to oo.fr for VTABLE support +
    • float.c words f> and >f to move floats to and from the param stack, analogous to >r and r> +
    • LOOKUP - Surrogate precompiled parse step for ficlParseWord (this step is hard + coded in INTERPRET) +
    • License text at top of source files changed from LGPL to BSD by request +
    • Win32 console version now handles exceptions more gracefully rather than crashing - uses win32 +structured exception handling. +
    • Fixed BASE bug from 2.05 (was returning the value rather than the address) +
    • Fixed ALLOT bug - feeds address units to dictCheck, which expects Cells. Changed dictCheck +to expect AU. +
    • Float stack display word renamed to f.s from .f to be consistent with r.s and .s +
    + + +

    General

    + +
      +
    • HTML documentation extensively revised +
    • Incorporated Alpha (64 bit) patches from the freeBSD team. +
    • Split SEARCH and SEARCH EXT words from words.c to search.c +
    • 2LOCALS defined in Johns Hopkins local syntax now lose the first '2:' in their names. +
    • Simple step debugger (see tools.c) +
    • The text interpreter is now extensible - this is accomplished through the use +of ficlAddParseStep(). FICL_MAX_PARSE_STEPS limits the number of parse steps +(default: 8). You can write a precompiled parse step (see ficlParseNumber) and +append it to the chain, or you can write one in ficl and use ADD-PARSE-STEP +to append it. Default parse steps are initialized in ficlInitSystem. You can list +the parse steps with parse-order ( -- ). +
    • 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. +
    • Fixes for improved command line operation in testmain.c (Larry Hastings) +
    • Numerous extensions to OO facility, including a new allot methods, ability +to catch method invocations (thanks to Daniel Sobral again) +
    • Incorporated Alpha (64 bit) patches contributed by Daniel Sobral and the freeBSD team +Ficl is now 64 bit friendly! UNS32 is now FICL_UNS. +
    • Split SEARCH and SEARCH EXT words from words.c to search.c +
    • ABORT" now complies with the ANS (-2 THROWs) +
    • Floating point support contributed by Guy Carver (Enable FICL_WANT_FLOAT in sysdep.h). +
    • Win32 vtable model for objects (Guy Carver) +
    • Win32 dll load/call suport (Larry Hastings) +
    • 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. +
    • 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 +
    + +

    +Bug fixes

    + +
      +
    • +ABORT" +now works correctly (I promise!) + +
    • +REFILL works +better + +
    • +ALLOT's +use of dictCheck corrected (finally) +
    + +

    +New words

    + +
      +
    • +2r@ 2r> 2>r +(CORE EXT) + +
    • +2VARIABLE +(DOUBLE) + +
    • +ORDER +now lists wordlists by name + +
    • +.S now +displays all stack entries on one line, like a stack comment + +
    • +wid-get-name   +given a wid, returns the address and count of its name. If no name, count +is 0 + +
    • +wid-set-name  +set optional wid name pointer to the \0 terminated string address specified. + +
    • +ficl-named-wordlist creates +a ficl-wordlist and names it. This is now used in vocabulary and +ficl-vocabulary  + +
    • +last-word  returns the +xt of the word being defined or most recently defined. + +
    • +q@ and q! +operate on quadbyte quantities for 64 bit friendliness +
    + +

    +New OO stuff

    + +
      +
    • +ALLOT (class method) + +
    • +ALLOT-ARRAY (class method) + +
    • +METHOD define method names globally + +
    • +MY=> early bind a method call to "this" class + +
    • +MY=[ ] early bind a string of method calls to "this" class and +obj members + +
    • +C-> late bind method invocation with CATCH + +
    • +Metaclass method resume-class and instance word suspend-class +create mutually referring classes. Example in string.fr + +
    • +Early binding words are now in the instance-vars wordlist, not visible +unless defining a class. + +
    • Support for refs to classes with VTABLE methods (contributed by Guy Carver). Guy writes: +

      +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. +

      +Here is an example of how to use VCALL: +

      +C++ class declaration +
      +class myclass
      +{
      +public:
      +  myclass();
      +  virtual ~myclass();
      +  virtual void Test( int iParam1 );
      +  virtual int Test( int iParam1, char cParam2 );
      +  virtual float Test();
      +};
      +
      +ficl class declaration +
      +object subclass myfclass hasvtable   \ hasvtable adds 4 to the offset to
      +                                   \  accommodate for the VTABLE pointer.
      +0 VCALL: Destructor()      \ VCALL: ( ParamCount -- )
      +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.
      +
      + +
    + + + +

    ficlwin

    + +
      +
    • +Catches exceptions thrown by VM in ficlThread (0 @ for example) rather +than passing them off to the OS.  +
    + +

    +ficl bugs vanquished

    + +
      +
    • +Fixed leading delimiter bugs in s" ." .( and ( (reported by Reuben Thomas) + +
    • +Makefile tabs restored (thanks to Michael Somos) + +
    • +ABORT" now throws -2 per the DPANS (thanks to Daniel Sobral for sharp eyes +again)  + +
    • +ficlExec does not print the prompt string unless (source-id == 0) + +
    • +Various fixes contributed by the FreeBSD team. +
    + +

    +ficl enhancements

    + +
      +
    • +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)  + +
    • +Added function vmGetStringEx with a flag to specify whether or not to skip +lead delimiters + +
    • +Added non-std word: number? + +
    • +Added CORE EXT word AGAIN (by request of Reuben Thomas)  + +
    • +Added double cell local (2local) support + +
    • +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) + +
    • +C-string class revised and enhanced - now dynamically sized + +
    • +C-hashstring class derived from c-string computes hashcode too. +
    + + + + +This is the first version of Ficl that includes contributed code. Thanks +especially to Daniel Sobral, Michael Gauland for contributions and bug +finding. +

    +New words: +

      +
    • +clock              +(FICL) + +
    • +clocks/sec         +(FICL) + +
    • +dnegate            +(DOUBLE) + +
    • +ms                 +(FACILITY EXT - replaces MSEC ficlWin only) + +
    • +throw              +(EXCEPTION) + +
    • +catch              +(EXCEPTION) + +
    • +allocate           +(MEMORY) + +
    • +free               +(MEMORY) + +
    • +resize             +(MEMORY) + +
    • +within             +(CORE EXT) + +
    • +alloc              +(class method) + +
    • +alloc-array        +(class method) + +
    • +free               +(class method) +
    + +Bugs Fixed: +
      +
    • +Bug fix in isNumber(): used to treat chars between 'Z' and 'a' as valid +in base 10... (harmless, but weird) + +
    • +ficlExec pushes the ip and interprets at the right times +so that nested calls to ficlExec behave the way you'd expect them to. + +
    • +evaluate respects count parameter, and also passes exceptional +return conditions back out to the calling instance of ficlExec. + +
    • +VM_QUIT now clears the locals dictionary in ficlExec. +
    +Ficlwin Enhancements  +
      +
    • +File Menu: recent file list and Open now load files. + +
    • +Text ouput function is now faster through use of string caching. Cache +flushes at the end of each line and each time ficlExec returns. + +
    • +Edit/paste now behaves more reasonably for text. File/open loads the specified +file. + +
    • +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 +
    +Ficl Enhancements  +
      +
    • +This version includes changes to make it 64 bit friendly. 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. + +
    • +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. + +
    • +ficl.c: Added ficlExecC() to operate on counted strings as opposed to zero +terminated ones. + +
    • +ficlExec pushes ip and executes interpret at the right times so that nested +calls to ficlExec behave the way you'd expect them to. + +
    • +ficlSetStackSize() allows specification of stack size at run-time (affects +subsequent invocations of ficlNewVM()). + +
    • +vm.c: vmThrow() checks for (pVM->pState != NULL) before longjmping it. +vmCreate nulls this pointer initially.  + +
    • +EXCEPTION wordset contributed by Daniel Sobral of FreeBSD + +
    • +MEMORY-ALLOC wordset contributed by Daniel Sobral, too. Added class methods +alloc +and alloc-array in softwords/oo.fr to allocate objects from the +heap. + +
    • +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. + +
    • +Added vmInnerLoop() to vm.h. This function/macro factors the inner  +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  + +
      comments in vm.c +
    • +EVALUATE respects the count parameter, and also passes exceptional return +conditions back out to the calling instance of ficlExec. + +
    • +VM_QUIT clears locals dictionary in ficlExec() + +
    • +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). + +
    • +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. + +
    • +testmain.c: Changed gets() in testmain to fgets() to appease the security +gods. + +
    • +testmain: msec renamed to ms in +line with the ANS + +
    • +softcore.pl now removes comments & spaces at the start and end of lines. +As a result: sizeof (softWords) == 7663 bytes (used to be 20000)  +and consumes 11384 bytes of dictionary when compiled + +
    • +Deleted license paste-o in readme.txt (oops). +
    + + + + +New words: + +Bugs Fixed  +
      +
    • +forget 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) + +
    • +:noname used to push the colon control marker and its execution +token in the wrong order + +
    • +source-id now behaves correctly when loading a file. + +
    • +refill returns zero at EOF (Win32 load). Win32 load +command continues to be misnamed. Really ought to be called included, +but does not exactly conform to that spec either (because included +expects a string signature on the stack, while Ficl's load +expects a filename upon invocation). The "real" LOAD is a BLOCK +word. +
    +Enhancements (IMHO)  +
      +
    • +dictUnsmudge no longer links anonymous definitions into the dictionary + +
    • +oop is no longer the default compile wordlist at startup, nor +is it in the search order. Execute also oop definitions +to use Ficl OOP. + +
    • +Revised oo.fr extensively to make more use of early binding + +
    • +Added meta - a constant that pushes the address of metaclass. +See oo.fr for examples of use. + +
    • +Added classes: c-ptr  c-bytePtr  c-2bytePtr  c-cellPtr +These +classes model pointers to non-object data, but each knows the size of its +referent. +
    + + + + +
      +
    • +Bug fix: (local) used to leave a value on the stack between the +first and last locals declared. This value is now stored in a static. + +
    • +Added new local syntax with parameter re-ordering. See +description below. (No longer compiled in version 2.02, in favor of +the Johns Hopkins syntax) +
    + + + + +
      +
    • +New ANS Forth words: TOOLS and part of TOOLS EXT, SEARCH +and SEARCH EXT, LOCALS and LOCALS EXT word sets, additional +words from CORE EXT, DOUBLE, and STRING. (See the function +ficlCompileCore in words.c for an alphabetical list by word set). + +
    • +Simple USER variable support - a user variable is a virtual machine +instance variable. User variables behave as VARIABLEs in all other +respects. + +
    • +Object oriented syntax extensions (see below) + +
    • +Optional stack underflow and overflow checking in many CORE words (enabled +when FICL_ROBUST >= 2) + +
    • +Various bug fixes +
    + + + + Index: vendor/ficl/dist/doc/source/upgrading.ht =================================================================== --- vendor/ficl/dist/doc/source/upgrading.ht (nonexistent) +++ vendor/ficl/dist/doc/source/upgrading.ht (revision 282803) @@ -0,0 +1,349 @@ +\n" + print "old name\n" + print "new name\n" + if extra != None: + print "" + extra + "\n" + print "\n" + +def oldvsnew(old, new, extra = None): + print "\n" + print "" + old + "\n" + print "" + new + "\n" + if extra != None: + print "" + extra + "\n" + print"\n\n" + + +def endoldvsnew(): + print "

    \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 What's New In Ficl 4.0? +section of the overview. +

    + + +Since the Ficl API has changed so dramatically, you can't just drop +the new Ficl source. You have two basic choices: +use the FICL_WANT_COMPATIBILITY support, and +switching to the new API. +

    + +Note that using either of these choices requires +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 source compatible +but not binary compatible with Ficl 3. + + + +FICL_WANT_COMPATIBILITY") ?> + + + +If you want to get Ficl 4.0 up and running in your project as quickly +as possible, FICL_WANT_COMPATIBILITY is what you'll want to use. +There are two easy steps, one of which you might be able to skip: +

    + +

      + +
    1. +Set the C preprocessor constant FICL_WANT_COMPATIBILITY to 1. +The best way is by adding the following line to ficllocal.h: +
      +	#define FICL_WANT_COMPATIBILITY (1)
      +
      + + +
    2. + +If you use a custom ficlTextOut() 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 ficlTextOut() directly (instead of calling +vmTextOut() as it should have). +We recommend renaming your function to ficlTextOutLocal(), as +we have have provided a prototype for this function for you in ficlcompatibility.h. +This will save you the trouble of defining your own prototype, ensuring you get +correct name decoration / linkage, etc. + +

      + +There are two methods you can use to specify your ficlTextOut() +function: +

        + +
      1. +Specify it in the FICL_INIT_INFO structure passed in to +ficlInitSystem(). 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. + +
      2. +Set it explicitly in every VM by calling vmSetTextOut() and +passing it in. + +
      +

      + +Note: Any other method, such as setting it by hand in the +FICL_SYSTEM or FICL_VM structures, +will not work. There is a special compatibility layer for old-style +OUTFUNC functions, but it is only invoked properly when you +use one of the two methods mentioned above. + + +

    + +

    + +This should 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. + + + + + + +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 should be. (After all, part of the point of this massive +renaming was to make all the external symbols consistent.) +

    + + + + + + +Every external type has been renamed. They all begin with the +word ficl, 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: +FICL_STRING is now ficlCountedString, as it +represents a "counted string" in the language, and +the more commonly-used STRINGINFO is now simply +ficlString. + + + + + +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!). + + + + +Text output callbacks have changed in two major ways: + +

      + +
    • +They no longer take a VM pointer; they now take a ficlCallback 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 ficlSystem...() function). + +
    • +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 \n character in the text. + +
    + +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 ficlOldnamesCallbackTextOut +as the name of the output function for the system and VM, and then set +the thunkedTextout member of the ficlSystem +or ficlVm to your old-style text output function. + + + + +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() + +?> + +ficllocal.h
    ") ?> + +One more note about macros. Ficl now ships with a standard place for +you to tweak the Ficl compile-time preprocessor switches such as +FICL_WANT_COMPATIBILITY and FICL_WANT_FLOAT. +It's a file called ficllocal.h, 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 ficl.h +or editing the makefile. That should make it much easier to integrate +future Ficl releases into your product—all you need do is preserve +your tweaked copy of ficllocal.h and replace the rest. + + + + +Every function that deals primarily with a particular structure +is now named after that structure. For instance, any function +that takes a ficlSystem as its first argument is +named ficlSystemSomething(). Any function +that takes a ficlVm as its first argument is +named ficlVmSomething(). And so on. +

    + +Also, functions that create a new object are always +called Create (not Alloc, Allot, Init, or New). +Functions that create a new object are always +called Destroy (not Free, Term, or Delete). +

    + + + +

    + +All functions exported by Ficl now start with the word ficl. +This is a feature, as it means the Ficl project will no longer +pollute your namespace. + +dataStack, p)") +oldvsnew("POPUNS()", "ficlStackPopUnsigned(vm->dataStack)") +oldvsnew("GETTOP()", "ficlStackGetTop(vm->dataStack)") +oldvsnew("ltoa()", "ficlLtoa()") +oldvsnew("strincmp()", "ficlStrincomp()") + +endoldvsnew() + +?> + + + + + +A few entry points have simply been removed. +For instance, functions specifically managing a system's ENVIRONMENT +settings have been removed, in favor of managing the system's +environment dictionary directly: + + + +In a similar vein, ficlSystemBuild() has been removed in favor +of using ficlDictionarySetPrimitive() directly: + + + +Finally, there is no exact replacement for ficlExec(). 99% of the code +that called ficlExec() never bothered to manage SOURCE-ID properly. +If you were calling ficlExec(), and you weren't changing SOURCE-ID +(or vm->sourceId) to match, you should replace those calls with ficlVmEvaluate(), +which will manage SOURCE-ID for you. +

    + +There is a function that takes the place of ficlExec() which doesn't change +SOURCE-ID: ficlVmExecuteString(). However, instead of taking a +straight C string (a char *), it takes a ficlString * as its +code argument. (This is to discourage its use.) + + + + +Note: 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. +

    + +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) +stack->top[-1]. It is now at stack->top[0]. +In other words, the "stack top" pointer used to point past the top +element; it now points at the top element. (Pointing at the +top element is not only less confusing, it is also faster.) + + + Index: vendor/ficl/dist/doc/upgrading.html =================================================================== --- vendor/ficl/dist/doc/upgrading.html (nonexistent) +++ vendor/ficl/dist/doc/upgrading.html (revision 282803) @@ -0,0 +1,808 @@ + + + + + + +upgrading ficl + + + + + + + + + + + + + + + +
    + + + +upgrading ficl + +
    +

    +Index

    +


    +ANS
    +API
    +Debugger
    +Download
    +Licensing
    +Links
    +Locals
    +OOP In Ficl
    +Parse Steps
    +Release History
    +Upgrading To 4.0
    +

    + + + +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 What's New In Ficl 4.0? +section of the overview. +

    + + +Since the Ficl API has changed so dramatically, you can't just drop +the new Ficl source. You have two basic choices: +use the FICL_WANT_COMPATIBILITY support, and +switching to the new API. +

    + +Note that using either of these choices requires +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 source compatible +but not binary compatible with Ficl 3. + + + + +

    +

    + + +
    + + +Using FICL_WANT_COMPATIBILITY +

    + + + + + +If you want to get Ficl 4.0 up and running in your project as quickly +as possible, FICL_WANT_COMPATIBILITY is what you'll want to use. +There are two easy steps, one of which you might be able to skip: +

    + +

      + +
    1. +Set the C preprocessor constant FICL_WANT_COMPATIBILITY to 1. +The best way is by adding the following line to ficllocal.h: +
      +	#define FICL_WANT_COMPATIBILITY (1)
      +
      + + +
    2. + +If you use a custom ficlTextOut() 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 ficlTextOut() directly (instead of calling +vmTextOut() as it should have). +We recommend renaming your function to ficlTextOutLocal(), as +we have have provided a prototype for this function for you in ficlcompatibility.h. +This will save you the trouble of defining your own prototype, ensuring you get +correct name decoration / linkage, etc. + +

      + +There are two methods you can use to specify your ficlTextOut() +function: +

        + +
      1. +Specify it in the FICL_INIT_INFO structure passed in to +ficlInitSystem(). 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. + +
      2. +Set it explicitly in every VM by calling vmSetTextOut() and +passing it in. + +
      +

      + +Note: Any other method, such as setting it by hand in the +FICL_SYSTEM or FICL_VM structures, +will not work. There is a special compatibility layer for old-style +OUTFUNC functions, but it is only invoked properly when you +use one of the two methods mentioned above. + + +

    + +

    + +This should 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. + + + + +

    +

    + + +
    + + +Using The New API +

    + + + + +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 should be. (After all, part of the point of this massive +renaming was to make all the external symbols consistent.) +

    + + + + + +

    +

    + + +
    + + +Types +

    + + + +Every external type has been renamed. They all begin with the +word ficl, 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: +FICL_STRING is now ficlCountedString, as it +represents a "counted string" in the language, and +the more commonly-used STRINGINFO is now simply +ficlString. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    old namenew name
    FICL_SYSTEMficlSystem
    FICL_VMficlVm
    FICL_SYSTEM_INFOficlSystemInformation
    FICL_WORDficlWord
    IPTYPEficlIp
    FICL_CODEficlPrimitive
    OUTFUNCficlOutputFunction
    FICL_DICTIONARYficlDictionary
    FICL_STACKficlStack
    STRINGINFOficlString
    FICL_STRINGficlCountedString

    + + + + +

    +

    + + +
    + + +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!). + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    old namenew nameaccessor
    pExtendcontextficlVmGetContext(), ficlSystemGetContext()
    pStackdataStackficlVmGetDataStack()
    fStackfloatStackficlVmGetFloatStack()
    rStackreturnStackficlVmGetReturnStack()

    + + + + +

    +

    + + +
    + + +Callback Functions +

    + + + +Text output callbacks have changed in two major ways: + +
      + +
    • +They no longer take a VM pointer; they now take a ficlCallback 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 ficlSystem...() function). + +
    • +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 \n character in the text. + +
    + +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 ficlOldnamesCallbackTextOut +as the name of the output function for the system and VM, and then set +the thunkedTextout member of the ficlSystem +or ficlVm to your old-style text output function. + + + +

    +

    + + +
    + + +Renamed Macros +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    old namenew name
    PUSHPTR(p)ficlStackPushPointer(vm->dataStack, p)
    POPUNS()ficlStackPopUnsigned(vm->dataStack)
    GETTOP()ficlStackGetTop(vm->dataStack)
    FW_IMMEDIATEFICL_WORD_IMMEDIATE
    FW_COMPILEFICL_WORD_COMPILE_ONLY
    VM_INNEREXITFICL_VM_STATUS_INNER_EXIT
    VM_OUTOFTEXTFICL_VM_STATUS_OUT_OF_TEXT
    VM_RESTARTFICL_VM_RESTART

    + + + + +

    +

    + + +
    + + +ficllocal.h +

    + + + +One more note about macros. Ficl now ships with a standard place for +you to tweak the Ficl compile-time preprocessor switches such as +FICL_WANT_COMPATIBILITY and FICL_WANT_FLOAT. +It's a file called ficllocal.h, 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 ficl.h +or editing the makefile. That should make it much easier to integrate +future Ficl releases into your product—all you need do is preserve +your tweaked copy of ficllocal.h and replace the rest. + + + +

    +

    + + +
    + + +Renamed Functions +

    + + + +Every function that deals primarily with a particular structure +is now named after that structure. For instance, any function +that takes a ficlSystem as its first argument is +named ficlSystemSomething(). Any function +that takes a ficlVm as its first argument is +named ficlVmSomething(). And so on. +

    + +Also, functions that create a new object are always +called Create (not Alloc, Allot, Init, or New). +Functions that create a new object are always +called Destroy (not Free, Term, or Delete). +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    old namenew name
    ficlInitSystem()ficlSystemCreate()
    ficlTermSystem()ficlSystemDestroy()
    ficlNewVM()ficlSystemCreateVm()
    ficlFreeVM()ficlVmDestroy()
    dictCreate()ficlDictionaryCreate()
    dictDelete()ficlDictionaryDestroy()

    + + +

    + +All functions exported by Ficl now start with the word ficl. +This is a feature, as it means the Ficl project will no longer +pollute your namespace. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    old namenew name
    PUSHPTR(p)ficlStackPushPointer(vm->dataStack, p)
    POPUNS()ficlStackPopUnsigned(vm->dataStack)
    GETTOP()ficlStackGetTop(vm->dataStack)
    ltoa()ficlLtoa()
    strincmp()ficlStrincomp()

    + + + + + + +

    +

    + + +
    + + +Removed Functions +

    + + + +A few entry points have simply been removed. +For instance, functions specifically managing a system's ENVIRONMENT +settings have been removed, in favor of managing the system's +environment dictionary directly: + + + + + + + + + + + + + + + + + + + + + + + + + + +
    old namenew name
    ficlSystemSetEnvironment(system)ficlDictionarySetConstant(ficlSystemGetEnvironment(system), ...)
    ficlSystemSet2Environment(system)ficlDictionarySet2Constant(ficlSystemGetEnvironment(system), ...)

    + + + + +In a similar vein, ficlSystemBuild() has been removed in favor +of using ficlDictionarySetPrimitive() directly: + + + + + + + + + + + + + + + + + + +
    old namenew name
    ficlSystemBuild(system, ...)ficlDictionarySetPrimitive(ficlSystemGetDictionary(system), ...)

    + + + +Finally, there is no exact replacement for ficlExec(). 99% of the code +that called ficlExec() never bothered to manage SOURCE-ID properly. +If you were calling ficlExec(), and you weren't changing SOURCE-ID +(or vm->sourceId) to match, you should replace those calls with ficlVmEvaluate(), +which will manage SOURCE-ID for you. +

    + +There is a function that takes the place of ficlExec() which doesn't change +SOURCE-ID: ficlVmExecuteString(). However, instead of taking a +straight C string (a char *), it takes a ficlString * as its +code argument. (This is to discourage its use.) + + + +

    +

    + + +
    + + +Internal Changes +

    + + + +Note: 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. +

    + +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) +stack->top[-1]. It is now at stack->top[0]. +In other words, the "stack top" pointer used to point past the top +element; it now points at the top element. (Pointing at the +top element is not only less confusing, it is also faster.) + + + Property changes on: vendor/ficl/dist/doc/upgrading.html ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/html \ No newline at end of property Index: vendor/ficl/dist/double.c =================================================================== --- vendor/ficl/dist/double.c (nonexistent) +++ vendor/ficl/dist/double.c (revision 282803) @@ -0,0 +1,479 @@ +/******************************************************************* +** 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.2 2010/09/12 15:18:07 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 + +#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 ((uintmax_t)1 << (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; +} + + Property changes on: vendor/ficl/dist/double.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/extras.c =================================================================== --- vendor/ficl/dist/extras.c (nonexistent) +++ vendor/ficl/dist/extras.c (revision 282803) @@ -0,0 +1,267 @@ +#include +#include +#include +#include +#include + +#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; +} + Property changes on: vendor/ficl/dist/extras.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficl.dsw =================================================================== --- vendor/ficl/dist/ficl.dsw (revision 282802) +++ vendor/ficl/dist/ficl.dsw (revision 282803) @@ -1,29 +1,59 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "ficl"=.\ficl.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ficldll"=.\ficldll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ficllib + End Project Dependency +}}} + +############################################################################### + +Project: "ficlexe"=.\ficlexe.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ficllib + End Project Dependency +}}} + +############################################################################### + +Project: "ficllib"=.\ficllib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + Index: vendor/ficl/dist/ficl.h =================================================================== --- vendor/ficl/dist/ficl.h (revision 282802) +++ vendor/ficl/dist/ficl.h (revision 282803) @@ -1,1117 +1,1862 @@ /******************************************************************* ** f i c l . h ** Forth Inspired Command Language ** Author: John Sadler (john_sadler@alum.mit.edu) ** Created: 19 July 1997 ** Dedicated to RHS, in loving memory -** $Id: ficl.h,v 1.19 2001-12-04 17:58:07-08 jsadler Exp jsadler $ -*******************************************************************/ -/* +** $Id: ficl.h,v 1.25 2010/10/03 09:52:12 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 +** 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 +** 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. */ #if !defined (__FICL_H__) #define __FICL_H__ /* ** Ficl (Forth-inspired command language) is an ANS Forth ** interpreter written in C. Unlike traditional Forths, this ** interpreter is designed to be embedded into other systems ** as a command/macro/development prototype language. ** ** Where Forths usually view themselves as the center of the system ** and expect the rest of the system to be coded in Forth, Ficl ** acts as a component of the system. It is easy to export ** code written in C or ASM to Ficl in the style of TCL, or to invoke ** Ficl code from a compiled module. This allows you to do incremental ** development in a way that combines the best features of threaded ** languages (rapid development, quick code/test/debug cycle, ** reasonably fast) with the best features of C (everyone knows it, ** easier to support large blocks of code, efficient, type checking). ** ** 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. This -** is more like TCL than Forth, which usually expcets to be at the center +** is more like TCL than Forth, which usually expects to be at the center ** of the system, requesting input at its convenience. Each Ficl virtual ** machine can be bound to a different I/O channel, and is independent ** of all others in in the same address space except that all virtual ** machines share a common dictionary (a sort or open symbol table that ** defines all of the elements of the language). ** ** Code is written in ANSI C for portability. ** ** Summary of Ficl features and constraints: ** - Standard: Implements the ANSI Forth CORE word set and part ** of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and ** TOOLS EXT, LOCAL and LOCAL ext and various extras. ** - 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! ** - Ficl and C can interact in two ways: Ficl can encapsulate ** C code, or C code can invoke Ficl code. ** - Thread-safe, re-entrant: The shared system dictionary ** uses a locking mechanism that you can either supply ** or stub out to provide exclusive access. Each Ficl ** virtual machine has an otherwise complete state, and ** each can be bound to a separate I/O channel (or none at all). ** - Simple encapsulation into existing systems: a basic implementation ** requires three function calls (see the example program in testmain.c). ** - 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. ** - Written an ANSI C to be as simple as I can make it to understand, ** support, debug, and port. Compiles without complaint at /Az /W4 ** (require ANSI C, max warnings) under Microsoft VC++ 5. ** - Does full 32 bit math (but you need to implement ** two mixed precision math primitives (see sysdep.c)) ** - Indirect threaded interpreter is not the fastest kind of ** Forth there is (see pForth 68K for a really fast subroutine ** threaded interpreter), but it's the cleanest match to a ** pure C implementation. ** ** P O R T I N G F i c l ** ** 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 sysdep.h and sysdep.c and edit them to suit your ** system. For example, INT16 is a short on some compilers and an ** int on others. Check the default CELL alignment controlled by ** FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree, -** ficlLockDictionary, and ficlTextOut to work with your operating system. -** Finally, use testmain.c as a guide to installing the Ficl system and -** one or more virtual machines into your code. You do not need to include -** testmain.c in your build. +** ficlLockDictionary, and ficlCallbackDefaultTextOut to work with your +** operating system. Finally, use testmain.c as a guide to installing the +** Ficl system and one or more virtual machines into your code. You do not +** need to include testmain.c in your build. ** ** T o D o L i s t ** ** 1. Unimplemented system dependent CORE word: key ** 2. Ficl uses the PAD in some CORE words - this violates the standard, ** but it's cleaner for a multithreaded system. I'll have to make a ** second pad for reference by the word PAD to fix this. ** ** F o r M o r e I n f o r m a t i o n ** -** Web home of ficl +** Web home of Ficl ** http://ficl.sourceforge.net ** Check this website for Forth literature (including the ANSI standard) ** http://www.taygeta.com/forthlit.html ** and here for software and more links ** http://www.taygeta.com/forth.html +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include +#include + +/* +** Put all your local defines in ficllocal.h, +** rather than editing the makefile/project/etc. +** ficllocal.h will always ship as an inert file. +*/ +#include "ficllocal.h" + + + + +#if defined(FICL_ANSI) + #include "ficlplatform/ansi.h" +#elif defined(_WIN32) + #include "ficlplatform/win32.h" +#elif defined (FREEBSD_ALPHA) + #include "ficlplatform/alpha.h" +#elif defined(unix) || defined(__unix__) || defined(__unix) + #include "ficlplatform/unix.h" +#else /* catch-all */ + #include "ficlplatform/ansi.h" +#endif /* platform */ + + + +/* ** -** Obvious Performance enhancement opportunities -** Compile speed -** - work on interpret speed -** - turn off locals (FICL_WANT_LOCALS) -** Interpret speed -** - Change inner interpreter (and everything else) -** so that a definition is a list of pointers to functions -** and inline data rather than pointers to words. This gets -** rid of vm->runningWord and a level of indirection in the -** inner loop. I'll look at it for ficl 3.0 -** - Make the main hash table a bigger prime (HASHSIZE) -** - FORGET about twiddling the hash function - my experience is -** that that is a waste of time. -** - Eliminate the need to pass the pVM parameter on the stack -** by dedicating a register to it. Most words need access to the -** vm, but the parameter passing overhead can be reduced. One way -** requires that the host OS have a task switch callout. Create -** a global variable for the running VM and refer to it in words -** that need VM access. Alternative: use thread local storage. -** For single threaded implementations, you can just use a global. -** The first two solutions create portability problems, so I -** haven't considered doing them. Another possibility is to -** declare the pVm parameter to be "register", and hope the compiler -** pays attention. +** B U I L D C O N T R O L S ** +** First, the FICL_WANT_* settings. +** These are all optional settings that you may or may not +** want Ficl to use. +** */ /* -** Revision History: -** -** 15 Apr 1999 (sadler) Merged FreeBSD changes for exception wordset and -** counted strings in ficlExec. -** 12 Jan 1999 (sobral) Corrected EVALUATE behavior. Now TIB has an -** "end" field, and all words respect this. ficlExec is passed a "size" -** of TIB, as well as vmPushTib. This size is used to calculate the "end" -** of the string, ie, base+size. If the size is not known, pass -1. +** FICL_WANT_MINIMAL +** If set to nonzero, build the smallest possible Ficl interpreter. +*/ +#if !defined(FICL_WANT_MINIMAL) +#define FICL_WANT_MINIMAL (0) +#endif + +#if FICL_WANT_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) +#define FICL_WANT_DEBUGGER (0) +#define FICL_WANT_OOP (0) +#define FICL_WANT_PLATFORM (0) +#define FICL_WANT_MULTITHREADED (0) +#define FICL_WANT_EXTENDED_PREFIX (0) + +#define FICL_ROBUST (0) + +#endif /* FICL_WANT_MINIMAL */ + + +/* +** FICL_WANT_PLATFORM +** Includes words defined in ficlCompilePlatform +** (see ficlplatform/win32.c and ficlplatform/unix.c for example) +*/ +#if !defined (FICL_WANT_PLATFORM) +#define FICL_WANT_PLATFORM (0) +#endif /* FICL_WANT_PLATFORM */ + + +/* +** FICL_WANT_COMPATIBILITY +** Changes Ficl 4 at compile-time so it is source-compatible +** with the Ficl 3 API. If you are a new user to Ficl you +** don't need to worry about this setting; if you are upgrading +** from a pre-4.0 version of Ficl, see doc/upgrading.html for +** more information. +*/ +#if !defined FICL_WANT_COMPATIBILITY +#define FICL_WANT_COMPATIBILITY (0) +#endif /* !defined FICL_WANT_COMPATIBILITY */ + + + +/* +** FICL_WANT_LZ_SOFTCORE +** If nonzero, the softcore words are stored compressed +** with patent-unencumbered Lempel-Ziv '77 compression. +** This results in a smaller Ficl interpreter, and adds +** only a *tiny* runtime speed hit. ** -** 10 Jan 1999 (sobral) EXCEPTION word set has been added, and existing -** words has been modified to conform to EXCEPTION EXT word set. +** As of version 4.0.27, all the runtime code for the decompressor +** is 688 bytes on a single-threaded release build, but saves 14179 +** bytes of data. That's a net savings of over 13k! Plus, it makes +** the resulting executable harder to hack :) ** -** 27 Aug 1998 (sadler) testing and corrections for LOCALS, LOCALS EXT, -** SEARCH / SEARCH EXT, TOOLS / TOOLS EXT. -** Added .X to display in hex, PARSE and PARSE-WORD to supplement WORD, -** EMPTY to clear stack. +** On my 850MHz Duron machine, decompression took 0.00384 seconds +** if QueryPerformanceCounter() can be believed... it claims that it +** took 13765 cycles to complete, and that my machine runs 3579545 +** cycles/second. ** -** 29 jun 1998 (sadler) added variable sized hash table support -** and ANS Forth optional SEARCH & SEARCH EXT word set. -** 26 May 1998 (sadler) -** FICL_PROMPT macro -** 14 April 1998 (sadler) V1.04 -** Ficlwin: Windows version, Skip Carter's Linux port -** 5 March 1998 (sadler) V1.03 -** Bug fixes -- passes John Ryan's ANS test suite "core.fr" +** Contributed by Larry Hastings. +*/ +#if !defined (FICL_WANT_LZ_SOFTCORE) +#define FICL_WANT_LZ_SOFTCORE (1) +#endif /* FICL_WANT_LZ_SOFTCORE */ + + +/* +** 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_FILE */ + +/* +** FICL_WANT_FLOAT +** Includes a floating point stack for the VM, and words to do float operations. +** Contributed by Guy Carver +*/ +#if !defined (FICL_WANT_FLOAT) +#define FICL_WANT_FLOAT (1) +#endif /* FICL_WANT_FLOAT */ + +/* +** FICL_WANT_DEBUGGER +** Inludes a simple source level debugger +*/ +#if !defined (FICL_WANT_DEBUGGER) +#define FICL_WANT_DEBUGGER (1) +#endif /* FICL_WANT_DEBUGGER */ + +/* +** 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_WANT_EXTENDED_PREFIX +#define FICL_WANT_EXTENDED_PREFIX (0) +#endif /* FICL_WANT_EXTENDED_PREFIX */ + +/* +** FICL_WANT_USER +** Enables user variables: per-instance variables bound to the VM. +** Kind of like thread-local storage. Could be implemented in a +** VM private dictionary, but I've chosen the lower overhead +** approach of an array of CELLs instead. +*/ +#if !defined FICL_WANT_USER +#define FICL_WANT_USER (1) +#endif /* FICL_WANT_USER */ + +/* +** FICL_WANT_LOCALS +** Controls the creation of the LOCALS wordset +** and a private dictionary for local variable compilation. +*/ +#if !defined FICL_WANT_LOCALS +#define FICL_WANT_LOCALS (1) +#endif /* FICL_WANT_LOCALS */ + +/* +** FICL_WANT_OOP +** Inludes object oriented programming support (in softwords) +** OOP support requires locals and user variables! +*/ +#if !defined (FICL_WANT_OOP) +#define FICL_WANT_OOP ((FICL_WANT_LOCALS) && (FICL_WANT_USER)) +#endif /* FICL_WANT_OOP */ + +/* +** FICL_WANT_SOFTWORDS +** Controls inclusion of all softwords in softcore.c. +*/ +#if !defined (FICL_WANT_SOFTWORDS) +#define FICL_WANT_SOFTWORDS (1) +#endif /* FICL_WANT_SOFTWORDS */ + +/* +** FICL_WANT_MULTITHREADED +** Enables dictionary mutual exclusion wia the +** ficlLockDictionary() system dependent function. ** -** 24 February 1998 (sadler) V1.02 -** -Fixed bugs in <# # #> -** -Changed FICL_WORD so that storage for the name characters -** can be allocated from the dictionary as needed rather than -** reserving 32 bytes in each word whether needed or not - -** this saved 50% of the dictionary storage requirement. -** -Added words in testmain for Win32 functions system,chdir,cwd, -** also added a word that loads and evaluates a file. +** Note: this implementation is experimental and poorly +** tested. Further, it's unnecessary unless you really +** intend to have multiple SESSIONS (poor choice of name +** on my part) - that is, threads that modify the dictionary +** at the same time. +*/ +#if !defined FICL_WANT_MULTITHREADED +#define FICL_WANT_MULTITHREADED (0) +#endif /* FICL_WANT_MULTITHREADED */ + + +/* +** FICL_WANT_OPTIMIZE +** Do you want to optimize for size, or for speed? +** Note that this doesn't affect Ficl very much one way +** or the other at the moment. +** Contributed by Larry Hastings +*/ +#define FICL_OPTIMIZE_FOR_SPEED (1) +#define FICL_OPTIMIZE_FOR_SIZE (2) +#if !defined (FICL_WANT_OPTIMIZE) +#define FICL_WANT_OPTIMIZE FICL_OPTIMIZE_FOR_SPEED +#endif /* FICL_WANT_OPTIMIZE */ + + +/* +** FICL_WANT_VCALL +** Ficl OO support for calling vtable methods. Win32 only. +** Contributed by Guy Carver +*/ +#if !defined (FICL_WANT_VCALL) +#define FICL_WANT_VCALL (0) +#endif /* FICL_WANT_VCALL */ + + + +/* +** P L A T F O R M S E T T I N G S ** -** December 1997 (sadler) -** -Added VM_RESTART exception handling in ficlExec -- this lets words -** that require additional text to succeed (like :, create, variable...) -** recover gracefully from an empty input buffer rather than emitting -** an error message. Definitions can span multiple input blocks with -** no restrictions. -** -Changed #include order so that is included in sysdep.h, -** and sysdep is included in all other files. This lets you define -** NDEBUG in sysdep.h to disable assertions if you want to. -** -Make PC specific system dependent code conditional on _M_IX86 -** defined so that ports can coexist in sysdep.h/sysdep.c +** The FICL_PLATFORM_* settings. +** These indicate attributes about the local platform. */ -#ifdef __cplusplus -extern "C" { + +/* +** FICL_PLATFORM_OS +** String constant describing the current hardware architecture. +*/ +#if !defined (FICL_PLATFORM_ARCHITECTURE) +#define FICL_PLATFORM_ARCHITECTURE "unknown" #endif -#include "sysdep.h" -#include /* UCHAR_MAX */ -#include +/* +** FICL_PLATFORM_OS +** String constant describing the current operating system. +*/ +#if !defined (FICL_PLATFORM_OS) +#define FICL_PLATFORM_OS "unknown" +#endif /* +** FICL_PLATFORM_HAS_2INTEGER +** Indicates whether or not the current architecture +** supports a native double-width integer type. +** If you set this to 1 in your ficlplatform/ *.h file, +** you *must* create typedefs for the following two types: +** ficl2Unsigned +** ficl2Integer +** If this is set to 0, Ficl will implement double-width +** integer math in C, which is both bigger *and* slower +** (the double whammy!). Make sure your compiler really +** genuinely doesn't support native double-width integers +** before setting this to 0. +*/ +#if !defined (FICL_PLATFORM_HAS_2INTEGER) +#define FICL_PLATFORM_HAS_2INTEGER (0) +#endif + +/* +** FICL_PLATFORM_HAS_FTRUNCATE +** Indicates whether or not the current platform provides +** the ftruncate() function (available on most UNIXes). +** This function is necessary to provide the complete +** File-Access wordset. +** +** If your platform does not have ftruncate() per se, +** but does have some method of truncating files, you +** should be able to implement ftruncate() yourself and +** set this constant to 1. For an example of this see +** "ficlplatform/win32.c". +*/ +#if !defined (FICL_PLATFORM_HAS_FTRUNCATE) +#define FICL_PLATFORM_HAS_FTRUNCATE (0) +#endif + + +/* +** FICL_PLATFORM_INLINE +** Must be defined, should be a function prototype type-modifying +** keyword that makes a function "inline". Ficl does not assume +** that the local platform supports inline functions; it therefore +** only uses "inline" where "static" would also work, and uses "static" +** in the absence of another keyword. +*/ +#if !defined FICL_PLATFORM_INLINE +#define FICL_PLATFORM_INLINE static +#endif /* !defined FICL_PLATFORM_INLINE */ + +/* +** FICL_PLATFORM_EXTERN +** Must be defined, should be a keyword used to declare +** a function prototype as being a genuine prototype. +** You should only have to fiddle with this setting if +** you're not using an ANSI-compliant compiler, in which +** case, good luck! +*/ +#if !defined FICL_PLATFORM_EXTERN +#define FICL_PLATFORM_EXTERN extern +#endif /* !defined FICL_PLATFORM_EXTERN */ + + + +/* +** FICL_PLATFORM_BASIC_TYPES +** +** If not defined yet, +*/ +#if !defined(FICL_PLATFORM_BASIC_TYPES) +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; + +#endif /* !defined(FICL_PLATFORM_BASIC_TYPES) */ + + + + + + + +/* +** FICL_ROBUST enables bounds checking of stacks and the dictionary. +** This will detect stack over and underflows and dictionary overflows. +** Any exceptional condition will result in an assertion failure. +** (As generated by the ANSI assert macro) +** FICL_ROBUST == 1 --> stack checking in the outer interpreter +** FICL_ROBUST == 2 also enables checking in many primitives +*/ + +#if !defined FICL_ROBUST +#define FICL_ROBUST (2) +#endif /* FICL_ROBUST */ + + + +/* +** FICL_DEFAULT_STACK_SIZE Specifies the default size (in CELLs) of +** a new virtual machine's stacks, unless overridden at +** create time. +*/ +#if !defined FICL_DEFAULT_STACK_SIZE +#define FICL_DEFAULT_STACK_SIZE (128) +#endif + +/* +** FICL_DEFAULT_DICTIONARY_SIZE specifies the number of ficlCells to allocate +** for the system dictionary by default. The value +** can be overridden at startup time as well. +*/ +#if !defined FICL_DEFAULT_DICTIONARY_SIZE +#define FICL_DEFAULT_DICTIONARY_SIZE (12288) +#endif + +/* +** FICL_DEFAULT_ENVIRONMENT_SIZE specifies the number of cells +** to allot for the environment-query dictionary. +*/ +#if !defined FICL_DEFAULT_ENVIRONMENT_SIZE +#define FICL_DEFAULT_ENVIRONMENT_SIZE (512) +#endif + +/* +** FICL_MAX_WORDLISTS specifies the maximum number of wordlists in +** the dictionary search order. See Forth DPANS sec 16.3.3 +** (file://dpans16.htm#16.3.3) +*/ +#if !defined FICL_MAX_WORDLISTS +#define FICL_MAX_WORDLISTS (16) +#endif + +/* +** FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM structure +** that stores pointers to parser extension functions. I would never expect to have +** more than 8 of these, so that's the default limit. Too many of these functions +** will probably exact a nasty performance penalty. +*/ +#if !defined FICL_MAX_PARSE_STEPS +#define FICL_MAX_PARSE_STEPS (8) +#endif + +/* +** Maximum number of local variables per definition. +** This only affects the size of the locals dictionary, +** and there's only one per entire ficlSystem, so it +** doesn't make sense to be a piker here. +*/ +#if (!defined(FICL_MAX_LOCALS)) && FICL_WANT_LOCALS +#define FICL_MAX_LOCALS (64) +#endif + +/* +** The pad is a small scratch area for text manipulation. ANS Forth +** requires it to hold at least 84 characters. +*/ +#if !defined FICL_PAD_SIZE +#define FICL_PAD_SIZE (256) +#endif + +/* +** ANS Forth requires that a word's name contain {1..31} characters. +*/ +#if !defined FICL_NAME_LENGTH +#define FICL_NAME_LENGTH (31) +#endif + +/* +** Default size of hash table. For most uniform +** performance, use a prime number! +*/ +#if !defined FICL_HASH_SIZE + #define FICL_HASH_SIZE (241) +#endif + + +/* +** Default number of USER flags. +*/ +#if (!defined(FICL_USER_CELLS)) && FICL_WANT_USER +#define FICL_USER_CELLS (16) +#endif + + + + + + +/* ** Forward declarations... read on. */ -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; +struct ficlWord; +typedef struct ficlWord ficlWord; +struct ficlVm; +typedef struct ficlVm ficlVm; +struct ficlDictionary; +typedef struct ficlDictionary ficlDictionary; +struct ficlSystem; +typedef struct ficlSystem ficlSystem; +struct ficlSystemInformation; +typedef struct ficlSystemInformation ficlSystemInformation; +struct ficlCallback; +typedef struct ficlCallback ficlCallback; +struct ficlCountedString; +typedef struct ficlCountedString ficlCountedString; +struct ficlString; +typedef struct ficlString ficlString; + +/* +** System dependent routines: +** Edit the implementations in your appropriate ficlplatform/ *.c to be +** compatible with your runtime environment. +** +** ficlCallbackDefaultTextOut sends a zero-terminated string to the +** default output device - used for system error messages. +** +** ficlMalloc(), ficlRealloc() and ficlFree() have the same semantics +** as the functions malloc(), realloc(), and free() from the standard C library. +*/ +FICL_PLATFORM_EXTERN void ficlCallbackDefaultTextOut(ficlCallback *callback, char *text); +FICL_PLATFORM_EXTERN void *ficlMalloc (size_t size); +FICL_PLATFORM_EXTERN void ficlFree (void *p); +FICL_PLATFORM_EXTERN void *ficlRealloc(void *p, size_t size); + + + + + + /* ** the Good Stuff starts here... */ -#define FICL_VER "3.03" +#define FICL_VERSION "4.1.0" + #if !defined (FICL_PROMPT) -#define FICL_PROMPT "ok> " +#define FICL_PROMPT "ok> " #endif /* ** ANS Forth requires false to be zero, and true to be the ones ** complement of false... that unifies logical and bitwise operations ** nicely. */ #define FICL_TRUE ((unsigned long)~(0L)) #define FICL_FALSE (0) #define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE) +#if !defined FICL_IGNORE /* Macro to silence unused param warnings */ +#define FICL_IGNORE(x) (void)x +#endif /* !defined FICL_IGNORE */ + + + + +#if !defined NULL +#define NULL ((void *)0) +#endif + + /* -** A CELL is the main storage type. It must be large enough +** Jiggery-pokery for the FICL_WANT_COMPATIBILITY compatibility layer. +** Even if you're not using it, compatibility.c won't compile properly +** unless FICL_WANT_COMPATIBILITY is turned on. Hence, we force it to +** always be turned on. +*/ +#ifdef FICL_FORCE_COMPATIBILITY +#undef FICL_WANT_COMPATIBILITY +#define FICL_WANT_COMPATIBILITY (1) +#endif /* FICL_FORCE_COMPATIBILITY */ + + + + + +/* +** 2integer structures +*/ +#if FICL_PLATFORM_HAS_2INTEGER + +#define FICL_2INTEGER_SET(high, low, doublei) ((doublei) = (ficl2Integer)(((ficlUnsigned)(low)) | (((ficl2Integer)(high)) << FICL_BITS_PER_CELL))) +#define FICL_2INTEGER_TO_2UNSIGNED(doublei) ((ficl2Unsigned)(doublei)) + +#define FICL_2UNSIGNED_SET(high, low, doubleu) ((doubleu) = ((ficl2Unsigned)(low)) | (((ficl2Unsigned)(high)) << FICL_BITS_PER_CELL)) +#define FICL_2UNSIGNED_GET_LOW(doubleu) ((ficlUnsigned)(doubleu & ((((ficl2Integer)1) << FICL_BITS_PER_CELL) - 1))) +#define FICL_2UNSIGNED_GET_HIGH(doubleu) ((ficlUnsigned)(doubleu >> FICL_BITS_PER_CELL)) +#define FICL_2UNSIGNED_NOT_ZERO(doubleu) ((doubleu) != 0) +#define FICL_2UNSIGNED_TO_2INTEGER(doubleu) ((ficl2Integer)(doubleu)) + +#define FICL_INTEGER_TO_2INTEGER(i, doublei) ((doublei) = (i)) +#define FICL_UNSIGNED_TO_2UNSIGNED(u, doubleu) ((doubleu) = (u)) + +#define ficl2IntegerIsNegative(doublei) ((doublei) < 0) +#define ficl2IntegerNegate(doublei) (-(doublei)) + +#define ficl2IntegerMultiply(x, y) (((ficl2Integer)(x)) * ((ficl2Integer)(y))) +#define ficl2IntegerDecrement(x) (((ficl2Integer)(x)) - 1) + +#define ficl2UnsignedAdd(x, y) (((ficl2Unsigned)(x)) + ((ficl2Unsigned)(y))) +#define ficl2UnsignedSubtract(x, y) (((ficl2Unsigned)(x)) - ((ficl2Unsigned)(y))) +#define ficl2UnsignedMultiply(x, y) (((ficl2Unsigned)(x)) * ((ficl2Unsigned)(y))) +#define ficl2UnsignedMultiplyAccumulate(u, mul, add) (((u) * (mul)) + (add)) +#define ficl2UnsignedArithmeticShiftLeft(x) ((x) << 1) +#define ficl2UnsignedArithmeticShiftRight(x) ((x) >> 1) +#define ficl2UnsignedCompare(x, y) ficl2UnsignedSubtract(x, y) +#define ficl2UnsignedOr(x, y) ((x) | (y)) + +#else /* FICL_PLATFORM_HAS_2INTEGER */ + +typedef struct +{ + ficlUnsigned high; + ficlUnsigned low; +} ficl2Unsigned; + +typedef struct +{ + ficlInteger high; + ficlInteger low; +} ficl2Integer; + + +#define FICL_2INTEGER_SET(hi, lo, doublei) { ficl2Integer x; x.low = (lo); x.high = (hi); (doublei) = x; } +#define FICL_2INTEGER_TO_2UNSIGNED(doublei) (*(ficl2Unsigned *)(&(doublei))) + + +#define FICL_2UNSIGNED_SET(hi, lo, doubleu) { ficl2Unsigned x; x.low = (lo); x.high = (hi); (doubleu) = x; } +#define FICL_2UNSIGNED_GET_LOW(doubleu) ((doubleu).low) +#define FICL_2UNSIGNED_GET_HIGH(doubleu) ((doubleu).high) +#define FICL_2UNSIGNED_NOT_ZERO(doubleu) ((doubleu).high || (doubleu).low) +#define FICL_2UNSIGNED_TO_2INTEGER(doubleu) (*(ficl2Integer *)(&(doubleu))) + +#define FICL_INTEGER_TO_2INTEGER(i, doublei) { ficlInteger __x = (ficlInteger)(i); FICL_2INTEGER_SET((__x < 0) ? -1L : 0, __x, doublei) } +#define FICL_UNSIGNED_TO_2UNSIGNED(u, doubleu) FICL_2UNSIGNED_SET(0, u, doubleu) + + +FICL_PLATFORM_EXTERN int ficl2IntegerIsNegative(ficl2Integer x); +FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerNegate(ficl2Integer x); + +FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerMultiply(ficlInteger x, ficlInteger y); +FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerDecrement(ficl2Integer x); + +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedAdd(ficl2Unsigned x, ficl2Unsigned y); +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedSubtract(ficl2Unsigned x, ficl2Unsigned y); +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedMultiply(ficlUnsigned x, ficlUnsigned y); +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedMultiplyAccumulate(ficl2Unsigned u, ficlUnsigned mul, ficlUnsigned add); +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedArithmeticShiftLeft( ficl2Unsigned x ); +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedArithmeticShiftRight( ficl2Unsigned x ); +FICL_PLATFORM_EXTERN int ficl2UnsignedCompare(ficl2Unsigned x, ficl2Unsigned y); +FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedOr( ficl2Unsigned x, ficl2Unsigned y ); + +#endif /* FICL_PLATFORM_HAS_2INTEGER */ + +FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerAbsoluteValue(ficl2Integer x); + +/* +** These structures represent the result of division. +*/ +typedef struct +{ + ficl2Unsigned quotient; + ficlUnsigned remainder; +} ficl2UnsignedQR; + +typedef struct +{ + ficl2Integer quotient; + ficlInteger remainder; +} ficl2IntegerQR; + + +#define FICL_2INTEGERQR_TO_2UNSIGNEDQR(doubleiqr) (*(ficl2UnsignedQR *)(&(doubleiqr))) +#define FICL_2UNSIGNEDQR_TO_2INTEGERQR(doubleuqr) (*(ficl2IntegerQR *)(&(doubleuqr))) + +/* +** 64 bit integer math support routines: multiply two UNS32s +** to get a 64 bit product, & divide the product by an UNS32 +** to get an UNS32 quotient and remainder. Much easier in asm +** on a 32 bit CPU than in C, which usually doesn't support +** the double length result (but it should). +*/ +FICL_PLATFORM_EXTERN ficl2IntegerQR ficl2IntegerDivideFloored(ficl2Integer num, ficlInteger den); +FICL_PLATFORM_EXTERN ficl2IntegerQR ficl2IntegerDivideSymmetric(ficl2Integer num, ficlInteger den); + +FICL_PLATFORM_EXTERN ficl2UnsignedQR ficl2UnsignedDivide(ficl2Unsigned q, ficlUnsigned y); + + + + + + +/* +** A ficlCell is the main storage type. It must be large enough ** to contain a pointer or a scalar. In order to accommodate ** 32 bit and 64 bit processors, use abstract types for int, ** unsigned, and float. +** +** A ficlUnsigned, ficlInteger, and ficlFloat *MUST* be the same +** size as a "void *" on the target system. (Sorry, but that's +** a design constraint of FORTH.) */ -typedef union _cell +typedef union ficlCell { - FICL_INT i; - FICL_UNS u; + ficlInteger i; + ficlUnsigned u; #if (FICL_WANT_FLOAT) - FICL_FLOAT f; + ficlFloat f; #endif void *p; void (*fn)(void); -} CELL; +} ficlCell; + +#define FICL_BITS_PER_CELL (sizeof(ficlCell) * 8) + /* -** LVALUEtoCELL does a little pointer trickery to cast any CELL sized +** FICL_PLATFORM_ALIGNMENT is the number of bytes to which +** the dictionary pointer address must be aligned. This value +** is usually either 2 or 4, depending on the memory architecture +** of the target system; 4 is safe on any 16 or 32 bit +** machine. 8 would be appropriate for a 64 bit machine. +*/ +#if !defined FICL_PLATFORM_ALIGNMENT +#define FICL_PLATFORM_ALIGNMENT (4) +#endif + + +/* +** FICL_LVALUE_TO_CELL does a little pointer trickery to cast any CELL sized ** lvalue (informal definition: an expression whose result has an ** address) to CELL. Remember that constants and casts are NOT ** themselves lvalues! */ -#define LVALUEtoCELL(v) (*(CELL *)&v) +#define FICL_LVALUE_TO_CELL(v) (*(ficlCell *)&v) /* ** PTRtoCELL is a cast through void * intended to satisfy the ** most outrageously pedantic compiler... (I won't mention ** its name) */ -#define PTRtoCELL (CELL *)(void *) -#define PTRtoSTRING (FICL_STRING *)(void *) +#define FICL_POINTER_TO_CELL(p) ((ficlCell *)(void *)p) /* -** Strings in FICL are stored in Pascal style - with a count -** preceding the text. We'll also NULL-terminate them so that -** they work with the usual C lib string functions. (Belt & -** suspenders? You decide.) -** STRINGINFO hides the implementation with a couple of -** macros for use in internal routines. +** FORTH defines the "counted string" data type. This is +** a "Pascal-style" string, where the first byte is an unsigned +** count of characters, followed by the characters themselves. +** The Ficl structure for this is ficlCountedString. +** Ficl also often zero-terminates them so that they work with the +** usual C runtime library string functions... strlen(), strcmp(), +** and the like. (Belt & suspenders? You decide.) +** +** The problem is, this limits strings to 255 characters, which +** can be a bit constricting to us wordy types. So FORTH only +** uses counted strings for backwards compatibility, and all new +** words are "c-addr u" style, where the address and length are +** stored separately, and the length is a full unsigned "cell" size. +** (For more on this trend, see DPANS94 section A.3.1.3.4.) +** Ficl represents this with the ficlString structure. Note that +** these are frequently *not* zero-terminated! Don't depend on +** it--that way lies madness. */ -typedef unsigned char FICL_COUNT; -#define FICL_STRING_MAX UCHAR_MAX -typedef struct _ficl_string +struct ficlCountedString { - FICL_COUNT count; + ficlUnsigned8 length; char text[1]; -} FICL_STRING; +}; -typedef struct +#define FICL_COUNTED_STRING_GET_LENGTH(cs) ((cs).length) +#define FICL_COUNTED_STRING_GET_POINTER(cs) ((cs).text) + +#define FICL_COUNTED_STRING_MAX (256) +#define FICL_POINTER_TO_COUNTED_STRING(p) ((ficlCountedString *)(void *)p) + +struct ficlString { - FICL_UNS count; - char *cp; -} STRINGINFO; + ficlUnsigned length; + char *text; +}; -#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 FICL_STRING_GET_LENGTH(fs) ((fs).length) +#define FICL_STRING_GET_POINTER(fs) ((fs).text) +#define FICL_STRING_SET_LENGTH(fs, l) ((fs).length = (ficlUnsigned)(l)) +#define FICL_STRING_SET_POINTER(fs, p) ((fs).text = (char *)(p)) +#define FICL_STRING_SET_FROM_COUNTED_STRING(string, countedstring) \ + {(string).text = (countedstring).text; (string).length = (countedstring).length;} /* -** Init a STRINGINFO from a pointer to NULL-terminated string +** Init a FICL_STRING from a pointer to a zero-terminated string */ -#define SI_PSZ(si, psz) \ - {si.cp = psz; si.count = (FICL_COUNT)strlen(psz);} -/* -** Init a STRINGINFO from a pointer to FICL_STRING -*/ -#define SI_PFS(si, pfs) \ - {si.cp = pfs->text; si.count = pfs->count;} +#define FICL_STRING_SET_FROM_CSTRING(string, cstring) \ + {(string).text = (cstring); (string).length = strlen(cstring);} /* ** Ficl uses this little structure to hold the address of ** the block of text it's working on and an index to the next ** unconsumed character in the string. Traditionally, this is ** done by a Text Input Buffer, so I've called this struct TIB. ** ** Since this structure also holds the size of the input buffer, ** and since evaluate requires that, let's put the size here. ** The size is stored as an end-pointer because that is what the ** null-terminated string aware functions find most easy to deal ** with. ** Notice, though, that nobody really uses this except evaluate, -** so it might just be moved to FICL_VM instead. (sobral) +** so it might just be moved to ficlVm instead. (sobral) */ typedef struct { - FICL_INT index; + ficlInteger index; char *end; - char *cp; -} TIB; + char *text; +} ficlTIB; /* ** Stacks get heavy use in Ficl and Forth... ** Each virtual machine implements two of them: ** one holds parameters (data), and the other holds return ** addresses and control flow information for the virtual ** machine. (Note: C's automatic stack is implicitly used, ** but not modeled because it doesn't need to be...) ** Here's an abstract type for a stack */ -typedef struct _ficlStack +typedef struct ficlStack { - FICL_UNS nCells; /* size of the stack */ - CELL *pFrame; /* link reg for stack frame */ - CELL *sp; /* stack pointer */ - CELL base[1]; /* Top of stack */ -} FICL_STACK; + ficlUnsigned size; /* size of the stack, in cells */ + ficlCell *frame; /* link reg for stack frame */ + ficlCell *top; /* stack pointer */ + ficlVm *vm; /* used for debugging */ + char *name; /* used for debugging */ + ficlCell base[1]; /* Top of stack */ +} ficlStack; /* ** Stack methods... many map closely to required Forth words. */ -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); +FICL_PLATFORM_EXTERN ficlStack *ficlStackCreate (ficlVm *vm, char *name, unsigned nCells); +FICL_PLATFORM_EXTERN void ficlStackDestroy (ficlStack *stack); +FICL_PLATFORM_EXTERN int ficlStackDepth (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackDrop (ficlStack *stack, int n); +FICL_PLATFORM_EXTERN ficlCell ficlStackFetch (ficlStack *stack, int n); +FICL_PLATFORM_EXTERN ficlCell ficlStackGetTop (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackPick (ficlStack *stack, int n); +FICL_PLATFORM_EXTERN ficlCell ficlStackPop (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackPush (ficlStack *stack, ficlCell c); +FICL_PLATFORM_EXTERN void ficlStackReset (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackRoll (ficlStack *stack, int n); +FICL_PLATFORM_EXTERN void ficlStackSetTop (ficlStack *stack, ficlCell c); +FICL_PLATFORM_EXTERN void ficlStackStore (ficlStack *stack, int n, ficlCell c); +#if FICL_WANT_LOCALS +FICL_PLATFORM_EXTERN void ficlStackLink (ficlStack *stack, int nCells); +FICL_PLATFORM_EXTERN void ficlStackUnlink (ficlStack *stack); +#endif /* FICL_WANT_LOCALS */ + +FICL_PLATFORM_EXTERN void *ficlStackPopPointer (ficlStack *stack); +FICL_PLATFORM_EXTERN ficlUnsigned ficlStackPopUnsigned (ficlStack *stack); +FICL_PLATFORM_EXTERN ficlInteger ficlStackPopInteger (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackPushPointer (ficlStack *stack, void *ptr); +FICL_PLATFORM_EXTERN void ficlStackPushUnsigned (ficlStack *stack, ficlUnsigned u); +FICL_PLATFORM_EXTERN void ficlStackPushInteger (ficlStack *stack, ficlInteger i); + #if (FICL_WANT_FLOAT) -float stackPopFloat (FICL_STACK *pStack); -void stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f); +FICL_PLATFORM_EXTERN ficlFloat ficlStackPopFloat (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackPushFloat (ficlStack *stack, ficlFloat f); #endif +FICL_PLATFORM_EXTERN void ficlStackPush2Integer (ficlStack *stack, ficl2Integer i64); +FICL_PLATFORM_EXTERN ficl2Integer ficlStackPop2Integer (ficlStack *stack); +FICL_PLATFORM_EXTERN void ficlStackPush2Unsigned(ficlStack *stack, ficl2Unsigned u64); +FICL_PLATFORM_EXTERN ficl2Unsigned ficlStackPop2Unsigned (ficlStack *stack); + + +#if FICL_ROBUST >= 1 +FICL_PLATFORM_EXTERN void ficlStackCheck (ficlStack *stack, int popCells, int pushCells); +#define FICL_STACK_CHECK(stack, popCells, pushCells) ficlStackCheck(stack, popCells, pushCells) +#else /* FICL_ROBUST >= 1 */ +#define FICL_STACK_CHECK(stack, popCells, pushCells) +#endif /* FICL_ROBUST >= 1 */ + +typedef ficlInteger (*ficlStackWalkFunction)(void *constant, ficlCell *cell); +FICL_PLATFORM_EXTERN void ficlStackWalk(ficlStack *stack, ficlStackWalkFunction callback, void *context, ficlInteger bottomToTop); +FICL_PLATFORM_EXTERN void ficlStackDisplay(ficlStack *stack, ficlStackWalkFunction callback, void *context); + + +typedef ficlWord **ficlIp; /* the VM's instruction pointer */ +typedef void (*ficlPrimitive)(ficlVm *vm); +typedef void (*ficlOutputFunction)(ficlCallback *callback, char *text); + + /* -** Shortcuts (Guy Carver) +** Each VM has a placeholder for an output function - +** this makes it possible to have each VM do I/O +** through a different device. If you specify no +** ficlOutputFunction, it defaults to ficlCallbackDefaultTextOut. +** +** You can also set a specific handler just for errors. +** If you don't specify one, it defaults to using textOut. */ -#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) +struct ficlCallback +{ + void *context; + ficlOutputFunction textOut; + ficlOutputFunction errorOut; + ficlSystem *system; + ficlVm *vm; +}; + +FICL_PLATFORM_EXTERN void ficlCallbackTextOut(ficlCallback *callback, char *text); +FICL_PLATFORM_EXTERN void ficlCallbackErrorOut(ficlCallback *callback, char *text); + +/* +** For backwards compatibility. +*/ +typedef void (*ficlCompatibilityOutputFunction)(ficlVm *vm, char *text, int newline); +FICL_PLATFORM_EXTERN void ficlCompatibilityTextOutCallback(ficlCallback *callback, char *text, ficlCompatibilityOutputFunction oldFunction); + + + +/* +** Starting with Ficl 4.0, Ficl uses a "switch-threaded" inner loop, +** where each primitive word is represented with a numeric constant, +** and words are (more or less) arrays of these constants. In Ficl +** these constants are an enumerated type called ficlInstruction. +*/ +enum ficlInstruction +{ + #define FICL_TOKEN(token, description) token, + #define FICL_INSTRUCTION_TOKEN(token, description, flags) token, + #include "ficltokens.h" + #undef FICL_TOKEN + #undef FICL_INSTRUCTION_TOKEN + + ficlInstructionLast, + + ficlInstructionFourByteTrick = 0x10000000 +}; +typedef intptr_t ficlInstruction; + + /* ** The virtual machine (VM) contains the state for one interpreter. ** Defined operations include: ** Create & initialize ** Delete ** Execute a block of text ** Parse a word out of the input stream ** Call return, and branch ** Text output ** Throw an exception */ -typedef FICL_WORD ** IPTYPE; /* the VM's instruction pointer */ -/* -** Each VM has a placeholder for an output function - -** this makes it possible to have each VM do I/O -** through a different device. If you specify no -** OUTFUNC, it defaults to ficlTextOut. -*/ -typedef void (*OUTFUNC)(FICL_VM *pVM, char *text, int fNewline); +struct ficlVm +{ + ficlCallback callback; + ficlVm *link; /* Ficl keeps a VM list for simple teardown */ + jmp_buf *exceptionHandler; /* crude exception mechanism... */ + short restart; /* Set TRUE to restart runningWord */ + ficlIp ip; /* instruction pointer */ + ficlWord *runningWord;/* address of currently running word (often just *(ip-1) ) */ + ficlUnsigned state; /* compiling or interpreting */ + ficlUnsigned base; /* number conversion base */ + ficlStack *dataStack; + ficlStack *returnStack; /* return stack */ +#if FICL_WANT_FLOAT + ficlStack *floatStack; /* float stack (optional) */ +#endif + ficlCell sourceId; /* -1 if EVALUATE, 0 if normal input, >0 if a file */ + ficlTIB tib; /* address of incoming text string */ +#if FICL_WANT_USER + ficlCell user[FICL_USER_CELLS]; +#endif + char pad[FICL_PAD_SIZE]; /* the scratch area (see above) */ +#if FICL_WANT_COMPATIBILITY + ficlCompatibilityOutputFunction thunkedTextout; +#endif /* FICL_WANT_COMPATIBILITY */ +}; + /* ** Each VM operates in one of two non-error states: interpreting ** or compiling. When interpreting, words are simply executed. ** When compiling, most words in the input stream have their ** addresses inserted into the word under construction. Some words ** (known as IMMEDIATE) are executed in the compile state, too. */ /* values of STATE */ -#define INTERPRET 0 -#define COMPILE 1 +#define FICL_VM_STATE_INTERPRET (0) +#define FICL_VM_STATE_COMPILE (1) + /* -** The pad is a small scratch area for text manipulation. ANS Forth -** requires it to hold at least 84 characters. +** Exit codes for vmThrow */ -#if !defined nPAD -#define nPAD 256 -#endif +#define FICL_VM_STATUS_INNER_EXIT (-256) /* tell ficlVmExecuteXT to exit inner loop */ +#define FICL_VM_STATUS_OUT_OF_TEXT (-257) /* hungry - normal exit */ +#define FICL_VM_STATUS_RESTART (-258) /* word needs more text to succeed -- re-run it */ +#define FICL_VM_STATUS_USER_EXIT (-259) /* user wants to quit */ +#define FICL_VM_STATUS_ERROR_EXIT (-260) /* interpreter found an error */ +#define FICL_VM_STATUS_BREAK (-261) /* debugger breakpoint */ +#define FICL_VM_STATUS_ABORT ( -1) /* like FICL_VM_STATUS_ERROR_EXIT -- abort */ +#define FICL_VM_STATUS_ABORTQ ( -2) /* like FICL_VM_STATUS_ERROR_EXIT -- abort" */ +#define FICL_VM_STATUS_QUIT ( -56) /* like FICL_VM_STATUS_ERROR_EXIT, but leave dataStack & base alone */ -/* -** ANS Forth requires that a word's name contain {1..31} characters. + +FICL_PLATFORM_EXTERN void ficlVmBranchRelative(ficlVm *vm, int offset); +FICL_PLATFORM_EXTERN ficlVm * ficlVmCreate (ficlVm *vm, unsigned nPStack, unsigned nRStack); +FICL_PLATFORM_EXTERN void ficlVmDestroy (ficlVm *vm); +FICL_PLATFORM_EXTERN ficlDictionary *ficlVmGetDictionary(ficlVm *vm); +FICL_PLATFORM_EXTERN char * ficlVmGetString (ficlVm *vm, ficlCountedString *spDest, char delimiter); +FICL_PLATFORM_EXTERN ficlString ficlVmGetWord (ficlVm *vm); +FICL_PLATFORM_EXTERN ficlString ficlVmGetWord0 (ficlVm *vm); +FICL_PLATFORM_EXTERN int ficlVmGetWordToPad (ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmInnerLoop (ficlVm *vm, ficlWord *word); +FICL_PLATFORM_EXTERN ficlString ficlVmParseString (ficlVm *vm, char delimiter); +FICL_PLATFORM_EXTERN ficlString ficlVmParseStringEx(ficlVm *vm, char delimiter, char fSkipLeading); +FICL_PLATFORM_EXTERN ficlCell ficlVmPop (ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmPush (ficlVm *vm, ficlCell c); +FICL_PLATFORM_EXTERN void ficlVmPopIP (ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmPushIP (ficlVm *vm, ficlIp newIP); +FICL_PLATFORM_EXTERN void ficlVmQuit (ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmReset (ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmSetTextOut (ficlVm *vm, ficlOutputFunction textOut); +FICL_PLATFORM_EXTERN void ficlVmThrow (ficlVm *vm, int except); +FICL_PLATFORM_EXTERN void ficlVmThrowError (ficlVm *vm, char *fmt, ...); +FICL_PLATFORM_EXTERN void ficlVmThrowErrorVararg(ficlVm *vm, char *fmt, va_list list); +FICL_PLATFORM_EXTERN void ficlVmTextOut (ficlVm *vm, char *text); +FICL_PLATFORM_EXTERN void ficlVmErrorOut (ficlVm *vm, char *text); + +#define ficlVmGetContext(vm) ((vm)->context) +#define ficlVmGetDataStack(vm) ((vm)->dataStack) +#define ficlVmGetFloatStack(vm) ((vm)->floatStack) +#define ficlVmGetReturnStack(vm) ((vm)->returnStack) +#define ficlVmGetRunningWord(vm) ((vm)->runningWord) + +FICL_PLATFORM_EXTERN void ficlVmDisplayDataStack(ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmDisplayDataStackSimple(ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlVmDisplayReturnStack(ficlVm *vm); +#if FICL_WANT_FLOAT +FICL_PLATFORM_EXTERN void ficlVmDisplayFloatStack(ficlVm *vm); +#endif /* FICL_WANT_FLOAT */ + +/* +** 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. */ -#if !defined nFICLNAME -#define nFICLNAME 31 -#endif +FICL_PLATFORM_EXTERN int ficlVmEvaluate(ficlVm *vm, char *s); /* -** OK - now we can really define the VM... +** f i c l V m E x e c * +** Evaluates a block of input text in the context of the +** specified interpreter. Emits any requested output to the +** interpreter's output function. If the input string is NULL +** terminated, you can pass -1 as nChars rather than count it. +** Execution returns when the text block has been executed, +** or an error occurs. +** Returns one of the FICL_VM_STATUS_... codes defined in ficl.h: +** FICL_VM_STATUS_OUT_OF_TEXT is the normal exit condition +** FICL_VM_STATUS_ERROR_EXIT means that the interpreter encountered a syntax error +** and the vm has been reset to recover (some or all +** of the text block got ignored +** FICL_VM_STATUS_USER_EXIT means that the user executed the "bye" command +** to shut down the interpreter. This would be a good +** time to delete the vm, etc -- or you can ignore this +** signal. +** FICL_VM_STATUS_ABORT and FICL_VM_STATUS_ABORTQ are generated by 'abort' and 'abort"' +** commands. +** Preconditions: successful execution of ficlInitSystem, +** Successful creation and init of the VM by ficlNewVM (or equivalent) +** +** If you call ficlExec() or one of its brothers, you MUST +** ensure vm->sourceId was set to a sensible value. +** ficlExec() explicitly DOES NOT manage SOURCE-ID for you. */ -struct vm -{ - FICL_SYSTEM *pSys; /* Which system this VM belongs to */ - FICL_VM *link; /* Ficl keeps a VM list for simple teardown */ - jmp_buf *pState; /* crude exception mechanism... */ - OUTFUNC textOut; /* Output callback - see sysdep.c */ - void * pExtend; /* vm extension pointer for app use - initialized from FICL_SYSTEM */ - 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) */ -}; +FICL_PLATFORM_EXTERN int ficlVmExecuteString(ficlVm *vm, ficlString s); +FICL_PLATFORM_EXTERN int ficlVmExecuteXT(ficlVm *vm, ficlWord *pWord); +FICL_PLATFORM_EXTERN void ficlVmExecuteInstruction(ficlVm *vm, ficlInstruction i); +FICL_PLATFORM_EXTERN void ficlVmExecuteWord(ficlVm *vm, ficlWord *pWord); +FICL_PLATFORM_EXTERN void ficlVmDictionaryAllot(ficlVm *vm, ficlDictionary *dictionary, int n); +FICL_PLATFORM_EXTERN void ficlVmDictionaryAllotCells(ficlVm *vm, ficlDictionary *dictionary, int cells); + +FICL_PLATFORM_EXTERN int ficlVmParseWord(ficlVm *vm, ficlString s); + + + /* +** TIB access routines... +** ANS forth seems to require the input buffer to be represented +** as a pointer to the start of the buffer, and an index to the +** next character to read. +** PushTib points the VM to a new input string and optionally +** returns a copy of the current state +** PopTib restores the TIB state given a saved TIB from PushTib +** GetInBuf returns a pointer to the next unused char of the TIB +*/ +FICL_PLATFORM_EXTERN void ficlVmPushTib (ficlVm *vm, char *text, ficlInteger nChars, ficlTIB *pSaveTib); +FICL_PLATFORM_EXTERN void ficlVmPopTib (ficlVm *vm, ficlTIB *pTib); +#define ficlVmGetInBuf(vm) ((vm)->tib.text + (vm)->tib.index) +#define ficlVmGetInBufLen(vm) ((vm)->tib.end - (vm)->tib.text) +#define ficlVmGetInBufEnd(vm) ((vm)->tib.end) +#define ficlVmGetTibIndex(vm) ((vm)->tib.index) +#define ficlVmSetTibIndex(vm, i) ((vm)->tib.index = i) +#define ficlVmUpdateTib(vm, str) ((vm)->tib.index = (str) - (vm)->tib.text) + +#if FICL_ROBUST >= 1 + FICL_PLATFORM_EXTERN void ficlVmDictionaryCheck(ficlVm *vm, ficlDictionary *dictionary, int n); + FICL_PLATFORM_EXTERN void ficlVmDictionarySimpleCheck(ficlVm *vm, ficlDictionary *dictionary, int n); + #define FICL_VM_DICTIONARY_CHECK(vm, dictionary, n) ficlVmDictionaryCheck(vm, dictionary, n) + #define FICL_VM_DICTIONARY_SIMPLE_CHECK(vm, dictionary, n) ficlVmDictionarySimpleCheck(vm, dictionary, n) +#else + #define FICL_VM_DICTIONARY_CHECK(vm, dictionary, n) + #define FICL_VM_DICTIONARY_SIMPLE_CHECK(vm, dictionary, n) +#endif /* FICL_ROBUST >= 1 */ + + + +FICL_PLATFORM_EXTERN void ficlPrimitiveLiteralIm(ficlVm *vm); + +/* ** 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 /* ** Ficl models memory as a contiguous space divided into ** words in a linked list called the dictionary. -** A FICL_WORD starts each entry in the list. +** A ficlWord starts each entry in the list. ** Version 1.02: space for the name characters is allotted from ** the dictionary ahead of the word struct, rather than using ** a fixed size array for each name. */ -struct ficl_word +struct ficlWord { - struct ficl_word *link; /* Previous word in the dictionary */ - UNS16 hash; - UNS8 flags; /* Immediate, Smudge, Compile-only */ - FICL_COUNT nName; /* Number of chars in word name */ + struct ficlWord *link; /* Previous word in the dictionary */ + ficlUnsigned16 hash; + ficlUnsigned8 flags; /* Immediate, Smudge, Compile-only, IsOjbect, Instruction */ + ficlUnsigned8 length; /* Number of chars in word name */ char *name; /* First nFICLNAME chars of word name */ - FICL_CODE code; /* Native code to execute the word */ - CELL param[1]; /* First data cell of the word */ + ficlPrimitive code; /* Native code to execute the word */ + ficlInstruction semiParen; /* Native code to execute the word */ + ficlCell param[1]; /* First data cell of the word */ }; /* -** Worst-case size of a word header: nFICLNAME chars in name +** ficlWord.flag bitfield values: */ -#define CELLS_PER_WORD \ - ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \ - / (sizeof (CELL)) ) -int wordIsImmediate(FICL_WORD *pFW); -int wordIsCompileOnly(FICL_WORD *pFW); +/* +** FICL_WORD_IMMEDIATE: +** This word is always executed immediately when +** encountered, even when compiling. +*/ +#define FICL_WORD_IMMEDIATE ( 1) -/* flag values for word header */ -#define FW_IMMEDIATE 1 /* execute me even if compiling */ -#define FW_COMPILE 2 /* error if executed when not compiling */ -#define FW_SMUDGE 4 /* definition in progress - hide me */ -#define FW_ISOBJECT 8 /* word is an object or object member variable */ +/* +** FICL_WORD_COMPILE_ONLY: +** This word is only valid during compilation. +** Ficl will throw a runtime error if this word executed +** while not compiling. +*/ +#define FICL_WORD_COMPILE_ONLY ( 2) -#define FW_COMPIMMED (FW_IMMEDIATE | FW_COMPILE) -#define FW_DEFAULT 0 +/* +** FICL_WORD_SMUDGED +** This word's definition is in progress. +** The word is hidden from dictionary lookups +** until it is "un-smudged". +*/ +#define FICL_WORD_SMUDGED ( 4) +/* +** FICL_WORD_OBJECT +** This word is an object or object member variable. +** (Currently only used by "my=[".) +*/ +#define FICL_WORD_OBJECT ( 8) /* -** Exit codes for vmThrow +** FICL_WORD_INSTRUCTION +** This word represents a ficlInstruction, not a normal word. +** param[0] is the instruction. +** When compiled, Ficl will simply copy over the instruction, +** rather than executing the word as normal. +** +** (Do *not* use this flag for words that need their PFA pushed +** before executing!) */ -#define VM_INNEREXIT -256 /* tell ficlExecXT to exit inner loop */ -#define VM_OUTOFTEXT -257 /* hungry - normal exit */ -#define VM_RESTART -258 /* word needs more text to succeed - re-run it */ -#define VM_USEREXIT -259 /* user wants to quit */ -#define VM_ERREXIT -260 /* interp found an error */ -#define VM_BREAK -261 /* debugger breakpoint */ -#define VM_ABORT -1 /* like errexit -- abort */ -#define VM_ABORTQ -2 /* like errexit -- abort" */ -#define VM_QUIT -56 /* like errexit, but leave pStack & base alone */ +#define FICL_WORD_INSTRUCTION (16) +/* +** FICL_WORD_COMPILE_ONLY_IMMEDIATE +** Most words that are "immediate" are also +** "compile-only". +*/ +#define FICL_WORD_COMPILE_ONLY_IMMEDIATE (FICL_WORD_IMMEDIATE | FICL_WORD_COMPILE_ONLY) +#define FICL_WORD_DEFAULT ( 0) -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 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) - - /* -** The inner interpreter - coded as a macro (see note for -** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5 +** Worst-case size of a word header: FICL_NAME_LENGTH chars in name */ -#define M_VM_STEP(pVM) \ - FICL_WORD *tempFW = *(pVM)->ip++; \ - (pVM)->runningWord = tempFW; \ - tempFW->code(pVM); +#define FICL_CELLS_PER_WORD \ + ( (sizeof (ficlWord) + FICL_NAME_LENGTH + sizeof (ficlCell)) \ + / (sizeof (ficlCell)) ) -#define M_INNER_LOOP(pVM) \ - for (;;) { M_VM_STEP(pVM) } +FICL_PLATFORM_EXTERN int ficlWordIsImmediate(ficlWord *word); +FICL_PLATFORM_EXTERN int ficlWordIsCompileOnly(ficlWord *word); -#if INLINE_INNER_LOOP != 0 -#define vmInnerLoop(pVM) M_INNER_LOOP(pVM) + + +#if FICL_ROBUST >= 1 + FICL_PLATFORM_EXTERN void ficlCallbackAssert(ficlCallback *callback, int expression, char *expressionString, char *filename, int line); + #define FICL_ASSERT(callback, expression) (ficlCallbackAssert((callback), (expression) != 0, #expression, __FILE__, __LINE__)) #else -void vmInnerLoop(FICL_VM *pVM); -#endif + #define FICL_ASSERT(callback, expression) +#endif /* FICL_ROBUST >= 1 */ -/* -** vmCheckStack needs a vm pointer because it might have to say -** something if it finds a problem. Parms popCells and pushCells -** correspond to the number of parameters on the left and right of -** a word's stack effect comment. -*/ -void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells); -#if FICL_WANT_FLOAT -void vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells); -#endif +#define FICL_VM_ASSERT(vm, expression) FICL_ASSERT((ficlCallback *)(vm), (expression)) +#define FICL_SYSTEM_ASSERT(system, expression) FICL_ASSERT((ficlCallback *)(system), (expression)) -/* -** TIB access routines... -** ANS forth seems to require the input buffer to be represented -** as a pointer to the start of the buffer, and an index to the -** next character to read. -** PushTib points the VM to a new input string and optionally -** returns a copy of the current state -** PopTib restores the TIB state given a saved TIB from PushTib -** GetInBuf returns a pointer to the next unused char of the TIB -*/ -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 + /* ** Generally useful string manipulators omitted by ANSI C... ** ltoa complements strtol */ -#if defined(_WIN32) && !FICL_MAIN -/* #SHEESH -** Why do Microsoft Meatballs insist on contaminating -** my namespace with their string functions??? -*/ -#pragma warning(disable: 4273) -#endif -int isPowerOfTwo(FICL_UNS u); +FICL_PLATFORM_EXTERN int ficlIsPowerOfTwo(ficlUnsigned 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); +FICL_PLATFORM_EXTERN char *ficlLtoa(ficlInteger value, char *string, int radix ); +FICL_PLATFORM_EXTERN char *ficlUltoa(ficlUnsigned value, char *string, int radix ); +FICL_PLATFORM_EXTERN char ficlDigitToCharacter(int value); +FICL_PLATFORM_EXTERN char *ficlStringReverse( char *string ); +FICL_PLATFORM_EXTERN char *ficlStringSkipSpace(char *s, char *end); +FICL_PLATFORM_EXTERN char *ficlStringCaseFold(char *s); +FICL_PLATFORM_EXTERN int ficlStrincmp(char *s1, char *s2, ficlUnsigned length); +FICL_PLATFORM_EXTERN void *ficlAlignPointer(void *ptr); -#if defined(_WIN32) && !FICL_MAIN -#pragma warning(default: 4273) -#endif /* ** Ficl hash table - variable size. ** assert(size > 0) ** If size is 1, the table degenerates into a linked list. ** A WORDLIST (see the search order word set in DPANS) is ** just a pointer to a FICL_HASH in this implementation. */ -#if !defined HASHSIZE /* Default size of hash table. For most uniform */ -#define HASHSIZE 241 /* performance, use a prime number! */ -#endif -typedef struct ficl_hash +typedef struct ficlHash { - struct ficl_hash *link; /* link to parent class wordlist for OO */ + struct ficlHash *link; /* link to parent class wordlist for OO */ char *name; /* optional pointer to \0 terminated wordlist name */ unsigned size; /* number of buckets in the hash */ - FICL_WORD *table[1]; -} FICL_HASH; + ficlWord *table[1]; +} 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); +FICL_PLATFORM_EXTERN void ficlHashForget (ficlHash *hash, void *where); +FICL_PLATFORM_EXTERN ficlUnsigned16 ficlHashCode (ficlString s); +FICL_PLATFORM_EXTERN void ficlHashInsertWord(ficlHash *hash, ficlWord *word); +FICL_PLATFORM_EXTERN ficlWord *ficlHashLookup (ficlHash *hash, ficlString name, ficlUnsigned16 hashCode); +FICL_PLATFORM_EXTERN void ficlHashReset (ficlHash *hash); /* ** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's ** memory model. Description of fields: ** ** here -- points to the next free byte in the dictionary. This ** pointer is forced to be CELL-aligned before a definition is added. ** Do not assume any specific alignment otherwise - Use dictAlign(). ** ** smudge -- pointer to word currently being defined (or last defined word) ** If the definition completes successfully, the word will be ** linked into the hash table. If unsuccessful, dictUnsmudge ** uses this pointer to restore the previous state of the dictionary. ** Smudge prevents unintentional recursion as a side-effect: the ** dictionary search algo examines only completed definitions, so a -** word cannot invoke itself by name. See the ficl word "recurse". +** word cannot invoke itself by name. See the Ficl word "recurse". ** NOTE: smudge always points to the last word defined. IMMEDIATE ** makes use of this fact. Smudge is initially NULL. ** -** pForthWords -- pointer to the default wordlist (FICL_HASH). +** forthWordlist -- pointer to the default wordlist (FICL_HASH). ** This is the initial compilation list, and contains all -** ficl's precompiled words. +** Ficl's precompiled words. ** -** pCompile -- compilation wordlist - initially equal to pForthWords -** pSearch -- array of pointers to wordlists. Managed as a stack. +** compilationWordlist -- compilation wordlist - initially equal to forthWordlist +** wordlists -- array of pointers to wordlists. Managed as a stack. ** Highest index is the first list in the search order. -** nLists -- number of lists in pSearch. nLists-1 is the highest -** filled slot in pSearch, and points to the first wordlist +** wordlistCount -- number of lists in wordlists. wordlistCount-1 is the highest +** filled slot in wordlists, and points to the first wordlist ** in the search order ** size -- number of cells in the dictionary (total) -** dict -- start of data area. Must be at the end of the struct. +** base -- start of data area. Must be at the end of the struct. */ -struct ficl_dict +struct ficlDictionary { - CELL *here; - 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)*/ - CELL dict[1]; /* Base of dictionary memory */ + ficlCell *here; + void *context; /* for your use, particularly with ficlDictionaryLock() */ + ficlWord *smudge; + ficlHash *forthWordlist; + ficlHash *compilationWordlist; + ficlHash *wordlists[FICL_MAX_WORDLISTS]; + int wordlistCount; + unsigned size; /* Number of cells in dictionary (total)*/ + ficlSystem *system; /* used for debugging */ + ficlCell base[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, +FICL_PLATFORM_EXTERN void ficlDictionaryAbortDefinition(ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN void ficlDictionaryAlign (ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN void ficlDictionaryAllot (ficlDictionary *dictionary, int n); +FICL_PLATFORM_EXTERN void ficlDictionaryAllotCells (ficlDictionary *dictionary, int nCells); +FICL_PLATFORM_EXTERN void ficlDictionaryAppendCell (ficlDictionary *dictionary, ficlCell c); +FICL_PLATFORM_EXTERN void ficlDictionaryAppendCharacter(ficlDictionary *dictionary, char c); +FICL_PLATFORM_EXTERN void ficlDictionaryAppendUnsigned(ficlDictionary *dictionary, ficlUnsigned u); +FICL_PLATFORM_EXTERN void *ficlDictionaryAppendData(ficlDictionary *dictionary, void *data, ficlInteger length); +FICL_PLATFORM_EXTERN char *ficlDictionaryAppendString(ficlDictionary *dictionary, ficlString s); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendWord(ficlDictionary *dictionary, + ficlString name, + ficlPrimitive pCode, + ficlUnsigned8 flags); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendPrimitive(ficlDictionary *dictionary, 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); + ficlPrimitive pCode, + ficlUnsigned8 flags); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendInstruction(ficlDictionary *dictionary, + char *name, + ficlInstruction i, + ficlUnsigned8 flags); + +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficlInteger value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppend2ConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficl2Integer value); + +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendConstant(ficlDictionary *dictionary, char *name, ficlInteger value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppend2Constant(ficlDictionary *dictionary, char *name, ficl2Integer value); +#define ficlDictionaryAppendConstantPointer(dictionary, name, pointer) \ + (ficlDictionaryAppendConstant(dictionary, name, (ficlInteger)pointer)) #if FICL_WANT_FLOAT -void dictHashSummary(FICL_VM *pVM); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendFConstant(ficlDictionary *dictionary, char *name, float value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryAppendF2Constant(ficlDictionary *dictionary, char *name, double value); +#endif /* FICL_WANT_FLOAT */ + + +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficlInteger value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySet2ConstantInstruction(ficlDictionary *dictionary, ficlString name, ficlInstruction instruction, ficl2Integer value); + +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetConstant(ficlDictionary *dictionary, char *name, ficlInteger value); +#define ficlDictionarySetConstantPointer(dictionary, name, pointer) \ + (ficlDictionarySetConstant(dictionary, name, (ficlInteger)pointer)) +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySet2Constant(ficlDictionary *dictionary, char *name, ficl2Integer value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetConstantString(ficlDictionary *dictionary, char *name, char *value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetPrimitive(ficlDictionary *dictionary, + char *name, + ficlPrimitive code, + ficlUnsigned8 flags); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetInstruction(ficlDictionary *dictionary, + char *name, + ficlInstruction i, + ficlUnsigned8 flags); +#if FICL_WANT_FLOAT +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetFConstant(ficlDictionary *dictionary, char *name, float value); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionarySetF2Constant(ficlDictionary *dictionary, char *name, double value); +#endif /* FICL_WANT_FLOAT */ + +FICL_PLATFORM_EXTERN int ficlDictionaryCellsAvailable (ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN int ficlDictionaryCellsUsed (ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN ficlDictionary *ficlDictionaryCreate(ficlSystem *system, unsigned nCELLS); +FICL_PLATFORM_EXTERN ficlDictionary *ficlDictionaryCreateHashed(ficlSystem *system, unsigned nCells, unsigned nHash); +FICL_PLATFORM_EXTERN ficlHash *ficlDictionaryCreateWordlist(ficlDictionary *dictionary, int nBuckets); +FICL_PLATFORM_EXTERN void ficlDictionaryDestroy (ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN void ficlDictionaryEmpty (ficlDictionary *dictionary, unsigned nHash); +FICL_PLATFORM_EXTERN int ficlDictionaryIncludes (ficlDictionary *dictionary, void *p); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryLookup (ficlDictionary *dictionary, ficlString name); +FICL_PLATFORM_EXTERN void ficlDictionaryResetSearchOrder(ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN void ficlDictionarySetFlags (ficlDictionary *dictionary, ficlUnsigned8 set); +FICL_PLATFORM_EXTERN void ficlDictionaryClearFlags(ficlDictionary *dictionary, ficlUnsigned8 clear); +FICL_PLATFORM_EXTERN void ficlDictionarySetImmediate(ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN void ficlDictionaryUnsmudge (ficlDictionary *dictionary); +FICL_PLATFORM_EXTERN ficlCell *ficlDictionaryWhere (ficlDictionary *dictionary); + +FICL_PLATFORM_EXTERN int ficlDictionaryIsAWord(ficlDictionary *dictionary, ficlWord *word); +FICL_PLATFORM_EXTERN void ficlDictionarySee(ficlDictionary *dictionary, ficlWord *word, ficlCallback *callback); +FICL_PLATFORM_EXTERN ficlWord *ficlDictionaryFindEnclosingWord(ficlDictionary *dictionary, ficlCell *cell); + +/* +** Stub function for dictionary access control - does nothing +** by default, user can redefine to guarantee exclusive dictionary +** access to a single thread for updates. All dictionary update code +** must be bracketed as follows: +** ficlLockDictionary(dictionary, FICL_TRUE); // any non-zero value will do +** +** ficlLockDictionary(dictionary, FICL_FALSE); +** +** Returns zero if successful, nonzero if unable to acquire lock +** before timeout (optional - could also block forever) +** +** NOTE: this function must be implemented with lock counting +** semantics: nested calls must behave properly. +*/ +#if FICL_MULTITHREAD +FICL_PLATFORM_EXTERN int ficlDictionaryLock(ficlDictionary *dictionary, short lockIncrement); +#else +#define ficlDictionaryLock(dictionary, lock) (void)0 /* ignore */ #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); + /* ** P A R S E S T E P ** (New for 2.05) ** See words.c: interpWord -** By default, ficl goes through two attempts to parse each token from its input +** By default, Ficl goes through two attempts to parse each token from its input ** stream: it first attempts to match it with a word in the dictionary, and ** if that fails, it attempts to convert it into a number. This mechanism is now ** extensible by additional steps. This allows extensions like floating point and ** double number support to be factored cleanly. ** ** Each parse step is a function that receives the next input token as a STRINGINFO. ** If the parse step matches the token, it must apply semantics to the token appropriate ** to the present value of VM.state (compiling or interpreting), and return FICL_TRUE. ** Otherwise it returns FICL_FALSE. See words.c: isNumber for an example ** ** Note: for the sake of efficiency, it's a good idea both to limit the number ** of parse steps and to code each parse step so that it rejects tokens that ** do not match as quickly as possible. */ -typedef int (*FICL_PARSE_STEP)(FICL_VM *pVM, STRINGINFO si); +typedef int (*ficlParseStep)(ficlVm *vm, ficlString s); /* -** Appends a parse step function to the end of the parse list (see -** FICL_PARSE_STEP notes in ficl.h for details). Returns 0 if successful, -** nonzero if there's no more room in the list. Each parse step is a word in -** the dictionary. Precompiled parse steps can use (PARSE-STEP) as their -** CFA - see parenParseStep in words.c. -*/ -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); - -/* ** FICL_BREAKPOINT record. -** origXT - if NULL, this breakpoint is unused. Otherwise it stores the xt +** oldXT - 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 +** oldXT - The original contents of the location with the breakpoint ** Note: address is NULL when this breakpoint is empty */ -typedef struct FICL_BREAKPOINT +typedef struct ficlBreakpoint { void *address; - FICL_WORD *origXT; -} FICL_BREAKPOINT; + ficlWord *oldXT; +} ficlBreakpoint; /* ** 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 -** support multiple Ficl systems, allowing multiple concurrent sessions +** virtual machines with their corresponding dictionaries. Ficl 3.0 added +** support for multiple Ficl systems, allowing multiple concurrent sessions ** to separate dictionaries with some constraints. -** The present model allows multiple sessions to one dictionary provided -** you implement ficlLockDictionary() as specified in sysdep.h -** Note: the pExtend pointer is there to provide context for applications. It is copied -** to each VM's pExtend field as that VM is created. +** Note: the context pointer is there to provide context for applications. It is copied +** to each VM's context field as that VM is created. */ -struct ficl_system +struct ficlSystemInformation { - FICL_SYSTEM *link; - void *pExtend; /* Initializes VM's pExtend pointer (for application use) */ - FICL_VM *vmList; - FICL_DICT *dp; - FICL_DICT *envp; -#ifdef FICL_WANT_LOCALS - FICL_DICT *localp; -#endif - FICL_WORD *pInterp[3]; - FICL_WORD *parseList[FICL_MAX_PARSE_STEPS]; - OUTFUNC textOut; + int size; /* structure size tag for versioning */ + void *context; /* Initializes VM's context pointer - for application use */ + int dictionarySize; /* Size of system's Dictionary, in cells */ + int stackSize; /* Size of all stacks created, in cells */ + ficlOutputFunction textOut; /* default textOut function */ + ficlOutputFunction errorOut; /* textOut function used for errors */ + int environmentSize; /* Size of Environment dictionary, in cells */ +}; - FICL_WORD *pBranchParen; - FICL_WORD *pDoParen; - FICL_WORD *pDoesParen; - FICL_WORD *pExitInner; - FICL_WORD *pExitParen; - FICL_WORD *pBranch0; - FICL_WORD *pInterpret; - FICL_WORD *pLitParen; - FICL_WORD *pTwoLitParen; - FICL_WORD *pLoopParen; - FICL_WORD *pPLoopParen; - FICL_WORD *pQDoParen; - FICL_WORD *pSemiParen; - FICL_WORD *pOfParen; - FICL_WORD *pStore; - FICL_WORD *pDrop; - FICL_WORD *pCStringLit; - FICL_WORD *pStringLit; +#define ficlSystemInformationInitialize(x) { memset((x), 0, sizeof(ficlSystemInformation)); \ + (x)->size = sizeof(ficlSystemInformation); } + + + +struct ficlSystem +{ + ficlCallback callback; + ficlSystem *link; + ficlVm *vmList; + ficlDictionary *dictionary; + ficlDictionary *environment; + + ficlWord *interpreterLoop[3]; + ficlWord *parseList[FICL_MAX_PARSE_STEPS]; + + ficlWord *exitInnerWord; + ficlWord *interpretWord; + #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; + ficlDictionary *locals; + ficlInteger localsCount; + ficlCell *localsFixup; #endif - FICL_BREAKPOINT bpStep; -}; + ficlInteger stackSize; -struct ficl_system_info -{ - int size; /* structure size tag for versioning */ - int nDictCells; /* Size of system's Dictionary */ - OUTFUNC textOut; /* default textOut function */ - void *pExtend; /* Initializes VM's pExtend pointer - for application use */ - int nEnvCells; /* Size of Environment dictionary */ + ficlBreakpoint breakpoint; +#if FICL_WANT_COMPATIBILITY + ficlCompatibilityOutputFunction thunkedTextout; +#endif /* FICL_WANT_COMPATIBILITY */ }; -#define ficlInitInfo(x) { memset((x), 0, sizeof(FICL_SYSTEM_INFO)); \ - (x)->size = sizeof(FICL_SYSTEM_INFO); } +#define ficlSystemGetContext(system) ((system)->context) + /* -** External interface to FICL... +** External interface to Ficl... */ /* -** f i c l I n i t S y s t e m +** f i c l S y s t e m C r e a t e ** Binds a global dictionary to the interpreter system and initializes -** the dict to contain the ANSI CORE wordset. +** the dictionary to contain the ANSI CORE wordset. ** 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. +** You can also specify the text output function at creation time. +** 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. */ -FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi); +FICL_PLATFORM_EXTERN ficlSystem *ficlSystemCreate(ficlSystemInformation *fsi); -/* Deprecated call */ -FICL_SYSTEM *ficlInitSystem(int nDictCells); - /* -** f i c l T e r m S y s t e m +** f i c l S y s t e m D e s t r o y ** Deletes the system dictionary and all virtual machines that ** were created with ficlNewVM (see below). Call this function to ** reclaim all memory used by the dictionary and VMs. */ -void ficlTermSystem(FICL_SYSTEM *pSys); +FICL_PLATFORM_EXTERN void ficlSystemDestroy(ficlSystem *system); /* -** 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 -** interpreter's output function. If the input string is NULL -** terminated, you can pass -1 as nChars rather than count it. -** Execution returns when the text block has been executed, -** or an error occurs. -** Returns one of the VM_XXXX codes defined in ficl.h: -** VM_OUTOFTEXT is the normal exit condition -** VM_ERREXIT means that the interp encountered a syntax error -** and the vm has been reset to recover (some or all -** of the text block got ignored -** VM_USEREXIT means that the user executed the "bye" command -** to shut down the interpreter. This would be a good -** time to delete the vm, etc -- or you can ignore this -** signal. -** VM_ABORT and VM_ABORTQ are generated by 'abort' and 'abort"' -** 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); -int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord); - -/* ** Create a new VM from the heap, and link it into the system VM list. ** Initializes the VM and binds default sized stacks to it. Returns the ** address of the VM, or NULL if an error occurs. ** Precondition: successful execution of ficlInitSystem */ -FICL_VM *ficlNewVM(FICL_SYSTEM *pSys); +FICL_PLATFORM_EXTERN ficlVm *ficlSystemCreateVm(ficlSystem *system); /* ** Force deletion of a VM. You do not need to do this ** unless you're creating and discarding a lot of VMs. ** For systems that use a constant pool of VMs for the life ** of the system, ficltermSystem takes care of VM cleanup ** automatically. */ -void ficlFreeVM(FICL_VM *pVM); +FICL_PLATFORM_EXTERN void ficlSystemDestroyVm(ficlVm *vm); /* -** Set the stack sizes (return and parameter) to be used for all -** subsequently created VMs. Returns actual stack size to be used. -*/ -int ficlSetStackSize(int nStackCells); - -/* ** Returns the address of the most recently defined word in the system ** dictionary with the given name, or NULL if no match. ** Precondition: successful execution of ficlInitSystem */ -FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name); +FICL_PLATFORM_EXTERN ficlWord *ficlSystemLookup(ficlSystem *system, char *name); /* ** f i c l G e t D i c t ** Utility function - returns the address of the system dictionary. ** Precondition: successful execution of ficlInitSystem */ -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); +ficlDictionary *ficlSystemGetDictionary(ficlSystem *system); +ficlDictionary *ficlSystemGetEnvironment(ficlSystem *system); #if FICL_WANT_LOCALS -FICL_DICT *ficlGetLoc (FICL_SYSTEM *pSys); +ficlDictionary *ficlSystemGetLocals(ficlSystem *system); #endif -/* -** f i c l B u i l d -** Builds a word into the system default dictionary in a thread-safe way. -** Preconditions: system must be initialized, and there must -** be enough space for the new word's header! Operation is -** controlled by ficlLockDictionary, so any initialization -** required by your version of the function (if you "overrode" -** it) must be complete at this point. -** Parameters: -** name -- the name of the word to be built -** code -- code to execute when the word is invoked - must take a single param -** pointer to a FICL_VM -** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR! -** Most words can use FW_DEFAULT. -** nAllot - number of extra cells to allocate in the parameter area (usually zero) -*/ -int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags); /* ** f i c l C o m p i l e C o r e ** Builds the ANS CORE wordset into the dictionary - called by -** ficlInitSystem - no need to waste dict space by doing it again. +** ficlInitSystem - no need to waste dictionary space by doing it again. */ -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); +FICL_PLATFORM_EXTERN void ficlSystemCompileCore(ficlSystem *system); +FICL_PLATFORM_EXTERN void ficlSystemCompilePrefix(ficlSystem *system); +FICL_PLATFORM_EXTERN void ficlSystemCompileSearch(ficlSystem *system); +FICL_PLATFORM_EXTERN void ficlSystemCompileSoftCore(ficlSystem *system); +FICL_PLATFORM_EXTERN void ficlSystemCompileTools(ficlSystem *system); +FICL_PLATFORM_EXTERN void ficlSystemCompileFile(ficlSystem *system); #if FICL_WANT_FLOAT -void ficlCompileFloat(FICL_SYSTEM *pSys); -int ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si ); /* float.c */ +FICL_PLATFORM_EXTERN void ficlSystemCompileFloat(ficlSystem *system); +FICL_PLATFORM_EXTERN int ficlVmParseFloatNumber(ficlVm *vm, ficlString s); +#endif /* FICL_WANT_FLOAT */ +#if FICL_WANT_PLATFORM +FICL_PLATFORM_EXTERN void ficlSystemCompilePlatform(ficlSystem *system); +#endif /* FICL_WANT_PLATFORM */ +FICL_PLATFORM_EXTERN void ficlSystemCompileExtras(ficlSystem *system); + + +FICL_PLATFORM_EXTERN int ficlVmParsePrefix(ficlVm *vm, ficlString s); + +#if FICL_WANT_LOCALS +FICL_PLATFORM_EXTERN ficlWord *ficlSystemLookupLocal(ficlSystem *system, ficlString name); #endif -#if FICL_PLATFORM_EXTEND -void ficlCompilePlatform(FICL_SYSTEM *pSys); -#endif -int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si); /* ** from words.c... */ -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); +FICL_PLATFORM_EXTERN int ficlVmParseNumber(ficlVm *vm, ficlString s); +FICL_PLATFORM_EXTERN void ficlPrimitiveTick(ficlVm *vm); +FICL_PLATFORM_EXTERN void ficlPrimitiveParseStepParen(ficlVm *vm); +#if FICL_WANT_LOCALS +FICL_PLATFORM_EXTERN void ficlLocalParen(ficlVm *vm, int isDouble, int isFloat); +#endif /* FICL_WANT_LOCALS */ + /* +** Appends a parse step function to the end of the parse list (see +** FICL_PARSE_STEP notes in ficl.h for details). Returns 0 if successful, +** nonzero if there's no more room in the list. Each parse step is a word in +** the dictionary. Precompiled parse steps can use (PARSE-STEP) as their +** CFA - see parenParseStep in words.c. +*/ +FICL_PLATFORM_EXTERN int ficlSystemAddParseStep(ficlSystem *system, ficlWord *word); /* ficl.c */ +FICL_PLATFORM_EXTERN void ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name, ficlParseStep pStep); + + +/* ** From tools.c */ -int isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW); /* ** The following supports SEE and the debugger. */ typedef enum { - BRANCH, - COLON, - CONSTANT, - CREATE, - DO, - DOES, - IF, - LITERAL, - LOOP, - OF, - PLOOP, - PRIMITIVE, - QDO, - STRINGLIT, - CSTRINGLIT, + FICL_WORDKIND_BRANCH, + FICL_WORDKIND_BRANCH0, + FICL_WORDKIND_COLON, + FICL_WORDKIND_CONSTANT, + FICL_WORDKIND_2CONSTANT, + FICL_WORDKIND_CREATE, + FICL_WORDKIND_DO, + FICL_WORDKIND_DOES, + FICL_WORDKIND_LITERAL, + FICL_WORDKIND_2LITERAL, +#if FICL_WANT_FLOAT + FICL_WORDKIND_FLITERAL, +#endif /* FICL_WANT_FLOAT */ + FICL_WORDKIND_LOOP, + FICL_WORDKIND_OF, + FICL_WORDKIND_PLOOP, + FICL_WORDKIND_PRIMITIVE, + FICL_WORDKIND_QDO, + FICL_WORDKIND_STRING_LITERAL, + FICL_WORDKIND_CSTRING_LITERAL, #if FICL_WANT_USER - USER, + FICL_WORDKIND_USER, #endif - VARIABLE, -} WORDKIND; + FICL_WORDKIND_VARIABLE, + FICL_WORDKIND_INSTRUCTION, + FICL_WORDKIND_INSTRUCTION_WORD, + FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT, +} ficlWordKind; -WORDKIND ficlWordClassify(FICL_WORD *pFW); +ficlWordKind ficlWordClassify(ficlWord *word); + /* ** 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 +typedef struct ficlFile { - FILE *f; - char filename[256]; -} ficlFILE; + FILE *f; + char filename[256]; +} ficlFile; + + +#if defined (FICL_PLATFORM_HAS_FTRUNCATE) +FICL_PLATFORM_EXTERN int ficlFileTruncate(ficlFile *ff, ficlUnsigned size); +#endif + +FICL_PLATFORM_EXTERN int ficlFileStatus(char *filename, int *status); +FICL_PLATFORM_EXTERN long ficlFileSize(ficlFile *ff); + + +/* +** Used with compressed softcore. +** +*/ + +#ifndef FICL_BIT_NUMBER +#define FICL_BIT_NUMBER(x) (1 << (x)) +#endif /* FICL_BIT_NUMBER */ + +#ifndef FICL_BIT_SET +#define FICL_BIT_SET(value, flag) ((value) |= (flag)) +#endif /* FICL_BIT_SET */ + +#ifndef FICL_BIT_CLEAR +#define FICL_BIT_CLEAR(value, flag) ((value) &= ~(flag)) +#endif /* FICL_BIT_CLEAR */ + +#ifndef FICL_BIT_CHECK +#define FICL_BIT_CHECK(value, flag) ((value) & (flag)) +#endif /* FICL_BIT_CHECK */ + + +#define FICL_LZ_TYPE_BITS (1) +#define FICL_LZ_OFFSET_BITS (12) +#define FICL_LZ_LENGTH_BITS (5) +#define FICL_LZ_NEXT_BITS (8) +#define FICL_LZ_PHRASE_BITS (FICL_LZ_TYPE_BITS + FICL_LZ_OFFSET_BITS + FICL_LZ_LENGTH_BITS + FICL_LZ_NEXT_BITS) +#define FICL_LZ_SYMBOL_BITS (FICL_LZ_TYPE_BITS + FICL_LZ_NEXT_BITS) + +/* +** if you match fewer characters than this, don't bother, +** it's smaller to encode it as a sequence of symbol tokens. +**/ +#define FICL_LZ_MINIMUM_USEFUL_MATCH ((int)(FICL_LZ_PHRASE_BITS / FICL_LZ_SYMBOL_BITS)) + +#define FICL_LZ_WINDOW_SIZE (FICL_BIT_NUMBER(FICL_LZ_OFFSET_BITS)) +#define FICL_LZ_BUFFER_SIZE (FICL_BIT_NUMBER(FICL_LZ_LENGTH_BITS) + FICL_LZ_MINIMUM_USEFUL_MATCH) + +FICL_PLATFORM_EXTERN int ficlBitGet(const unsigned char *bits, size_t index); +FICL_PLATFORM_EXTERN void ficlBitSet(unsigned char *bits, size_t size_t, int value); +FICL_PLATFORM_EXTERN void ficlBitGetString(unsigned char *destination, const unsigned char *source, int offset, int count, int destAlignment); + +FICL_PLATFORM_EXTERN ficlUnsigned16 ficlNetworkUnsigned16(ficlUnsigned16 number); +FICL_PLATFORM_EXTERN ficlUnsigned32 ficlNetworkUnsigned32(ficlUnsigned32 number); + +#define FICL_MIN(a, b) (((a) < (b)) ? (a) : (b)) +FICL_PLATFORM_EXTERN int ficlLzCompress(const unsigned char *uncompressed, size_t uncompressedSize, unsigned char **compressed, size_t *compressedSize); +FICL_PLATFORM_EXTERN int ficlLzUncompress(const unsigned char *compressed, unsigned char **uncompressed, size_t *uncompressedSize); + + + +#if FICL_WANT_COMPATIBILITY + #include "ficlcompatibility.h" +#endif /* FICL_WANT_COMPATIBILITY */ + #ifdef __cplusplus } #endif #endif /* __FICL_H__ */ Index: vendor/ficl/dist/ficlcompatibility.h =================================================================== --- vendor/ficl/dist/ficlcompatibility.h (nonexistent) +++ vendor/ficl/dist/ficlcompatibility.h (revision 282803) @@ -0,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 */ Property changes on: vendor/ficl/dist/ficlcompatibility.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficldll.def =================================================================== --- vendor/ficl/dist/ficldll.def (nonexistent) +++ vendor/ficl/dist/ficldll.def (revision 282803) @@ -0,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 + Index: vendor/ficl/dist/ficldll.dsp =================================================================== --- vendor/ficl/dist/ficldll.dsp (nonexistent) +++ vendor/ficl/dist/ficldll.dsp (revision 282803) @@ -0,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 Index: vendor/ficl/dist/ficlexe.dsp =================================================================== --- vendor/ficl/dist/ficlexe.dsp (nonexistent) +++ vendor/ficl/dist/ficlexe.dsp (revision 282803) @@ -0,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 Index: vendor/ficl/dist/ficllib.dsp =================================================================== --- vendor/ficl/dist/ficllib.dsp (nonexistent) +++ vendor/ficl/dist/ficllib.dsp (revision 282803) @@ -0,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 Index: vendor/ficl/dist/ficllocal.h =================================================================== --- vendor/ficl/dist/ficllocal.h (nonexistent) +++ vendor/ficl/dist/ficllocal.h (revision 282803) @@ -0,0 +1,8 @@ +/* +** ficllocal.h +** +** Put all local settings here. This file will always ship empty. +** +*/ + + Property changes on: vendor/ficl/dist/ficllocal.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/alpha.h =================================================================== --- vendor/ficl/dist/ficlplatform/alpha.h (nonexistent) +++ vendor/ficl/dist/ficlplatform/alpha.h (revision 282803) @@ -0,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; Property changes on: vendor/ficl/dist/ficlplatform/alpha.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/ansi.c =================================================================== --- vendor/ficl/dist/ficlplatform/ansi.c (nonexistent) +++ vendor/ficl/dist/ficlplatform/ansi.c (revision 282803) @@ -0,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; +} + + Property changes on: vendor/ficl/dist/ficlplatform/ansi.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/ansi.h =================================================================== --- vendor/ficl/dist/ficlplatform/ansi.h (nonexistent) +++ vendor/ficl/dist/ficlplatform/ansi.h (revision 282803) @@ -0,0 +1,19 @@ +#include + +typedef int8_t ficlInteger8; +typedef uint8_t ficlUnsigned8; +typedef int16_t ficlInteger16; +typedef uint16_t ficlUnsigned16; +typedef int32_t ficlInteger32; +typedef uint32_t ficlUnsigned32; + +typedef intptr_t ficlInteger; +typedef uintptr_t 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" Property changes on: vendor/ficl/dist/ficlplatform/ansi.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/ficlexports.txt =================================================================== --- vendor/ficl/dist/ficlplatform/ficlexports.txt (nonexistent) +++ vendor/ficl/dist/ficlplatform/ficlexports.txt (revision 282803) @@ -0,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 + Property changes on: vendor/ficl/dist/ficlplatform/ficlexports.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/makedef.py =================================================================== --- vendor/ficl/dist/ficlplatform/makedef.py (nonexistent) +++ vendor/ficl/dist/ficlplatform/makedef.py (revision 282803) @@ -0,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() Property changes on: vendor/ficl/dist/ficlplatform/makedef.py ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/unix.c =================================================================== --- vendor/ficl/dist/ficlplatform/unix.c (nonexistent) +++ vendor/ficl/dist/ficlplatform/unix.c (revision 282803) @@ -0,0 +1,75 @@ +#include +#include +#include + +#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; +} + + Property changes on: vendor/ficl/dist/ficlplatform/unix.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/unix.h =================================================================== --- vendor/ficl/dist/ficlplatform/unix.h (nonexistent) +++ vendor/ficl/dist/ficlplatform/unix.h (revision 282803) @@ -0,0 +1,46 @@ +#include +#include + + +#define FICL_WANT_PLATFORM (1) + +#define FICL_PLATFORM_OS "unix" +#define FICL_PLATFORM_ARCHITECTURE "unknown" + +#define FICL_PLATFORM_BASIC_TYPES (1) +#if defined(__amd64__) +#define FICL_PLATFORM_ALIGNMENT (8) +#else +#define FICL_PLATFORM_ALIGNMENT (4) +#endif +#define FICL_PLATFORM_INLINE inline + +#define FICL_PLATFORM_HAS_FTRUNCATE (1) +#if defined(__amd64__) +#define FICL_PLATFORM_HAS_2INTEGER (0) +#else +#define FICL_PLATFORM_HAS_2INTEGER (1) +#endif + +typedef int8_t ficlInteger8; +typedef uint8_t ficlUnsigned8; +typedef int16_t ficlInteger16; +typedef uint16_t ficlUnsigned16; +typedef int32_t ficlInteger32; +typedef uint32_t ficlUnsigned32; +typedef int64_t ficlInteger64; +typedef uint64_t ficlUnsigned64; + +#if defined(__amd64__) +typedef ficlInteger64 ficlInteger; +typedef ficlUnsigned64 ficlUnsigned; +#else /* default */ +typedef intptr_t ficlInteger; +typedef uintptr_t ficlUnsigned; +#endif +typedef float ficlFloat; + +#if defined(FICL_PLATFORM_HAS_2INTEGER) && FICL_PLATFORM_HAS_2INTEGER +typedef ficlInteger64 ficl2Integer; +typedef ficlUnsigned64 ficl2Unsigned; +#endif Property changes on: vendor/ficl/dist/ficlplatform/unix.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/win32.c =================================================================== --- vendor/ficl/dist/ficlplatform/win32.c (nonexistent) +++ vendor/ficl/dist/ficlplatform/win32.c (revision 282803) @@ -0,0 +1,413 @@ +/* +** win32.c +** submitted to Ficl by Larry Hastings, larry@hastings.org +**/ + +#include +#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; +} Property changes on: vendor/ficl/dist/ficlplatform/win32.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficlplatform/win32.h =================================================================== --- vendor/ficl/dist/ficlplatform/win32.h (nonexistent) +++ vendor/ficl/dist/ficlplatform/win32.h (revision 282803) @@ -0,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 +#pragma warning(default: 4115) +#include + +#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 */ + Property changes on: vendor/ficl/dist/ficlplatform/win32.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/ficltokens.h =================================================================== --- vendor/ficl/dist/ficltokens.h (nonexistent) +++ vendor/ficl/dist/ficltokens.h (revision 282803) @@ -0,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 **") Property changes on: vendor/ficl/dist/ficltokens.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/fileaccess.c =================================================================== --- vendor/ficl/dist/fileaccess.c (revision 282802) +++ vendor/ficl/dist/fileaccess.c (revision 282803) @@ -1,423 +1,387 @@ #include #include #include #include #include -#include #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) +static void pushIor(ficlVm *vm, int success) { int ior; if (success) ior = 0; else ior = errno; - stackPushINT(pVM->pStack, ior); + ficlStackPushInteger(vm->dataStack, ior); } -static void ficlFopen(FICL_VM *pVM, char *writeMode) /* ( c-addr u fam -- fileid ior ) */ +static void ficlFileOpen(ficlVm *vm, char *writeMode) /* ( c-addr u fam -- fileid ior ) */ { - int fam = stackPopINT(pVM->pStack); - int length = stackPopINT(pVM->pStack); - void *address = (void *)stackPopPtr(pVM->pStack); + int fam = ficlStackPopInteger(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); char mode[4]; FILE *f; - - char *filename = (char *)alloca(length + 1); + char *filename = (char *)malloc(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; + ficlStackPushPointer(vm->dataStack, NULL); + ficlStackPushInteger(vm->dataStack, EINVAL); + goto EXIT; 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); + ficlStackPushPointer(vm->dataStack, NULL); else { - ficlFILE *ff = (ficlFILE *)malloc(sizeof(ficlFILE)); + ficlFile *ff = (ficlFile *)malloc(sizeof(ficlFile)); strcpy(ff->filename, filename); ff->f = f; - stackPushPtr(pVM->pStack, ff); + ficlStackPushPointer(vm->dataStack, ff); fseek(f, 0, SEEK_SET); } - pushIor(pVM, f != NULL); + pushIor(vm, f != NULL); + +EXIT: + free(filename); } -static void ficlOpenFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */ +static void ficlPrimitiveOpenFile(ficlVm *vm) /* ( c-addr u fam -- fileid ior ) */ { - ficlFopen(pVM, "a"); + ficlFileOpen(vm, "a"); } -static void ficlCreateFile(FICL_VM *pVM) /* ( c-addr u fam -- fileid ior ) */ +static void ficlPrimitiveCreateFile(ficlVm *vm) /* ( c-addr u fam -- fileid ior ) */ { - ficlFopen(pVM, "w"); + ficlFileOpen(vm, "w"); } -static int closeFiclFILE(ficlFILE *ff) /* ( fileid -- ior ) */ +static int ficlFileClose(ficlFile *ff) /* ( fileid -- ior ) */ { FILE *f = ff->f; free(ff); return !fclose(f); } -static void ficlCloseFile(FICL_VM *pVM) /* ( fileid -- ior ) */ +static void ficlPrimitiveCloseFile(ficlVm *vm) /* ( fileid -- ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - pushIor(pVM, closeFiclFILE(ff)); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + pushIor(vm, ficlFileClose(ff)); } -static void ficlDeleteFile(FICL_VM *pVM) /* ( c-addr u -- ior ) */ +static void ficlPrimitiveDeleteFile(ficlVm *vm) /* ( c-addr u -- ior ) */ { - int length = stackPopINT(pVM->pStack); - void *address = (void *)stackPopPtr(pVM->pStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); - char *filename = (char *)alloca(length + 1); + char *filename = (char *)malloc(length + 1); memcpy(filename, address, length); filename[length] = 0; - pushIor(pVM, !unlink(filename)); + pushIor(vm, !unlink(filename)); + free(filename); } -static void ficlRenameFile(FICL_VM *pVM) /* ( c-addr1 u1 c-addr2 u2 -- ior ) */ +static void ficlPrimitiveRenameFile(ficlVm *vm) /* ( 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); + length = ficlStackPopInteger(vm->dataStack); + address = (void *)ficlStackPopPointer(vm->dataStack); + to = (char *)malloc(length + 1); memcpy(to, address, length); to[length] = 0; - length = stackPopINT(pVM->pStack); - address = (void *)stackPopPtr(pVM->pStack); + length = ficlStackPopInteger(vm->dataStack); + address = (void *)ficlStackPopPointer(vm->dataStack); - from = (char *)alloca(length + 1); + from = (char *)malloc(length + 1); memcpy(from, address, length); from[length] = 0; - pushIor(pVM, !rename(from, to)); + pushIor(vm, !rename(from, to)); + + free(from); + free(to); } -static void ficlFileStatus(FICL_VM *pVM) /* ( c-addr u -- x ior ) */ +static void ficlPrimitiveFileStatus(ficlVm *vm) /* ( c-addr u -- x ior ) */ { - struct stat statbuf; + int status; + int ior; + + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); - int length = stackPopINT(pVM->pStack); - void *address = (void *)stackPopPtr(pVM->pStack); - - char *filename = (char *)alloca(length + 1); + char *filename = (char *)malloc(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); - } + ior = ficlFileStatus(filename, &status); + free(filename); + + ficlStackPushInteger(vm->dataStack, status); + ficlStackPushInteger(vm->dataStack, ior); } -static void ficlFilePosition(FICL_VM *pVM) /* ( fileid -- ud ior ) */ +static void ficlPrimitiveFilePosition(ficlVm *vm) /* ( fileid -- ud ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); long ud = ftell(ff->f); - stackPushINT(pVM->pStack, ud); - pushIor(pVM, ud != -1); + ficlStackPushInteger(vm->dataStack, ud); + pushIor(vm, ud != -1); } -static long fileSize(FILE *f) +static void ficlPrimitiveFileSize(ficlVm *vm) /* ( fileid -- ud ior ) */ { - struct stat statbuf; - statbuf.st_size = -1; - if (fstat(fileno(f), &statbuf) != 0) - return -1; - return statbuf.st_size; + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + long ud = ficlFileSize(ff); + ficlStackPushInteger(vm->dataStack, ud); + pushIor(vm, ud != -1); } -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 ) */ +static void ficlPrimitiveIncludeFile(ficlVm *vm) /* ( i*x fileid -- j*x ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - CELL id = pVM->sourceID; - int result = VM_OUTOFTEXT; + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + ficlCell id = vm->sourceId; + int except = FICL_VM_STATUS_OUT_OF_TEXT; long currentPosition, totalSize; long size; - pVM->sourceID.p = (void *)ff; + ficlString s; + vm->sourceId.p = (void *)ff; currentPosition = ftell(ff->f); - totalSize = fileSize(ff->f); + totalSize = ficlFileSize(ff); 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; - } + { + FICL_STRING_SET_POINTER(s, buffer); + FICL_STRING_SET_LENGTH(s, size); + except = ficlVmExecuteString(vm, s); + } } -#endif /* 0 */ + + if ((except < 0) && (except != FICL_VM_STATUS_OUT_OF_TEXT)) + ficlVmThrow(vm, except); + /* ** Pass an empty line with SOURCE-ID == -1 to flush ** any pending REFILLs (as required by FILE wordset) */ - pVM->sourceID.i = -1; - ficlExec(pVM, ""); + vm->sourceId.i = -1; + FICL_STRING_SET_FROM_CSTRING(s, ""); + ficlVmExecuteString(vm, s); - pVM->sourceID = id; - closeFiclFILE(ff); + vm->sourceId = id; + ficlFileClose(ff); } -static void ficlReadFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 ior ) */ +static void ficlPrimitiveReadFile(ficlVm *vm) /* ( c-addr u1 fileid -- u2 ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - int length = stackPopINT(pVM->pStack); - void *address = (void *)stackPopPtr(pVM->pStack); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); int result; clearerr(ff->f); result = fread(address, 1, length, ff->f); - stackPushINT(pVM->pStack, result); - pushIor(pVM, ferror(ff->f) == 0); + ficlStackPushInteger(vm->dataStack, result); + pushIor(vm, ferror(ff->f) == 0); } -static void ficlReadLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- u2 flag ior ) */ +static void ficlPrimitiveReadLine(ficlVm *vm) /* ( c-addr u1 fileid -- u2 flag ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - int length = stackPopINT(pVM->pStack); - char *address = (char *)stackPopPtr(pVM->pStack); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + char *address = (char *)ficlStackPopPointer(vm->dataStack); int error; int flag; if (feof(ff->f)) { - stackPushINT(pVM->pStack, -1); - stackPushINT(pVM->pStack, 0); - stackPushINT(pVM->pStack, 0); + ficlStackPushInteger(vm->dataStack, -1); + ficlStackPushInteger(vm->dataStack, 0); + ficlStackPushInteger(vm->dataStack, 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); + ficlStackPushInteger(vm->dataStack, -1); + ficlStackPushInteger(vm->dataStack, 0); + ficlStackPushInteger(vm->dataStack, 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 */ + ficlStackPushInteger(vm->dataStack, length); + ficlStackPushInteger(vm->dataStack, flag); + ficlStackPushInteger(vm->dataStack, 0); /* ior */ } -static void ficlWriteFile(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */ +static void ficlPrimitiveWriteFile(ficlVm *vm) /* ( c-addr u1 fileid -- ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - int length = stackPopINT(pVM->pStack); - void *address = (void *)stackPopPtr(pVM->pStack); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + int length = ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); clearerr(ff->f); fwrite(address, 1, length, ff->f); - pushIor(pVM, ferror(ff->f) == 0); + pushIor(vm, ferror(ff->f) == 0); } -static void ficlWriteLine(FICL_VM *pVM) /* ( c-addr u1 fileid -- ior ) */ +static void ficlPrimitiveWriteLine(ficlVm *vm) /* ( 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); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + size_t length = (size_t)ficlStackPopInteger(vm->dataStack); + void *address = (void *)ficlStackPopPointer(vm->dataStack); clearerr(ff->f); if (fwrite(address, 1, length, ff->f) == length) fwrite("\n", 1, 1, ff->f); - pushIor(pVM, ferror(ff->f) == 0); + pushIor(vm, ferror(ff->f) == 0); } -static void ficlRepositionFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */ +static void ficlPrimitiveRepositionFile(ficlVm *vm) /* ( ud fileid -- ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - size_t ud = (size_t)stackPopINT(pVM->pStack); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + size_t ud = (size_t)ficlStackPopInteger(vm->dataStack); - pushIor(pVM, fseek(ff->f, ud, SEEK_SET) == 0); + pushIor(vm, fseek(ff->f, ud, SEEK_SET) == 0); } -static void ficlFlushFile(FICL_VM *pVM) /* ( fileid -- ior ) */ +static void ficlPrimitiveFlushFile(ficlVm *vm) /* ( fileid -- ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - pushIor(pVM, fflush(ff->f) == 0); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + pushIor(vm, fflush(ff->f) == 0); } -#if FICL_HAVE_FTRUNCATE +#if FICL_PLATFORM_HAS_FTRUNCATE -static void ficlResizeFile(FICL_VM *pVM) /* ( ud fileid -- ior ) */ +static void ficlPrimitiveResizeFile(ficlVm *vm) /* ( ud fileid -- ior ) */ { - ficlFILE *ff = (ficlFILE *)stackPopPtr(pVM->pStack); - size_t ud = (size_t)stackPopINT(pVM->pStack); + ficlFile *ff = (ficlFile *)ficlStackPopPointer(vm->dataStack); + size_t ud = (size_t)ficlStackPopInteger(vm->dataStack); - pushIor(pVM, ftruncate(fileno(ff->f), ud) == 0); + pushIor(vm, ficlFileTruncate(ff, ud) == 0); } -#endif /* FICL_HAVE_FTRUNCATE */ +#endif /* FICL_PLATFORM_HAS_FTRUNCATE */ #endif /* FICL_WANT_FILE */ -void ficlCompileFile(FICL_SYSTEM *pSys) +void ficlSystemCompileFile(ficlSystem *system) { -#if FICL_WANT_FILE - FICL_DICT *dp = pSys->dp; - assert(dp); +#if !FICL_WANT_FILE + FICL_IGNORE(system); +#else + ficlDictionary *dictionary = ficlSystemGetDictionary(system); + ficlDictionary *environment = ficlSystemGetEnvironment(system); - 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); + FICL_SYSTEM_ASSERT(system, dictionary); + FICL_SYSTEM_ASSERT(system, environment); - dictAppendWord(dp, "delete-file", ficlDeleteFile, FW_DEFAULT); - dictAppendWord(dp, "rename-file", ficlRenameFile, FW_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "create-file", ficlPrimitiveCreateFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "open-file", ficlPrimitiveOpenFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "close-file", ficlPrimitiveCloseFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "include-file", ficlPrimitiveIncludeFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "read-file", ficlPrimitiveReadFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "read-line", ficlPrimitiveReadLine, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "write-file", ficlPrimitiveWriteFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "write-line", ficlPrimitiveWriteLine, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "file-position", ficlPrimitiveFilePosition, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "file-size", ficlPrimitiveFileSize, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "reposition-file", ficlPrimitiveRepositionFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "file-status", ficlPrimitiveFileStatus, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "flush-file", ficlPrimitiveFlushFile, FICL_WORD_DEFAULT); -#ifdef FICL_HAVE_FTRUNCATE - dictAppendWord(dp, "resize-file", ficlResizeFile, FW_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "delete-file", ficlPrimitiveDeleteFile, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "rename-file", ficlPrimitiveRenameFile, FICL_WORD_DEFAULT); - ficlSetEnv(pSys, "file", FICL_TRUE); - ficlSetEnv(pSys, "file-ext", FICL_TRUE); -#endif /* FICL_HAVE_FTRUNCATE */ -#else - &pSys; -#endif /* FICL_WANT_FILE */ +#if FICL_PLATFORM_HAS_FTRUNCATE + ficlDictionarySetPrimitive(dictionary, "resize-file", ficlPrimitiveResizeFile, FICL_WORD_DEFAULT); + + ficlDictionarySetConstant(environment, "file", FICL_TRUE); + ficlDictionarySetConstant(environment, "file-ext", FICL_TRUE); +#else /* FICL_PLATFORM_HAS_FTRUNCATE */ + ficlDictionarySetConstant(environment, "file", FICL_FALSE); + ficlDictionarySetConstant(environment, "file-ext", FICL_FALSE); +#endif /* FICL_PLATFORM_HAS_FTRUNCATE */ + +#endif /* !FICL_WANT_FILE */ } Index: vendor/ficl/dist/float.c =================================================================== --- vendor/ficl/dist/float.c (revision 282802) +++ vendor/ficl/dist/float.c (revision 282803) @@ -1,1065 +1,469 @@ /******************************************************************* ** f l o a t . c ** Forth Inspired Command Language ** 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.8 2001-12-04 17:58:16-08 jsadler Exp jsadler $ +** $Id: float.c,v 1.10 2010/09/13 18:43:04 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 +** 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 +** 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 #include #include #include #include #include "ficl.h" #if FICL_WANT_FLOAT -/******************************************************************* -** Do float addition r1 + r2. -** f+ ( r1 r2 -- r ) -*******************************************************************/ -static void Fadd(FICL_VM *pVM) -{ - FICL_FLOAT f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 1); -#endif - - f = POPFLOAT(); - f += GETTOPF().f; - SETTOPF(f); -} - /******************************************************************* -** Do float subtraction r1 - r2. -** f- ( r1 r2 -- r ) +** Create a floating point constant. +** fconstant ( r -"name"- ) *******************************************************************/ -static void Fsub(FICL_VM *pVM) +static void ficlPrimitiveFConstant(ficlVm *vm) { - FICL_FLOAT f; + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + ficlString name = ficlVmGetWord(vm); -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 1); -#endif + FICL_STACK_CHECK(vm->floatStack, 1, 0); - f = POPFLOAT(); - f = GETTOPF().f - f; - SETTOPF(f); + ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionFConstantParen, FICL_WORD_DEFAULT); + ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->floatStack)); } -/******************************************************************* -** Do float multiplication r1 * r2. -** f* ( r1 r2 -- r ) -*******************************************************************/ -static void Fmul(FICL_VM *pVM) -{ - FICL_FLOAT f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 1); -#endif - - f = POPFLOAT(); - f *= GETTOPF().f; - SETTOPF(f); -} - -/******************************************************************* -** Do float negation. -** fnegate ( r -- r ) -*******************************************************************/ -static void Fnegate(FICL_VM *pVM) +ficlWord *ficlDictionaryAppendFConstant(ficlDictionary *dictionary, char *name, float value) { - FICL_FLOAT f; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 1); -#endif - - f = -GETTOPF().f; - SETTOPF(f); + ficlString s; + FICL_STRING_SET_FROM_CSTRING(s, name); + return ficlDictionaryAppendConstantInstruction(dictionary, s, ficlInstructionFConstantParen, *(ficlInteger *)(&value)); } -/******************************************************************* -** Do float division r1 / r2. -** f/ ( r1 r2 -- r ) -*******************************************************************/ -static void Fdiv(FICL_VM *pVM) -{ - FICL_FLOAT f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 1); -#endif - - f = POPFLOAT(); - f = GETTOPF().f / f; - SETTOPF(f); -} - -/******************************************************************* -** Do float + integer r + n. -** f+i ( r n -- r ) -*******************************************************************/ -static void Faddi(FICL_VM *pVM) +ficlWord *ficlDictionarySetFConstant(ficlDictionary *dictionary, char *name, float value) { - FICL_FLOAT f; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 1); - vmCheckStack(pVM, 1, 0); -#endif - - f = (FICL_FLOAT)POPINT(); - f += GETTOPF().f; - SETTOPF(f); + ficlString s; + FICL_STRING_SET_FROM_CSTRING(s, name); + return ficlDictionarySetConstantInstruction(dictionary, s, ficlInstructionFConstantParen, *(ficlInteger *)(&value)); } -/******************************************************************* -** Do float - integer r - n. -** f-i ( r n -- r ) -*******************************************************************/ -static void Fsubi(FICL_VM *pVM) -{ - FICL_FLOAT f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 1); - vmCheckStack(pVM, 1, 0); -#endif - f = GETTOPF().f; - f -= (FICL_FLOAT)POPINT(); - SETTOPF(f); -} -/******************************************************************* -** Do float * integer r * n. -** f*i ( r n -- r ) -*******************************************************************/ -static void Fmuli(FICL_VM *pVM) +static void ficlPrimitiveF2Constant(ficlVm *vm) { - FICL_FLOAT f; + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + ficlString name = ficlVmGetWord(vm); -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 1); - vmCheckStack(pVM, 1, 0); -#endif + FICL_STACK_CHECK(vm->floatStack, 2, 0); - f = (FICL_FLOAT)POPINT(); - f *= GETTOPF().f; - SETTOPF(f); + ficlDictionaryAppendWord(dictionary, name, (ficlPrimitive)ficlInstructionF2ConstantParen, FICL_WORD_DEFAULT); + ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->floatStack)); + ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->floatStack)); } -/******************************************************************* -** Do float / integer r / n. -** f/i ( r n -- r ) -*******************************************************************/ -static void Fdivi(FICL_VM *pVM) -{ - FICL_FLOAT f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 1); - vmCheckStack(pVM, 1, 0); -#endif - - f = GETTOPF().f; - f /= (FICL_FLOAT)POPINT(); - SETTOPF(f); -} - -/******************************************************************* -** Do integer - float n - r. -** i-f ( n r -- r ) -*******************************************************************/ -static void isubf(FICL_VM *pVM) +ficlWord *ficlDictionaryAppendF2Constant(ficlDictionary *dictionary, char *name, double value) { - FICL_FLOAT f; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 1); - vmCheckStack(pVM, 1, 0); -#endif - - f = (FICL_FLOAT)POPINT(); - f -= GETTOPF().f; - SETTOPF(f); + ficlString s; + FICL_STRING_SET_FROM_CSTRING(s, name); + return ficlDictionaryAppend2ConstantInstruction(dictionary, s, ficlInstructionF2ConstantParen, *(ficl2Integer *)(&value)); } -/******************************************************************* -** Do integer / float n / r. -** i/f ( n r -- r ) -*******************************************************************/ -static void idivf(FICL_VM *pVM) -{ - FICL_FLOAT f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1,1); - vmCheckStack(pVM, 1, 0); -#endif - - f = (FICL_FLOAT)POPINT(); - f /= GETTOPF().f; - SETTOPF(f); -} - -/******************************************************************* -** Do integer to float conversion. -** int>float ( n -- r ) -*******************************************************************/ -static void itof(FICL_VM *pVM) +ficlWord *ficlDictionarySetF2Constant(ficlDictionary *dictionary, char *name, double value) { - float f; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); - vmCheckFStack(pVM, 0, 1); -#endif - - f = (float)POPINT(); - PUSHFLOAT(f); + ficlString s; + FICL_STRING_SET_FROM_CSTRING(s, name); + return ficlDictionarySet2ConstantInstruction(dictionary, s, ficlInstructionF2ConstantParen, *(ficl2Integer *)(&value)); } -/******************************************************************* -** Do float to integer conversion. -** float>int ( r -- n ) -*******************************************************************/ -static void Ftoi(FICL_VM *pVM) -{ - FICL_INT i; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); - vmCheckFStack(pVM, 1, 0); -#endif - - i = (FICL_INT)POPFLOAT(); - PUSHINT(i); -} - /******************************************************************* -** Floating point constant execution word. -*******************************************************************/ -void FconstantParen(FICL_VM *pVM) -{ - FICL_WORD *pFW = pVM->runningWord; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 0, 1); -#endif - - PUSHFLOAT(pFW->param[0].f); -} - -/******************************************************************* -** Create a floating point constant. -** fconstant ( r -"name"- ) -*******************************************************************/ -static void Fconstant(FICL_VM *pVM) -{ - FICL_DICT *dp = vmGetDict(pVM); - STRINGINFO si = vmGetWord(pVM); - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); -#endif - - dictAppendWord2(dp, si, FconstantParen, FW_DEFAULT); - dictAppendCell(dp, stackPop(pVM->fStack)); -} - -/******************************************************************* ** Display a float in decimal format. ** f. ( r -- ) *******************************************************************/ -static void FDot(FICL_VM *pVM) +static void ficlPrimitiveFDot(ficlVm *vm) { float f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); -#endif + FICL_STACK_CHECK(vm->floatStack, 1, 0); - f = POPFLOAT(); - sprintf(pVM->pad,"%#f ",f); - vmTextOut(pVM, pVM->pad, 0); + f = ficlStackPopFloat(vm->floatStack); + sprintf(vm->pad,"%#f ",f); + ficlVmTextOut(vm, vm->pad); } /******************************************************************* ** Display a float in engineering format. ** fe. ( r -- ) *******************************************************************/ -static void EDot(FICL_VM *pVM) +static void ficlPrimitiveEDot(ficlVm *vm) { float f; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); -#endif + FICL_STACK_CHECK(vm->floatStack, 1, 0); - f = POPFLOAT(); - sprintf(pVM->pad,"%#e ",f); - vmTextOut(pVM, pVM->pad, 0); + f = ficlStackPopFloat(vm->floatStack); + sprintf(vm->pad,"%#e ",f); + ficlVmTextOut(vm, vm->pad); } /************************************************************************** d i s p l a y FS t a c k ** Display the parameter stack (code for "f.s") ** f.s ( -- ) **************************************************************************/ -static void displayFStack(FICL_VM *pVM) +struct stackContext { - int d = stackDepth(pVM->fStack); - int i; - CELL *pCell; + ficlVm *vm; + int count; +}; - vmCheckFStack(pVM, 0, 0); - - vmTextOut(pVM, "F:", 0); - - if (d == 0) - vmTextOut(pVM, "[0]", 0); - else - { - ltoa(d, &pVM->pad[1], pVM->base); - pVM->pad[0] = '['; - strcat(pVM->pad,"] "); - vmTextOut(pVM,pVM->pad,0); - - pCell = pVM->fStack->sp - d; - for (i = 0; i < d; i++) - { - sprintf(pVM->pad,"%#f ",(*pCell++).f); - vmTextOut(pVM,pVM->pad,0); - } - } -} - -/******************************************************************* -** Do float stack depth. -** fdepth ( -- n ) -*******************************************************************/ -static void Fdepth(FICL_VM *pVM) +static ficlInteger ficlFloatStackDisplayCallback(void *c, ficlCell *cell) { - int i; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - - i = stackDepth(pVM->fStack); - PUSHINT(i); + struct stackContext *context = (struct stackContext *)c; + char buffer[64]; + sprintf(buffer, "[0x%08x %3d] %16f (0x%08x)\n", cell, context->count++, (double)(cell->f), cell->i); + ficlVmTextOut(context->vm, buffer); + return FICL_TRUE; } -/******************************************************************* -** Do float stack drop. -** fdrop ( r -- ) -*******************************************************************/ -static void Fdrop(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); -#endif - DROPF(1); -} -/******************************************************************* -** Do float stack 2drop. -** f2drop ( r r -- ) -*******************************************************************/ -static void FtwoDrop(FICL_VM *pVM) +void ficlVmDisplayFloatStack(ficlVm *vm) { -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 0); -#endif - - DROPF(2); + struct stackContext context; + context.vm = vm; + context.count = 0; + ficlStackDisplay(vm->floatStack, ficlFloatStackDisplayCallback, &context); + return; } -/******************************************************************* -** Do float stack dup. -** fdup ( r -- r r ) -*******************************************************************/ -static void Fdup(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 2); -#endif - PICKF(0); -} /******************************************************************* -** Do float stack 2dup. -** f2dup ( r1 r2 -- r1 r2 r1 r2 ) +** Do float stack depth. +** fdepth ( -- n ) *******************************************************************/ -static void FtwoDup(FICL_VM *pVM) +static void ficlPrimitiveFDepth(ficlVm *vm) { -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 4); -#endif + int i; - PICKF(1); - PICKF(1); -} + FICL_STACK_CHECK(vm->dataStack, 0, 1); -/******************************************************************* -** Do float stack over. -** fover ( r1 r2 -- r1 r2 r1 ) -*******************************************************************/ -static void Fover(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 3); -#endif - - PICKF(1); + i = ficlStackDepth(vm->floatStack); + ficlStackPushInteger(vm->dataStack, i); } /******************************************************************* -** Do float stack 2over. -** f2over ( r1 r2 r3 -- r1 r2 r3 r1 r2 ) -*******************************************************************/ -static void FtwoOver(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 4, 6); -#endif - - PICKF(3); - PICKF(3); -} - -/******************************************************************* -** Do float stack pick. -** fpick ( n -- r ) -*******************************************************************/ -static void Fpick(FICL_VM *pVM) -{ - CELL c = POP(); - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, c.i+1, c.i+2); -#endif - - PICKF(c.i); -} - -/******************************************************************* -** Do float stack ?dup. -** f?dup ( r -- r ) -*******************************************************************/ -static void FquestionDup(FICL_VM *pVM) -{ - CELL c; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 2); -#endif - - c = GETTOPF(); - if (c.f != 0) - PICKF(0); -} - -/******************************************************************* -** Do float stack roll. -** froll ( n -- ) -*******************************************************************/ -static void Froll(FICL_VM *pVM) -{ - int i = POP().i; - i = (i > 0) ? i : 0; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, i+1, i+1); -#endif - - ROLLF(i); -} - -/******************************************************************* -** Do float stack -roll. -** f-roll ( n -- ) -*******************************************************************/ -static void FminusRoll(FICL_VM *pVM) -{ - int i = POP().i; - i = (i > 0) ? i : 0; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, i+1, i+1); -#endif - - ROLLF(-i); -} - -/******************************************************************* -** Do float stack rot. -** frot ( r1 r2 r3 -- r2 r3 r1 ) -*******************************************************************/ -static void Frot(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 3, 3); -#endif - - ROLLF(2); -} - -/******************************************************************* -** Do float stack -rot. -** f-rot ( r1 r2 r3 -- r3 r1 r2 ) -*******************************************************************/ -static void Fminusrot(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 3, 3); -#endif - - ROLLF(-2); -} - -/******************************************************************* -** Do float stack swap. -** fswap ( r1 r2 -- r2 r1 ) -*******************************************************************/ -static void Fswap(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 2); -#endif - - ROLLF(1); -} - -/******************************************************************* -** Do float stack 2swap -** f2swap ( r1 r2 r3 r4 -- r3 r4 r1 r2 ) -*******************************************************************/ -static void FtwoSwap(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 4, 4); -#endif - - ROLLF(3); - ROLLF(3); -} - -/******************************************************************* -** Get a floating point number from a variable. -** f@ ( n -- r ) -*******************************************************************/ -static void Ffetch(FICL_VM *pVM) -{ - CELL *pCell; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 0, 1); - vmCheckStack(pVM, 1, 0); -#endif - - pCell = (CELL *)POPPTR(); - PUSHFLOAT(pCell->f); -} - -/******************************************************************* -** Store a floating point number into a variable. -** f! ( r n -- ) -*******************************************************************/ -static void Fstore(FICL_VM *pVM) -{ - CELL *pCell; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); - vmCheckStack(pVM, 1, 0); -#endif - - pCell = (CELL *)POPPTR(); - pCell->f = POPFLOAT(); -} - -/******************************************************************* -** Add a floating point number to contents of a variable. -** f+! ( r n -- ) -*******************************************************************/ -static void FplusStore(FICL_VM *pVM) -{ - CELL *pCell; - -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 0); - vmCheckFStack(pVM, 1, 0); -#endif - - pCell = (CELL *)POPPTR(); - pCell->f += POPFLOAT(); -} - -/******************************************************************* -** Floating point literal execution word. -*******************************************************************/ -static void fliteralParen(FICL_VM *pVM) -{ -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 0, 1); -#endif - - PUSHFLOAT(*(float*)(pVM->ip)); - vmBranchRelative(pVM, 1); -} - -/******************************************************************* ** Compile a floating point literal. *******************************************************************/ -static void fliteralIm(FICL_VM *pVM) +static void ficlPrimitiveFLiteralImmediate(ficlVm *vm) { - FICL_DICT *dp = vmGetDict(pVM); - FICL_WORD *pfLitParen = ficlLookup(pVM->pSys, "(fliteral)"); + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + ficlCell cell; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); -#endif - dictAppendCell(dp, LVALUEtoCELL(pfLitParen)); - dictAppendCell(dp, stackPop(pVM->fStack)); -} + FICL_STACK_CHECK(vm->floatStack, 1, 0); -/******************************************************************* -** Do float 0= comparison r = 0.0. -** f0= ( r -- T/F ) -*******************************************************************/ -static void FzeroEquals(FICL_VM *pVM) -{ - CELL c; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); /* Make sure something on float stack. */ - vmCheckStack(pVM, 0, 1); /* Make sure room for result. */ -#endif - - c.i = FICL_BOOL(POPFLOAT() == 0); - PUSH(c); + cell = ficlStackPop(vm->floatStack); + if (cell.f == 1.0f) + { + ficlDictionaryAppendUnsigned(dictionary, ficlInstructionF1); + } + else if (cell.f == 0.0f) + { + ficlDictionaryAppendUnsigned(dictionary, ficlInstructionF0); + } + else if (cell.f == -1.0f) + { + ficlDictionaryAppendUnsigned(dictionary, ficlInstructionFNeg1); + } + else + { + ficlDictionaryAppendUnsigned(dictionary, ficlInstructionFLiteralParen); + ficlDictionaryAppendCell(dictionary, cell); + } } -/******************************************************************* -** Do float 0< comparison r < 0.0. -** f0< ( r -- T/F ) -*******************************************************************/ -static void FzeroLess(FICL_VM *pVM) -{ - CELL c; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); /* Make sure something on float stack. */ - vmCheckStack(pVM, 0, 1); /* Make sure room for result. */ -#endif - - c.i = FICL_BOOL(POPFLOAT() < 0); - PUSH(c); -} - -/******************************************************************* -** Do float 0> comparison r > 0.0. -** f0> ( r -- T/F ) -*******************************************************************/ -static void FzeroGreater(FICL_VM *pVM) -{ - CELL c; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); - vmCheckStack(pVM, 0, 1); -#endif - - c.i = FICL_BOOL(POPFLOAT() > 0); - PUSH(c); -} - -/******************************************************************* -** Do float = comparison r1 = r2. -** f= ( r1 r2 -- T/F ) -*******************************************************************/ -static void FisEqual(FICL_VM *pVM) -{ - float x, y; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 0); - vmCheckStack(pVM, 0, 1); -#endif - - x = POPFLOAT(); - y = POPFLOAT(); - PUSHINT(FICL_BOOL(x == y)); -} - -/******************************************************************* -** Do float < comparison r1 < r2. -** f< ( r1 r2 -- T/F ) -*******************************************************************/ -static void FisLess(FICL_VM *pVM) -{ - float x, y; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 0); - vmCheckStack(pVM, 0, 1); -#endif - - y = POPFLOAT(); - x = POPFLOAT(); - PUSHINT(FICL_BOOL(x < y)); -} - -/******************************************************************* -** Do float > comparison r1 > r2. -** f> ( r1 r2 -- T/F ) -*******************************************************************/ -static void FisGreater(FICL_VM *pVM) -{ - float x, y; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 2, 0); - vmCheckStack(pVM, 0, 1); -#endif - - y = POPFLOAT(); - x = POPFLOAT(); - PUSHINT(FICL_BOOL(x > y)); -} - - -/******************************************************************* -** Move float to param stack (assumes they both fit in a single CELL) -** f>s -*******************************************************************/ -static void FFrom(FICL_VM *pVM) -{ - CELL c; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 1, 0); - vmCheckStack(pVM, 0, 1); -#endif - - c = stackPop(pVM->fStack); - stackPush(pVM->pStack, c); - return; -} - -static void ToF(FICL_VM *pVM) -{ - CELL c; - -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 0, 1); - vmCheckStack(pVM, 1, 0); -#endif - - c = stackPop(pVM->pStack); - stackPush(pVM->fStack, c); - return; -} - - /************************************************************************** F l o a t P a r s e S t a t e ** Enum to determine the current segement of a floating point number ** being parsed. **************************************************************************/ #define NUMISNEG 1 #define EXPISNEG 2 typedef enum _floatParseState { FPS_START, FPS_ININT, FPS_INMANT, FPS_STARTEXP, FPS_INEXP } FloatParseState; /************************************************************************** f i c l P a r s e F l o a t N u m b e r -** pVM -- Virtual Machine pointer. -** si -- String to parse. +** vm -- Virtual Machine pointer. +** s -- String to parse. ** Returns 1 if successful, 0 if not. **************************************************************************/ -int ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si ) +int ficlVmParseFloatNumber( ficlVm *vm, ficlString s) { - unsigned char ch, digit; - char *cp; - FICL_COUNT count; + unsigned char c; + unsigned char digit; + char *trace; + ficlUnsigned length; float power; float accum = 0.0f; float mant = 0.1f; - FICL_INT exponent = 0; + ficlInteger exponent = 0; char flag = 0; FloatParseState estate = FPS_START; -#if FICL_ROBUST > 1 - vmCheckFStack(pVM, 0, 1); -#endif + FICL_STACK_CHECK(vm->floatStack, 0, 1); + + /* ** floating point numbers only allowed in base 10 */ - if (pVM->base != 10) + if (vm->base != 10) return(0); - cp = SI_PTR(si); - count = (FICL_COUNT)SI_COUNT(si); + trace = FICL_STRING_GET_POINTER(s); + length = FICL_STRING_GET_LENGTH(s); /* Loop through the string's characters. */ - while ((count--) && ((ch = *cp++) != 0)) + while ((length--) && ((c = *trace++) != 0)) { switch (estate) { /* At start of the number so look for a sign. */ case FPS_START: { estate = FPS_ININT; - if (ch == '-') + if (c == '-') { flag |= NUMISNEG; break; } - if (ch == '+') + if (c == '+') { break; } } /* Note! Drop through to FPS_ININT */ /* **Converting integer part of number. ** Only allow digits, decimal and 'E'. */ case FPS_ININT: { - if (ch == '.') + if (c == '.') { estate = FPS_INMANT; } - else if ((ch == 'e') || (ch == 'E')) + else if ((c == 'e') || (c == 'E')) { estate = FPS_STARTEXP; } else { - digit = (unsigned char)(ch - '0'); + digit = (unsigned char)(c - '0'); if (digit > 9) return(0); accum = accum * 10 + digit; } break; } /* ** Processing the fraction part of number. ** Only allow digits and 'E' */ case FPS_INMANT: { - if ((ch == 'e') || (ch == 'E')) + if ((c == 'e') || (c == 'E')) { estate = FPS_STARTEXP; } else { - digit = (unsigned char)(ch - '0'); + digit = (unsigned char)(c - '0'); if (digit > 9) return(0); accum += digit * mant; mant *= 0.1f; } break; } /* Start processing the exponent part of number. */ /* Look for sign. */ case FPS_STARTEXP: { estate = FPS_INEXP; - if (ch == '-') + if (c == '-') { flag |= EXPISNEG; break; } - else if (ch == '+') + else if (c == '+') { break; } } /* Note! Drop through to FPS_INEXP */ /* ** Processing the exponent part of number. ** Only allow digits. */ case FPS_INEXP: { - digit = (unsigned char)(ch - '0'); + digit = (unsigned char)(c - '0'); if (digit > 9) return(0); exponent = exponent * 10 + digit; break; } } } /* If parser never made it to the exponent this is not a float. */ if (estate < FPS_STARTEXP) return(0); /* Set the sign of the number. */ if (flag & NUMISNEG) accum = -accum; /* If exponent is not 0 then adjust number by it. */ if (exponent != 0) { /* Determine if exponent is negative. */ if (flag & EXPISNEG) { exponent = -exponent; } /* power = 10^x */ power = (float)pow(10.0, exponent); accum *= power; } - PUSHFLOAT(accum); - if (pVM->state == COMPILE) - fliteralIm(pVM); + ficlStackPushFloat(vm->floatStack, accum); + if (vm->state == FICL_VM_STATE_COMPILE) + ficlPrimitiveFLiteralImmediate(vm); return(1); } + +#if FICL_WANT_LOCALS + +static void ficlPrimitiveFLocalParen(ficlVm *vm) +{ + ficlLocalParen(vm, 0, 1); +} + +static void ficlPrimitiveF2LocalParen(ficlVm *vm) +{ + ficlLocalParen(vm, 1, 1); +} + +#endif /* FICL_WANT_LOCALS */ + #endif /* FICL_WANT_FLOAT */ /************************************************************************** ** Add float words to a system's dictionary. -** pSys -- Pointer to the FICL sytem to add float words to. +** system -- Pointer to the Ficl sytem to add float words to. **************************************************************************/ -void ficlCompileFloat(FICL_SYSTEM *pSys) +void ficlSystemCompileFloat(ficlSystem *system) { - FICL_DICT *dp = pSys->dp; - assert(dp); - #if FICL_WANT_FLOAT - dictAppendWord(dp, ">float", ToF, FW_DEFAULT); - /* d>f */ - dictAppendWord(dp, "f!", Fstore, FW_DEFAULT); - dictAppendWord(dp, "f*", Fmul, FW_DEFAULT); - dictAppendWord(dp, "f+", Fadd, FW_DEFAULT); - dictAppendWord(dp, "f-", Fsub, FW_DEFAULT); - dictAppendWord(dp, "f/", Fdiv, FW_DEFAULT); - dictAppendWord(dp, "f0<", FzeroLess, FW_DEFAULT); - dictAppendWord(dp, "f0=", FzeroEquals, FW_DEFAULT); - dictAppendWord(dp, "f<", FisLess, FW_DEFAULT); + ficlDictionary *dictionary = ficlSystemGetDictionary(system); + ficlDictionary *environment = ficlSystemGetEnvironment(system); + + FICL_SYSTEM_ASSERT(system, dictionary); + FICL_SYSTEM_ASSERT(system, environment); + + ficlDictionarySetPrimitive(dictionary, "fconstant", ficlPrimitiveFConstant, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "fvalue", ficlPrimitiveFConstant, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "f2constant", ficlPrimitiveF2Constant, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "f2value", ficlPrimitiveF2Constant, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "fdepth", ficlPrimitiveFDepth, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "fliteral", ficlPrimitiveFLiteralImmediate, FICL_WORD_IMMEDIATE); + ficlDictionarySetPrimitive(dictionary, "f.", ficlPrimitiveFDot, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "f.s", ficlVmDisplayFloatStack, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "fe.", ficlPrimitiveEDot, FICL_WORD_DEFAULT); + +#if FICL_WANT_LOCALS + ficlDictionarySetPrimitive(dictionary, "(flocal)", ficlPrimitiveFLocalParen, FICL_WORD_COMPILE_ONLY); + ficlDictionarySetPrimitive(dictionary, "(f2local)", ficlPrimitiveF2LocalParen, FICL_WORD_COMPILE_ONLY); +#endif /* FICL_WANT_LOCALS */ + /* + Missing words: + + d>f f>d - */ - dictAppendWord(dp, "f@", Ffetch, FW_DEFAULT); - /* falign faligned - */ - dictAppendWord(dp, "fconstant", Fconstant, FW_DEFAULT); - dictAppendWord(dp, "fdepth", Fdepth, FW_DEFAULT); - dictAppendWord(dp, "fdrop", Fdrop, FW_DEFAULT); - dictAppendWord(dp, "fdup", Fdup, FW_DEFAULT); - dictAppendWord(dp, "fliteral", fliteralIm, FW_IMMEDIATE); -/* float+ floats floor fmax fmin */ - dictAppendWord(dp, "f?dup", FquestionDup, FW_DEFAULT); - dictAppendWord(dp, "f=", FisEqual, FW_DEFAULT); - dictAppendWord(dp, "f>", FisGreater, FW_DEFAULT); - dictAppendWord(dp, "f0>", FzeroGreater, FW_DEFAULT); - dictAppendWord(dp, "f2drop", FtwoDrop, FW_DEFAULT); - dictAppendWord(dp, "f2dup", FtwoDup, FW_DEFAULT); - dictAppendWord(dp, "f2over", FtwoOver, FW_DEFAULT); - dictAppendWord(dp, "f2swap", FtwoSwap, FW_DEFAULT); - dictAppendWord(dp, "f+!", FplusStore, FW_DEFAULT); - dictAppendWord(dp, "f+i", Faddi, FW_DEFAULT); - dictAppendWord(dp, "f-i", Fsubi, FW_DEFAULT); - dictAppendWord(dp, "f*i", Fmuli, FW_DEFAULT); - dictAppendWord(dp, "f/i", Fdivi, FW_DEFAULT); - dictAppendWord(dp, "int>float", itof, FW_DEFAULT); - dictAppendWord(dp, "float>int", Ftoi, FW_DEFAULT); - dictAppendWord(dp, "f.", FDot, FW_DEFAULT); - dictAppendWord(dp, "f.s", displayFStack, FW_DEFAULT); - dictAppendWord(dp, "fe.", EDot, FW_DEFAULT); - dictAppendWord(dp, "fover", Fover, FW_DEFAULT); - dictAppendWord(dp, "fnegate", Fnegate, FW_DEFAULT); - dictAppendWord(dp, "fpick", Fpick, FW_DEFAULT); - dictAppendWord(dp, "froll", Froll, FW_DEFAULT); - dictAppendWord(dp, "frot", Frot, FW_DEFAULT); - dictAppendWord(dp, "fswap", Fswap, FW_DEFAULT); - dictAppendWord(dp, "i-f", isubf, FW_DEFAULT); - dictAppendWord(dp, "i/f", idivf, FW_DEFAULT); - dictAppendWord(dp, "float>", FFrom, FW_DEFAULT); - - dictAppendWord(dp, "f-roll", FminusRoll, FW_DEFAULT); - dictAppendWord(dp, "f-rot", Fminusrot, FW_DEFAULT); - dictAppendWord(dp, "(fliteral)", fliteralParen, FW_COMPILE); - - ficlSetEnv(pSys, "floating", FICL_FALSE); /* not all required words are present */ - ficlSetEnv(pSys, "floating-ext", FICL_FALSE); - ficlSetEnv(pSys, "floating-stack", FICL_DEFAULT_STACK); + ficlDictionarySetConstant(environment, "floating", FICL_FALSE); /* not all required words are present */ + ficlDictionarySetConstant(environment, "floating-ext", FICL_FALSE); + ficlDictionarySetConstant(environment, "floating-stack", system->stackSize); +#else /* FICL_WANT_FLOAT */ + /* get rid of unused parameter warning */ + system = NULL; #endif return; } - Index: vendor/ficl/dist/hash.c =================================================================== --- vendor/ficl/dist/hash.c (nonexistent) +++ vendor/ficl/dist/hash.c (revision 282803) @@ -0,0 +1,163 @@ +#include + +#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; +} + + Property changes on: vendor/ficl/dist/hash.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/lzcompress.c =================================================================== --- vendor/ficl/dist/lzcompress.c (nonexistent) +++ vendor/ficl/dist/lzcompress.c (revision 282803) @@ -0,0 +1,202 @@ +#include +#include +#include + +#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; + } + Property changes on: vendor/ficl/dist/lzcompress.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/lzuncompress.c =================================================================== --- vendor/ficl/dist/lzuncompress.c (nonexistent) +++ vendor/ficl/dist/lzuncompress.c (revision 282803) @@ -0,0 +1,94 @@ +#include +#include + +#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; + } Property changes on: vendor/ficl/dist/lzuncompress.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/main.c =================================================================== --- vendor/ficl/dist/main.c (nonexistent) +++ vendor/ficl/dist/main.c (revision 282803) @@ -0,0 +1,78 @@ +/* +** stub main for testing Ficl +** $Id: main.c,v 1.2 2010/09/10 09:01:28 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 +#include + +#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); + if (fgets(buffer, sizeof(buffer), stdin) == NULL) break; + returnValue = ficlVmEvaluate(vm, buffer); + } + + ficlSystemDestroy(system); + return 0; +} + Property changes on: vendor/ficl/dist/main.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/prefix.c =================================================================== --- vendor/ficl/dist/prefix.c (revision 282802) +++ vendor/ficl/dist/prefix.c (revision 282803) @@ -1,197 +1,178 @@ /******************************************************************* ** p r e f i x . c ** Forth Inspired Command Language ** Parser extensions for Ficl ** Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu) ** Created: April 2001 -** $Id: prefix.c,v 1.5 2001-12-04 17:58:13-08 jsadler Exp jsadler $ +** $Id: prefix.c,v 1.8 2010/09/13 18:43:04 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 +** 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 +** 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 #include #include "ficl.h" -#include "math64.h" /* ** (jws) revisions: ** A prefix is a word in a dedicated wordlist (name stored in list_name below) ** that is searched in a special way by the prefix parse step. When a prefix ** matches the beginning of an incoming token, push the non-prefix part of the ** token back onto the input stream and execute the prefix code. ** ** The parse step is called ficlParsePrefix. ** Storing prefix entries in the dictionary greatly simplifies ** the process of matching and dispatching prefixes, avoids the ** need to clean up a dynamically allocated prefix list when the system ** goes away, but still allows prefixes to be allocated at runtime. */ static char list_name[] = ""; /************************************************************************** f i c l P a r s e P r e f i x ** This is the parse step for prefixes - it checks an incoming word -** to see if it starts with a prefix, and if so runs the corrseponding +** to see if it starts with a prefix, and if so runs the corresponding ** code against the remainder of the word and returns true. **************************************************************************/ -int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si) +int ficlVmParsePrefix(ficlVm *vm, ficlString s) { int i; - FICL_HASH *pHash; - FICL_WORD *pFW = ficlLookup(pVM->pSys, list_name); + ficlHash *hash; + ficlWord *word = ficlSystemLookup(vm->callback.system, list_name); /* ** Make sure we found the prefix dictionary - otherwise silently fail ** If forth-wordlist is not in the search order, we won't find the prefixes. */ - if (!pFW) - return FICL_FALSE; + if (!word) + return 0; /* false */ - pHash = (FICL_HASH *)(pFW->param[0].p); + hash = (ficlHash *)(word->param[0].p); /* ** Walk the list looking for a match with the beginning of the incoming token */ - for (i = 0; i < (int)pHash->size; i++) + for (i = 0; i < (int)hash->size; i++) { - pFW = pHash->table[i]; - while (pFW != NULL) + word = hash->table[i]; + while (word != NULL) { int n; - n = pFW->nName; + n = word->length; /* ** If we find a match, adjust the TIB to give back the non-prefix characters ** and execute the prefix word. */ - if (!strincmp(SI_PTR(si), pFW->name, (FICL_UNS)n)) + if (!ficlStrincmp(FICL_STRING_GET_POINTER(s), word->name, (ficlUnsigned)n)) { /* (sadler) fixed off-by-one error when the token has no trailing space in the TIB */ - vmSetTibIndex(pVM, si.cp + n - pVM->tib.cp ); - vmExecute(pVM, pFW); + ficlVmSetTibIndex(vm, s.text + n - vm->tib.text); + ficlVmExecuteWord(vm, word); - return FICL_TRUE; + return 1; /* true */ } - pFW = pFW->link; + word = word->link; } } - return FICL_FALSE; + return 0; /* false */ } -static void tempBase(FICL_VM *pVM, int base) +static void ficlPrimitiveTempBase(ficlVm *vm) { - int oldbase = pVM->base; - STRINGINFO si = vmGetWord0(pVM); + int oldbase = vm->base; + ficlString number = ficlVmGetWord0(vm); + int base = ficlStackPopInteger(vm->dataStack); - pVM->base = base; - if (!ficlParseNumber(pVM, si)) - { - int i = SI_COUNT(si); - vmThrowErr(pVM, "%.*s not recognized", i, SI_PTR(si)); - } + vm->base = base; + if (!ficlVmParseNumber(vm, number)) + ficlVmThrowError(vm, "%.*s not recognized", FICL_STRING_GET_LENGTH(number), FICL_STRING_GET_POINTER(number)); - pVM->base = oldbase; + vm->base = oldbase; return; } -static void fTempBase(FICL_VM *pVM) -{ - int base = stackPopINT(pVM->pStack); - tempBase(pVM, base); - return; -} -static void prefixHex(FICL_VM *pVM) -{ - tempBase(pVM, 16); -} -static void prefixTen(FICL_VM *pVM) -{ - tempBase(pVM, 10); -} - - /************************************************************************** f i c l C o m p i l e P r e f i x ** Build prefix support into the dictionary and the parser ** Note: since prefixes always execute, they are effectively IMMEDIATE. ** If they need to generate code in compile state you must add ** this code explicitly. **************************************************************************/ -void ficlCompilePrefix(FICL_SYSTEM *pSys) +void ficlSystemCompilePrefix(ficlSystem *system) { - FICL_DICT *dp = pSys->dp; - FICL_HASH *pHash; - FICL_HASH *pPrevCompile = dp->pCompile; -#if (FICL_EXTENDED_PREFIX) - FICL_WORD *pFW; -#endif + ficlDictionary *dictionary = system->dictionary; + ficlHash *hash; /* ** Create a named wordlist for prefixes to reside in... ** Since we're doing a special kind of search, make it ** a single bucket hashtable - hashing does not help here. */ - pHash = dictCreateWordlist(dp, 1); - pHash->name = list_name; - dictAppendWord(dp, list_name, constantParen, FW_DEFAULT); - dictAppendCell(dp, LVALUEtoCELL(pHash)); + hash = ficlDictionaryCreateWordlist(dictionary, 1); + hash->name = list_name; + ficlDictionaryAppendConstantPointer(dictionary, list_name, hash); - /* - ** Put __tempbase in the forth-wordlist - */ - dictAppendWord(dp, "__tempbase", fTempBase, FW_DEFAULT); + /* + ** Put __tempbase in the forth-wordlist + */ + ficlDictionarySetPrimitive(dictionary, "__tempbase", ficlPrimitiveTempBase, FICL_WORD_DEFAULT); /* - ** Temporarily make the prefix list the compile wordlist so that - ** we can create some precompiled prefixes. + ** If you want to add some prefixes at compilation-time, copy this line to the top of this function: + ** + ficlHash *oldCompilationWordlist; + + ** + ** then copy this code to the bottom, just above the return: + ** + + oldCompilationWordlist = dictionary->compilationWordlist; + dictionary->compilationWordlist = hash; + ficlDictionarySetPrimitive(dictionary, YOUR WORD HERE, FICL_WORD_DEFAULT); + dictionary->compilationWordlist = oldCompilationWordlist; + + ** + ** and substitute in your own actual calls to ficlDictionarySetPrimitive() as needed. + ** + ** Or--better yet--do it in your own code, so you don't have to re-modify the Ficl + ** source code every time we cut a new release! */ - dp->pCompile = pHash; - dictAppendWord(dp, "0x", prefixHex, FW_DEFAULT); - dictAppendWord(dp, "0d", prefixTen, FW_DEFAULT); -#if (FICL_EXTENDED_PREFIX) - pFW = ficlLookup(pSys, "\\"); - if (pFW) - { - dictAppendWord(dp, "//", pFW->code, FW_DEFAULT); - } -#endif - dp->pCompile = pPrevCompile; return; } Index: vendor/ficl/dist/primitives.c =================================================================== --- vendor/ficl/dist/primitives.c (nonexistent) +++ vendor/ficl/dist/primitives.c (revision 282803) @@ -0,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.4 2010/09/13 18:43:04 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 +#include +#include +#include +#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 = 0; /* false */ + + int append = 1; /* 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((unsigned char)*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 = 1; /* true */ + case 'd': + case 'D': + { + int integer = ficlStackPopInteger(vm->dataStack); + if (unsignedInteger) + ficlUltoa(integer, scratch, base); + else + ficlLtoa(integer, scratch, base); + base = 10; + unsignedInteger = 0; /* false */ + source = scratch; + actualLength = strlen(scratch); + break; + } + case '%': + source = format; + actualLength = 1; + default: + continue; + } + } + + if (append) + { + if (!desiredLength) + desiredLength = actualLength; + if (desiredLength > bufferLength) + { + append = 0; /* 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 && FICL_TRUE); +} + + +/************************************************************************** + 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" -- ) +** 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); + ficlInteger 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 ( "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 ( "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: ( "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 "ccc" -- 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 ( 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" -- 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 -- ) "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, 0, 0); +} + +static void ficlPrimitiveDo2LocalIm(ficlVm *vm) +{ + ficlLocalParenIm(vm, 1, 0); +} + +#if FICL_WANT_FLOAT +static void ficlPrimitiveDoFLocalIm(ficlVm *vm) +{ + ficlLocalParenIm(vm, 0, 1); +} + +static void ficlPrimitiveDoF2LocalIm(ficlVm *vm) +{ + ficlLocalParenIm(vm, 1, 1); +} +#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, 0, 0); +} + +static void ficlPrimitive2LocalParen(ficlVm *vm) +{ + ficlLocalParen(vm, 1, 0); +} + + +#endif /* FICL_WANT_LOCALS */ + + +/************************************************************************** + t o V a l u e +** CORE EXT +** Interpretation: ( x "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; +} + Property changes on: vendor/ficl/dist/primitives.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/search.c =================================================================== --- vendor/ficl/dist/search.c (revision 282802) +++ vendor/ficl/dist/search.c (revision 282803) @@ -1,391 +1,399 @@ /******************************************************************* ** s e a r c h . c ** Forth Inspired Command Language ** 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 01:24:34-07 jsadler Exp jsadler $ +** $Id: search.c,v 1.10 2010/08/12 13:57:22 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 +** 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 +** 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 #include "ficl.h" -#include "math64.h" /************************************************************************** d e f i n i t i o n s ** SEARCH ( -- ) ** Make the compilation word list the same as the first word list in the ** search order. Specifies that the names of subsequent definitions will ** be placed in the compilation word list. Subsequent changes in the search ** order will not affect the compilation word list. **************************************************************************/ -static void definitions(FICL_VM *pVM) +static void ficlPrimitiveDefinitions(ficlVm *vm) { - FICL_DICT *pDict = vmGetDict(pVM); + ficlDictionary *dictionary = ficlVmGetDictionary(vm); - assert(pDict); - if (pDict->nLists < 1) + FICL_VM_ASSERT(vm, dictionary); + if (dictionary->wordlistCount < 1) { - vmThrowErr(pVM, "DEFINITIONS error - empty search order"); + ficlVmThrowError(vm, "DEFINITIONS error - empty search order"); } - pDict->pCompile = pDict->pSearch[pDict->nLists-1]; + dictionary->compilationWordlist = dictionary->wordlists[dictionary->wordlistCount-1]; return; } /************************************************************************** f o r t h - w o r d l i s t ** SEARCH ( -- wid ) ** Return wid, the identifier of the word list that includes all standard ** words provided by the implementation. This word list is initially the ** compilation word list and is part of the initial search order. **************************************************************************/ -static void forthWordlist(FICL_VM *pVM) +static void ficlPrimitiveForthWordlist(ficlVm *vm) { - FICL_HASH *pHash = vmGetDict(pVM)->pForthWords; - stackPushPtr(pVM->pStack, pHash); + ficlHash *hash = ficlVmGetDictionary(vm)->forthWordlist; + ficlStackPushPointer(vm->dataStack, hash); return; } /************************************************************************** g e t - c u r r e n t ** SEARCH ( -- wid ) ** Return wid, the identifier of the compilation word list. **************************************************************************/ -static void getCurrent(FICL_VM *pVM) +static void ficlPrimitiveGetCurrent(ficlVm *vm) { - ficlLockDictionary(TRUE); - stackPushPtr(pVM->pStack, vmGetDict(pVM)->pCompile); - ficlLockDictionary(FALSE); + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + ficlDictionaryLock(dictionary, FICL_TRUE); + ficlStackPushPointer(vm->dataStack, dictionary->compilationWordlist); + ficlDictionaryLock(dictionary, FICL_FALSE); return; } /************************************************************************** g e t - o r d e r ** SEARCH ( -- widn ... wid1 n ) ** Returns the number of word lists n in the search order and the word list ** identifiers widn ... wid1 identifying these word lists. wid1 identifies ** the word list that is searched first, and widn the word list that is ** searched last. The search order is unaffected. **************************************************************************/ -static void getOrder(FICL_VM *pVM) +static void ficlPrimitiveGetOrder(ficlVm *vm) { - FICL_DICT *pDict = vmGetDict(pVM); - int nLists = pDict->nLists; + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + int wordlistCount = dictionary->wordlistCount; int i; - ficlLockDictionary(TRUE); - for (i = 0; i < nLists; i++) + ficlDictionaryLock(dictionary, FICL_TRUE); + for (i = 0; i < wordlistCount; i++) { - stackPushPtr(pVM->pStack, pDict->pSearch[i]); + ficlStackPushPointer(vm->dataStack, dictionary->wordlists[i]); } - stackPushUNS(pVM->pStack, nLists); - ficlLockDictionary(FALSE); + ficlStackPushUnsigned(vm->dataStack, wordlistCount); + ficlDictionaryLock(dictionary, FICL_FALSE); return; } /************************************************************************** s e a r c h - w o r d l i s t ** SEARCH ( c-addr u wid -- 0 | xt 1 | xt -1 ) ** Find the definition identified by the string c-addr u in the word list ** identified by wid. If the definition is not found, return zero. If the ** definition is found, return its execution token xt and one (1) if the ** definition is immediate, minus-one (-1) otherwise. **************************************************************************/ -static void searchWordlist(FICL_VM *pVM) +static void ficlPrimitiveSearchWordlist(ficlVm *vm) { - STRINGINFO si; - UNS16 hashCode; - FICL_WORD *pFW; - FICL_HASH *pHash = stackPopPtr(pVM->pStack); + ficlString name; + ficlUnsigned16 hashCode; + ficlWord *word; + ficlHash *hash = ficlStackPopPointer(vm->dataStack); - si.count = (FICL_COUNT)stackPopUNS(pVM->pStack); - si.cp = stackPopPtr(pVM->pStack); - hashCode = hashHashCode(si); + name.length = (ficlUnsigned8)ficlStackPopUnsigned(vm->dataStack); + name.text = ficlStackPopPointer(vm->dataStack); + hashCode = ficlHashCode(name); - ficlLockDictionary(TRUE); - pFW = hashLookup(pHash, si, hashCode); - ficlLockDictionary(FALSE); + ficlDictionaryLock(ficlVmGetDictionary(vm), FICL_TRUE); + word = ficlHashLookup(hash, name, hashCode); + ficlDictionaryLock(ficlVmGetDictionary(vm), FICL_FALSE); - if (pFW) + if (word) { - stackPushPtr(pVM->pStack, pFW); - stackPushINT(pVM->pStack, (wordIsImmediate(pFW) ? 1 : -1)); + ficlStackPushPointer(vm->dataStack, word); + ficlStackPushInteger(vm->dataStack, (ficlWordIsImmediate(word) ? 1 : -1)); } else { - stackPushUNS(pVM->pStack, 0); + ficlStackPushUnsigned(vm->dataStack, 0); } return; } /************************************************************************** s e t - c u r r e n t ** SEARCH ( wid -- ) ** Set the compilation word list to the word list identified by wid. **************************************************************************/ -static void setCurrent(FICL_VM *pVM) +static void ficlPrimitiveSetCurrent(ficlVm *vm) { - FICL_HASH *pHash = stackPopPtr(pVM->pStack); - FICL_DICT *pDict = vmGetDict(pVM); - ficlLockDictionary(TRUE); - pDict->pCompile = pHash; - ficlLockDictionary(FALSE); + ficlHash *hash = ficlStackPopPointer(vm->dataStack); + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + ficlDictionaryLock(dictionary, FICL_TRUE); + dictionary->compilationWordlist = hash; + ficlDictionaryLock(dictionary, FICL_FALSE); return; } /************************************************************************** s e t - o r d e r ** SEARCH ( widn ... wid1 n -- ) ** Set the search order to the word lists identified by widn ... wid1. ** Subsequently, word list wid1 will be searched first, and word list ** widn searched last. If n is zero, empty the search order. If n is minus ** one, set the search order to the implementation-defined minimum ** search order. The minimum search order shall include the words ** FORTH-WORDLIST and SET-ORDER. A system shall allow n to ** be at least eight. **************************************************************************/ -static void setOrder(FICL_VM *pVM) +static void ficlPrimitiveSetOrder(ficlVm *vm) { int i; - int nLists = stackPopINT(pVM->pStack); - FICL_DICT *dp = vmGetDict(pVM); + int wordlistCount = ficlStackPopInteger(vm->dataStack); + ficlDictionary *dictionary = ficlVmGetDictionary(vm); - if (nLists > FICL_DEFAULT_VOCS) + if (wordlistCount > FICL_MAX_WORDLISTS) { - vmThrowErr(pVM, "set-order error: list would be too large"); + ficlVmThrowError(vm, "set-order error: list would be too large"); } - ficlLockDictionary(TRUE); + ficlDictionaryLock(dictionary, FICL_TRUE); - if (nLists >= 0) + if (wordlistCount >= 0) { - dp->nLists = nLists; - for (i = nLists-1; i >= 0; --i) + dictionary->wordlistCount = wordlistCount; + for (i = wordlistCount-1; i >= 0; --i) { - dp->pSearch[i] = stackPopPtr(pVM->pStack); + dictionary->wordlists[i] = ficlStackPopPointer(vm->dataStack); } } else { - dictResetSearchOrder(dp); + ficlDictionaryResetSearchOrder(dictionary); } - ficlLockDictionary(FALSE); + ficlDictionaryLock(dictionary, FICL_FALSE); return; } /************************************************************************** f i c l - w o r d l i s t ** SEARCH ( -- wid ) ** Create a new empty word list, returning its word list identifier wid. ** The new word list may be returned from a pool of preallocated word ** lists or may be dynamically allocated in data space. A system shall ** allow the creation of at least 8 new word lists in addition to any ** provided as part of the system. ** Notes: -** 1. ficl creates a new single-list hash in the dictionary and returns +** 1. Ficl creates a new single-list hash in the dictionary and returns ** its address. ** 2. ficl-wordlist takes an arg off the stack indicating the number of ** hash entries in the wordlist. Ficl 2.02 and later define WORDLIST as ** : wordlist 1 ficl-wordlist ; **************************************************************************/ -static void ficlWordlist(FICL_VM *pVM) +static void ficlPrimitiveFiclWordlist(ficlVm *vm) { - FICL_DICT *dp = vmGetDict(pVM); - FICL_HASH *pHash; - FICL_UNS nBuckets; + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + ficlHash *hash; + ficlUnsigned nBuckets; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 1, 1); -#endif - nBuckets = stackPopUNS(pVM->pStack); - pHash = dictCreateWordlist(dp, nBuckets); - stackPushPtr(pVM->pStack, pHash); + FICL_STACK_CHECK(vm->dataStack, 1, 1); + + nBuckets = ficlStackPopUnsigned(vm->dataStack); + hash = ficlDictionaryCreateWordlist(dictionary, nBuckets); + ficlStackPushPointer(vm->dataStack, hash); return; } /************************************************************************** S E A R C H > -** ficl ( -- wid ) +** Ficl ( -- wid ) ** Pop wid off the search order. Error if the search order is empty **************************************************************************/ -static void searchPop(FICL_VM *pVM) +static void ficlPrimitiveSearchPop(ficlVm *vm) { - FICL_DICT *dp = vmGetDict(pVM); - int nLists; + ficlDictionary *dictionary = ficlVmGetDictionary(vm); + int wordlistCount; - ficlLockDictionary(TRUE); - nLists = dp->nLists; - if (nLists == 0) + ficlDictionaryLock(dictionary, FICL_TRUE); + wordlistCount = dictionary->wordlistCount; + if (wordlistCount == 0) { - vmThrowErr(pVM, "search> error: empty search order"); + ficlVmThrowError(vm, "search> error: empty search order"); } - stackPushPtr(pVM->pStack, dp->pSearch[--dp->nLists]); - ficlLockDictionary(FALSE); + ficlStackPushPointer(vm->dataStack, dictionary->wordlists[--dictionary->wordlistCount]); + ficlDictionaryLock(dictionary, FICL_FALSE); return; } /************************************************************************** > S E A R C H -** ficl ( wid -- ) +** Ficl ( wid -- ) ** Push wid onto the search order. Error if the search order is full. **************************************************************************/ -static void searchPush(FICL_VM *pVM) +static void ficlPrimitiveSearchPush(ficlVm *vm) { - FICL_DICT *dp = vmGetDict(pVM); + ficlDictionary *dictionary = ficlVmGetDictionary(vm); - ficlLockDictionary(TRUE); - if (dp->nLists > FICL_DEFAULT_VOCS) + ficlDictionaryLock(dictionary, FICL_TRUE); + if (dictionary->wordlistCount > FICL_MAX_WORDLISTS) { - vmThrowErr(pVM, ">search error: search order overflow"); + ficlVmThrowError(vm, ">search error: search order overflow"); } - dp->pSearch[dp->nLists++] = stackPopPtr(pVM->pStack); - ficlLockDictionary(FALSE); + dictionary->wordlists[dictionary->wordlistCount++] = ficlStackPopPointer(vm->dataStack); + ficlDictionaryLock(dictionary, FICL_FALSE); return; } /************************************************************************** W I D - G E T - N A M E -** ficl ( wid -- c-addr u ) +** Ficl ( wid -- c-addr u ) ** Get wid's (optional) name and push onto stack as a counted string **************************************************************************/ -static void widGetName(FICL_VM *pVM) +static void ficlPrimitiveWidGetName(ficlVm *vm) { - FICL_HASH *pHash = vmPop(pVM).p; - char *cp = pHash->name; - FICL_INT len = 0; + ficlHash *hash; + char *name; + ficlInteger length; + + hash = ficlVmPop(vm).p; + name = hash->name; - if (cp) - len = strlen(cp); + if (name != NULL) + length = strlen(name); + else + length = 0; - vmPush(pVM, LVALUEtoCELL(cp)); - vmPush(pVM, LVALUEtoCELL(len)); + ficlVmPush(vm, FICL_LVALUE_TO_CELL(name)); + ficlVmPush(vm, FICL_LVALUE_TO_CELL(length)); return; } /************************************************************************** W I D - S E T - N A M E -** ficl ( wid c-addr -- ) +** Ficl ( wid c-addr -- ) ** Set wid's name pointer to the \0 terminated string address supplied **************************************************************************/ -static void widSetName(FICL_VM *pVM) +static void ficlPrimitiveWidSetName(ficlVm *vm) { - char *cp = (char *)vmPop(pVM).p; - FICL_HASH *pHash = vmPop(pVM).p; - pHash->name = cp; + char *name = (char *)ficlVmPop(vm).p; + ficlHash *hash = ficlVmPop(vm).p; + hash->name = name; return; } /************************************************************************** setParentWid -** FICL +** Ficl ** setparentwid ( parent-wid wid -- ) ** Set WID's link field to the parent-wid. search-wordlist will ** iterate through all the links when finding words in the child wid. **************************************************************************/ -static void setParentWid(FICL_VM *pVM) +static void ficlPrimitiveSetParentWid(ficlVm *vm) { - FICL_HASH *parent, *child; -#if FICL_ROBUST > 1 - vmCheckStack(pVM, 2, 0); -#endif - child = (FICL_HASH *)stackPopPtr(pVM->pStack); - parent = (FICL_HASH *)stackPopPtr(pVM->pStack); + ficlHash *parent, *child; + FICL_STACK_CHECK(vm->dataStack, 2, 0); + + child = (ficlHash *)ficlStackPopPointer(vm->dataStack); + parent = (ficlHash *)ficlStackPopPointer(vm->dataStack); + child->link = parent; return; } /************************************************************************** f i c l C o m p i l e S e a r c h ** Builds the primitive wordset and the environment-query namespace. **************************************************************************/ -void ficlCompileSearch(FICL_SYSTEM *pSys) +void ficlSystemCompileSearch(ficlSystem *system) { - FICL_DICT *dp = pSys->dp; - assert (dp); + ficlDictionary *dictionary = ficlSystemGetDictionary(system); + ficlDictionary *environment = ficlSystemGetEnvironment(system); + FICL_SYSTEM_ASSERT(system, dictionary); + FICL_SYSTEM_ASSERT(system, environment); + + /* ** optional SEARCH-ORDER word set */ - dictAppendWord(dp, ">search", searchPush, FW_DEFAULT); - dictAppendWord(dp, "search>", searchPop, FW_DEFAULT); - dictAppendWord(dp, "definitions", - definitions, FW_DEFAULT); - dictAppendWord(dp, "forth-wordlist", - forthWordlist, FW_DEFAULT); - dictAppendWord(dp, "get-current", - getCurrent, FW_DEFAULT); - dictAppendWord(dp, "get-order", getOrder, FW_DEFAULT); - dictAppendWord(dp, "search-wordlist", - searchWordlist, FW_DEFAULT); - dictAppendWord(dp, "set-current", - setCurrent, FW_DEFAULT); - dictAppendWord(dp, "set-order", setOrder, FW_DEFAULT); - dictAppendWord(dp, "ficl-wordlist", - ficlWordlist, FW_DEFAULT); + ficlDictionarySetPrimitive(dictionary, ">search", ficlPrimitiveSearchPush, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "search>", ficlPrimitiveSearchPop, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "definitions", + ficlPrimitiveDefinitions, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "forth-wordlist", + ficlPrimitiveForthWordlist, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "get-current", + ficlPrimitiveGetCurrent, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "get-order", ficlPrimitiveGetOrder, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "search-wordlist", + ficlPrimitiveSearchWordlist, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "set-current", + ficlPrimitiveSetCurrent, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "set-order", ficlPrimitiveSetOrder, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "ficl-wordlist", + ficlPrimitiveFiclWordlist, FICL_WORD_DEFAULT); /* ** Set SEARCH environment query values */ - ficlSetEnv(pSys, "search-order", FICL_TRUE); - ficlSetEnv(pSys, "search-order-ext", FICL_TRUE); - ficlSetEnv(pSys, "wordlists", FICL_DEFAULT_VOCS); + ficlDictionarySetConstant(environment, "search-order", FICL_TRUE); + ficlDictionarySetConstant(environment, "search-order-ext", FICL_TRUE); + ficlDictionarySetConstant(environment, "wordlists", FICL_MAX_WORDLISTS); - dictAppendWord(dp, "wid-get-name", widGetName, FW_DEFAULT); - dictAppendWord(dp, "wid-set-name", widSetName, FW_DEFAULT); - dictAppendWord(dp, "wid-set-super", - setParentWid, FW_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "wid-get-name", ficlPrimitiveWidGetName, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "wid-set-name", ficlPrimitiveWidSetName, FICL_WORD_DEFAULT); + ficlDictionarySetPrimitive(dictionary, "wid-set-super", + ficlPrimitiveSetParentWid, FICL_WORD_DEFAULT); return; } Index: vendor/ficl/dist/softcore/classes.fr =================================================================== --- vendor/ficl/dist/softcore/classes.fr (nonexistent) +++ vendor/ficl/dist/softcore/classes.fr (revision 282803) @@ -0,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] Index: vendor/ficl/dist/softcore/ficl.fr =================================================================== --- vendor/ficl/dist/softcore/ficl.fr (nonexistent) +++ vendor/ficl/dist/softcore/ficl.fr (revision 282803) @@ -0,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 + Index: vendor/ficl/dist/softcore/ficlclass.fr =================================================================== --- vendor/ficl/dist/softcore/ficlclass.fr (nonexistent) +++ vendor/ficl/dist/softcore/ficlclass.fr (revision 282803) @@ -0,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] Index: vendor/ficl/dist/softcore/ficllocal.fr =================================================================== --- vendor/ficl/dist/softcore/ficllocal.fr (nonexistent) +++ vendor/ficl/dist/softcore/ficllocal.fr (revision 282803) @@ -0,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 Index: vendor/ficl/dist/softcore/fileaccess.fr =================================================================== --- vendor/ficl/dist/softcore/fileaccess.fr (nonexistent) +++ vendor/ficl/dist/softcore/fileaccess.fr (revision 282803) @@ -0,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] Index: vendor/ficl/dist/softcore/forml.fr =================================================================== --- vendor/ficl/dist/softcore/forml.fr (nonexistent) +++ vendor/ficl/dist/softcore/forml.fr (revision 282803) @@ -0,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 + Index: vendor/ficl/dist/softcore/ifbrack.fr =================================================================== --- vendor/ficl/dist/softcore/ifbrack.fr (nonexistent) +++ vendor/ficl/dist/softcore/ifbrack.fr (revision 282803) @@ -0,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 Index: vendor/ficl/dist/softcore/jhlocal.fr =================================================================== --- vendor/ficl/dist/softcore/jhlocal.fr (nonexistent) +++ vendor/ficl/dist/softcore/jhlocal.fr (revision 282803) @@ -0,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] + Index: vendor/ficl/dist/softcore/make.bat =================================================================== --- vendor/ficl/dist/softcore/make.bat (nonexistent) +++ vendor/ficl/dist/softcore/make.bat (revision 282803) @@ -0,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 Index: vendor/ficl/dist/softcore/makefile =================================================================== --- vendor/ficl/dist/softcore/makefile (nonexistent) +++ vendor/ficl/dist/softcore/makefile (revision 282803) @@ -0,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) $(CFLAGS) $(CPPFLAGS) -I.. -o makesoftcore makesoftcore.c ../lzcompress.c ../bit.c + +clean: + - rm ../softcore.c *.o makesoftcore + Property changes on: vendor/ficl/dist/softcore/makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/softcore/makesoftcore.c =================================================================== --- vendor/ficl/dist/softcore/makesoftcore.c (nonexistent) +++ vendor/ficl/dist/softcore/makesoftcore.c (revision 282803) @@ -0,0 +1,244 @@ +/* +** 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 +#include +#include +#include + +#include "ficl.h" + + +#ifndef SOFTCORE_OUT +#define SOFTCORE_OUT "../softcore.c" +#endif + +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 = 1; /* true */ + + while (*data) + { + if (*data == '\n') + { + if (!lineIsBlank) + fprintf(f, "\\n\"\n"); + lineIsBlank = 1; /* true */ + } + else + { + if (lineIsBlank) + { + fputc('\t', f); + fputc('"', f); + lineIsBlank = 0; /* 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); + unsigned char *compressed; + char *trace = uncompressed; + int i; + size_t compressedSize; + size_t uncompressedSize; + char *src, *dst; + FILE *f; + time_t currentTimeT; + struct tm *currentTime; + char cleverTime[32]; + + time(¤tTimeT); + currentTime = localtime(¤tTimeT); + 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_OUT, "wt"); + if (f == NULL) + { + printf("couldn't open " SOFTCORE_OUT " 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); + } Property changes on: vendor/ficl/dist/softcore/makesoftcore.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: vendor/ficl/dist/softcore/marker.fr =================================================================== --- vendor/ficl/dist/softcore/marker.fr (nonexistent) +++ vendor/ficl/dist/softcore/marker.fr (revision 282803) @@ -0,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 +; Index: vendor/ficl/dist/softcore/oo.fr =================================================================== --- vendor/ficl/dist/softcore/oo.fr (nonexistent) +++ vendor/ficl/dist/softcore/oo.fr (revision 282803) @@ -0,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 -- exc-flag ) + lookup-method catch +; + +: exec-method ( instance class c-addr u -- ) + 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 -- 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] Index: vendor/ficl/dist/softcore/prefix.fr =================================================================== --- vendor/ficl/dist/softcore/prefix.fr (nonexistent) +++ vendor/ficl/dist/softcore/prefix.fr (revision 282803) @@ -0,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 +\ wordlist. start-prefixes and end-prefixes handle the bookkeeping + +variable save-current + +: start-prefixes get-current save-current ! set-current ; +: end-prefixes save-current @ set-current ; +: show-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 + Index: vendor/ficl/dist/softcore/softcore.fr =================================================================== --- vendor/ficl/dist/softcore/softcore.fr (nonexistent) +++ vendor/ficl/dist/softcore/softcore.fr (revision 282803) @@ -0,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 +\ +\ set-current +\