summaryrefslogtreecommitdiff
path: root/usr/src/common/ficl/dictionary.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/common/ficl/dictionary.c')
-rw-r--r--usr/src/common/ficl/dictionary.c881
1 files changed, 881 insertions, 0 deletions
diff --git a/usr/src/common/ficl/dictionary.c b/usr/src/common/ficl/dictionary.c
new file mode 100644
index 0000000000..39460e9144
--- /dev/null
+++ b/usr/src/common/ficl/dictionary.c
@@ -0,0 +1,881 @@
+/*
+ * d i c t . c
+ * Forth Inspired Command Language - dictionary methods
+ * Author: John Sadler (john_sadler@alum.mit.edu)
+ * Created: 19 July 1997
+ * $Id: dictionary.c,v 1.2 2010/09/12 15:14:52 asau Exp $
+ */
+/*
+ * This file implements the dictionary -- Ficl's model of
+ * memory management. All Ficl words are stored in the
+ * dictionary. A word is a named chunk of data with its
+ * associated code. Ficl treats all words the same, even
+ * precompiled ones, so your words become first-class
+ * extensions of the language. You can even define new
+ * control structures.
+ *
+ * 29 jun 1998 (sadler) added variable sized hash table support
+ */
+/*
+ * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
+ * All rights reserved.
+ *
+ * Get the latest Ficl release at http://ficl.sourceforge.net
+ *
+ * I am interested in hearing from anyone who uses Ficl. If you have
+ * a problem, a success story, a defect, an enhancement request, or
+ * if you would like to contribute to the Ficl release, please
+ * contact me by email at the address above.
+ *
+ * L I C E N S E and D I S C L A I M E R
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "ficl.h"
+
+#define FICL_SAFE_CALLBACK_FROM_SYSTEM(system) \
+ (((system) != NULL) ? &((system)->callback) : NULL)
+#define FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary) \
+ (((dictionary) != NULL) ? (dictionary)->system : NULL)
+#define FICL_DICTIONARY_ASSERT(dictionary, expression) \
+ FICL_SYSTEM_ASSERT(FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary), \
+ expression)
+
+/*
+ * d i c t A b o r t D e f i n i t i o n
+ * Abort a definition in process: reclaim its memory and unlink it
+ * from the dictionary list. Assumes that there is a smudged
+ * definition in process...otherwise does nothing.
+ * NOTE: this function is not smart enough to unlink a word that
+ * has been successfully defined (ie linked into a hash). It
+ * only works for defs in process. If the def has been unsmudged,
+ * nothing happens.
+ */
+void
+ficlDictionaryAbortDefinition(ficlDictionary *dictionary)
+{
+ ficlWord *word;
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+ word = dictionary->smudge;
+
+ if (word->flags & FICL_WORD_SMUDGED)
+ dictionary->here = (ficlCell *)word->name;
+
+ ficlDictionaryLock(dictionary, FICL_FALSE);
+}
+
+/*
+ * d i c t A l i g n
+ * Align the dictionary's free space pointer
+ */
+void
+ficlDictionaryAlign(ficlDictionary *dictionary)
+{
+ dictionary->here = ficlAlignPointer(dictionary->here);
+}
+
+/*
+ * d i c t A l l o t
+ * Allocate or remove n chars of dictionary space, with
+ * checks for underrun and overrun
+ */
+void
+ficlDictionaryAllot(ficlDictionary *dictionary, int n)
+{
+ char *here = (char *)dictionary->here;
+ here += n;
+ dictionary->here = FICL_POINTER_TO_CELL(here);
+}
+
+/*
+ * d i c t A l l o t C e l l s
+ * Reserve space for the requested number of ficlCells in the
+ * dictionary. If nficlCells < 0 , removes space from the dictionary.
+ */
+void
+ficlDictionaryAllotCells(ficlDictionary *dictionary, int nficlCells)
+{
+ dictionary->here += nficlCells;
+}
+
+/*
+ * d i c t A p p e n d C e l l
+ * Append the specified ficlCell to the dictionary
+ */
+void
+ficlDictionaryAppendCell(ficlDictionary *dictionary, ficlCell c)
+{
+ *dictionary->here++ = c;
+}
+
+/*
+ * d i c t A p p e n d C h a r
+ * Append the specified char to the dictionary
+ */
+void
+ficlDictionaryAppendCharacter(ficlDictionary *dictionary, char c)
+{
+ char *here = (char *)dictionary->here;
+ *here++ = c;
+ dictionary->here = FICL_POINTER_TO_CELL(here);
+}
+
+/*
+ * d i c t A p p e n d U N S
+ * Append the specified ficlUnsigned to the dictionary
+ */
+void
+ficlDictionaryAppendUnsigned(ficlDictionary *dictionary, ficlUnsigned u)
+{
+ ficlCell c;
+
+ c.u = u;
+ ficlDictionaryAppendCell(dictionary, c);
+}
+
+void *
+ficlDictionaryAppendData(ficlDictionary *dictionary, void *data,
+ ficlInteger length)
+{
+ char *here = (char *)dictionary->here;
+ char *oldHere = here;
+ char *from = (char *)data;
+
+ if (length == 0) {
+ ficlDictionaryAlign(dictionary);
+ return ((char *)dictionary->here);
+ }
+
+ while (length) {
+ *here++ = *from++;
+ length--;
+ }
+
+ *here++ = '\0';
+
+ dictionary->here = FICL_POINTER_TO_CELL(here);
+ ficlDictionaryAlign(dictionary);
+ return (oldHere);
+}
+
+/*
+ * d i c t C o p y N a m e
+ * Copy up to FICL_NAME_LENGTH characters of the name specified by s into
+ * the dictionary starting at "here", then NULL-terminate the name,
+ * point "here" to the next available byte, and return the address of
+ * the beginning of the name. Used by dictAppendWord.
+ * N O T E S :
+ * 1. "here" is guaranteed to be aligned after this operation.
+ * 2. If the string has zero length, align and return "here"
+ */
+char *
+ficlDictionaryAppendString(ficlDictionary *dictionary, ficlString s)
+{
+ void *data = FICL_STRING_GET_POINTER(s);
+ ficlInteger length = FICL_STRING_GET_LENGTH(s);
+
+ if (length > FICL_NAME_LENGTH)
+ length = FICL_NAME_LENGTH;
+
+ return (ficlDictionaryAppendData(dictionary, data, length));
+}
+
+ficlWord *
+ficlDictionaryAppendConstantInstruction(ficlDictionary *dictionary,
+ ficlString name, ficlInstruction instruction, ficlInteger value)
+{
+ ficlWord *word = ficlDictionaryAppendWord(dictionary, name,
+ (ficlPrimitive)instruction, FICL_WORD_DEFAULT);
+
+ if (word != NULL)
+ ficlDictionaryAppendUnsigned(dictionary, value);
+ return (word);
+}
+
+ficlWord *
+ficlDictionaryAppend2ConstantInstruction(ficlDictionary *dictionary,
+ ficlString name, ficlInstruction instruction, ficl2Integer value)
+{
+ ficlWord *word = ficlDictionaryAppendWord(dictionary, name,
+ (ficlPrimitive)instruction, FICL_WORD_DEFAULT);
+
+ if (word != NULL) {
+ ficlDictionaryAppendUnsigned(dictionary,
+ FICL_2UNSIGNED_GET_HIGH(value));
+ ficlDictionaryAppendUnsigned(dictionary,
+ FICL_2UNSIGNED_GET_LOW(value));
+ }
+ return (word);
+}
+
+ficlWord *
+ficlDictionaryAppendConstant(ficlDictionary *dictionary, char *name,
+ ficlInteger value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return (ficlDictionaryAppendConstantInstruction(dictionary, s,
+ ficlInstructionConstantParen, value));
+}
+
+ficlWord *
+ficlDictionaryAppend2Constant(ficlDictionary *dictionary, char *name,
+ ficl2Integer value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return (ficlDictionaryAppend2ConstantInstruction(dictionary, s,
+ ficlInstruction2ConstantParen, value));
+}
+
+ficlWord *
+ficlDictionarySetConstantInstruction(ficlDictionary *dictionary,
+ ficlString name, ficlInstruction instruction, ficlInteger value)
+{
+ ficlWord *word = ficlDictionaryLookup(dictionary, name);
+ ficlCell c;
+
+ if (word == NULL) {
+ word = ficlDictionaryAppendConstantInstruction(dictionary,
+ name, instruction, value);
+ } else {
+ word->code = (ficlPrimitive)instruction;
+ c.i = value;
+ word->param[0] = c;
+ }
+ return (word);
+}
+
+ficlWord *
+ficlDictionarySetConstant(ficlDictionary *dictionary, char *name,
+ ficlInteger value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ return (ficlDictionarySetConstantInstruction(dictionary, s,
+ ficlInstructionConstantParen, value));
+}
+
+ficlWord *
+ficlDictionarySet2ConstantInstruction(ficlDictionary *dictionary, ficlString s,
+ ficlInstruction instruction, ficl2Integer value)
+{
+ ficlWord *word;
+ word = ficlDictionaryLookup(dictionary, s);
+
+ /*
+ * only reuse the existing word if we're sure it has space for a
+ * 2constant
+ */
+#if FICL_WANT_FLOAT
+ if ((word != NULL) &&
+ ((((ficlInstruction)word->code) == ficlInstruction2ConstantParen) ||
+ (((ficlInstruction)word->code) == ficlInstructionF2ConstantParen)))
+#else
+ if ((word != NULL) &&
+ ((((ficlInstruction)word->code) == ficlInstruction2ConstantParen)))
+#endif /* FICL_WANT_FLOAT */
+ {
+ word->code = (ficlPrimitive)instruction;
+ word->param[0].u = FICL_2UNSIGNED_GET_HIGH(value);
+ word->param[1].u = FICL_2UNSIGNED_GET_LOW(value);
+ } else {
+ word = ficlDictionaryAppend2ConstantInstruction(dictionary, s,
+ instruction, value);
+ }
+
+ return (word);
+}
+
+ficlWord *
+ficlDictionarySet2Constant(ficlDictionary *dictionary, char *name,
+ ficl2Integer value)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+
+ return (ficlDictionarySet2ConstantInstruction(dictionary, s,
+ ficlInstruction2ConstantParen, value));
+}
+
+ficlWord *
+ficlDictionarySetConstantString(ficlDictionary *dictionary, char *name,
+ char *value)
+{
+ ficlString s;
+ ficl2Integer valueAs2Integer;
+ FICL_2INTEGER_SET(strlen(value), (intptr_t)value, valueAs2Integer);
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+
+ return (ficlDictionarySet2ConstantInstruction(dictionary, s,
+ ficlInstruction2ConstantParen, valueAs2Integer));
+}
+
+/*
+ * d i c t A p p e n d W o r d
+ * Create a new word in the dictionary with the specified
+ * ficlString, code, and flags. Does not require a NULL-terminated
+ * name.
+ */
+ficlWord *
+ficlDictionaryAppendWord(ficlDictionary *dictionary, ficlString name,
+ ficlPrimitive code, ficlUnsigned8 flags)
+{
+ ficlUnsigned8 length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(name);
+ char *nameCopy;
+ ficlWord *word;
+
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+
+ /*
+ * NOTE: ficlDictionaryAppendString advances "here" as a side-effect.
+ * It must execute before word is initialized.
+ */
+ nameCopy = ficlDictionaryAppendString(dictionary, name);
+ word = (ficlWord *)dictionary->here;
+ dictionary->smudge = word;
+ word->hash = ficlHashCode(name);
+ word->code = code;
+ word->semiParen = ficlInstructionSemiParen;
+ word->flags = (ficlUnsigned8)(flags | FICL_WORD_SMUDGED);
+ word->length = length;
+ word->name = nameCopy;
+
+ /*
+ * Point "here" to first ficlCell of new word's param area...
+ */
+ dictionary->here = word->param;
+
+ if (!(flags & FICL_WORD_SMUDGED))
+ ficlDictionaryUnsmudge(dictionary);
+
+ ficlDictionaryLock(dictionary, FICL_FALSE);
+ return (word);
+}
+
+/*
+ * d i c t A p p e n d W o r d
+ * Create a new word in the dictionary with the specified
+ * name, code, and flags. Name must be NULL-terminated.
+ */
+ficlWord *
+ficlDictionaryAppendPrimitive(ficlDictionary *dictionary, char *name,
+ ficlPrimitive code, ficlUnsigned8 flags)
+{
+ ficlString s;
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+
+ return (ficlDictionaryAppendWord(dictionary, s, code, flags));
+}
+
+ficlWord *
+ficlDictionarySetPrimitive(ficlDictionary *dictionary, char *name,
+ ficlPrimitive code, ficlUnsigned8 flags)
+{
+ ficlString s;
+ ficlWord *word;
+
+ FICL_STRING_SET_FROM_CSTRING(s, name);
+ word = ficlDictionaryLookup(dictionary, s);
+
+ if (word == NULL) {
+ word = ficlDictionaryAppendPrimitive(dictionary, name,
+ code, flags);
+ } else {
+ word->code = (ficlPrimitive)code;
+ word->flags = flags;
+ }
+ return (word);
+}
+
+ficlWord *
+ficlDictionaryAppendInstruction(ficlDictionary *dictionary, char *name,
+ ficlInstruction i, ficlUnsigned8 flags)
+{
+ return (ficlDictionaryAppendPrimitive(dictionary, name,
+ (ficlPrimitive)i, (ficlUnsigned8)(FICL_WORD_INSTRUCTION | flags)));
+}
+
+ficlWord *
+ficlDictionarySetInstruction(ficlDictionary *dictionary, char *name,
+ ficlInstruction i, ficlUnsigned8 flags)
+{
+ return (ficlDictionarySetPrimitive(dictionary, name,
+ (ficlPrimitive)i, (ficlUnsigned8)(FICL_WORD_INSTRUCTION | flags)));
+}
+
+/*
+ * d i c t C e l l s A v a i l
+ * Returns the number of empty ficlCells left in the dictionary
+ */
+int
+ficlDictionaryCellsAvailable(ficlDictionary *dictionary)
+{
+ return (dictionary->size - ficlDictionaryCellsUsed(dictionary));
+}
+
+/*
+ * d i c t C e l l s U s e d
+ * Returns the number of ficlCells consumed in the dicionary
+ */
+int
+ficlDictionaryCellsUsed(ficlDictionary *dictionary)
+{
+ return (dictionary->here - dictionary->base);
+}
+
+/*
+ * d i c t C r e a t e
+ * Create and initialize a dictionary with the specified number
+ * of ficlCells capacity, and no hashing (hash size == 1).
+ */
+ficlDictionary *
+ficlDictionaryCreate(ficlSystem *system, unsigned size)
+{
+ return (ficlDictionaryCreateHashed(system, size, 1));
+}
+
+ficlDictionary *
+ficlDictionaryCreateHashed(ficlSystem *system, unsigned size,
+ unsigned bucketCount)
+{
+ ficlDictionary *dictionary;
+ size_t nAlloc;
+
+ nAlloc = sizeof (ficlDictionary) + (size * sizeof (ficlCell))
+ + sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *);
+
+ dictionary = ficlMalloc(nAlloc);
+ FICL_SYSTEM_ASSERT(system, dictionary != NULL);
+
+ dictionary->size = size;
+ dictionary->system = system;
+
+ ficlDictionaryEmpty(dictionary, bucketCount);
+ return (dictionary);
+}
+
+/*
+ * d i c t C r e a t e W o r d l i s t
+ * Create and initialize an anonymous wordlist
+ */
+ficlHash *
+ficlDictionaryCreateWordlist(ficlDictionary *dictionary, int bucketCount)
+{
+ ficlHash *hash;
+
+ ficlDictionaryAlign(dictionary);
+ hash = (ficlHash *)dictionary->here;
+ ficlDictionaryAllot(dictionary,
+ sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *));
+
+ hash->size = bucketCount;
+ ficlHashReset(hash);
+ return (hash);
+}
+
+/*
+ * d i c t D e l e t e
+ * Free all memory allocated for the given dictionary
+ */
+void
+ficlDictionaryDestroy(ficlDictionary *dictionary)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary != NULL);
+ ficlFree(dictionary);
+}
+
+/*
+ * d i c t E m p t y
+ * Empty the dictionary, reset its hash table, and reset its search order.
+ * Clears and (re-)creates the hash table with the size specified by nHash.
+ */
+void
+ficlDictionaryEmpty(ficlDictionary *dictionary, unsigned bucketCount)
+{
+ ficlHash *hash;
+
+ dictionary->here = dictionary->base;
+
+ ficlDictionaryAlign(dictionary);
+ hash = (ficlHash *)dictionary->here;
+ ficlDictionaryAllot(dictionary,
+ sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *));
+
+ hash->size = bucketCount;
+ ficlHashReset(hash);
+
+ dictionary->forthWordlist = hash;
+ dictionary->smudge = NULL;
+ ficlDictionaryResetSearchOrder(dictionary);
+}
+
+/*
+ * i s A F i c l W o r d
+ * Vet a candidate pointer carefully to make sure
+ * it's not some chunk o' inline data...
+ * It has to have a name, and it has to look
+ * like it's in the dictionary address range.
+ * NOTE: this excludes :noname words!
+ */
+int
+ficlDictionaryIsAWord(ficlDictionary *dictionary, ficlWord *word)
+{
+ if ((((ficlInstruction)word) > ficlInstructionInvalid) &&
+ (((ficlInstruction)word) < ficlInstructionLast))
+ return (1);
+
+ if (!ficlDictionaryIncludes(dictionary, word))
+ return (0);
+
+ if (!ficlDictionaryIncludes(dictionary, word->name))
+ return (0);
+
+ if ((word->link != NULL) &&
+ !ficlDictionaryIncludes(dictionary, word->link))
+ return (0);
+
+ if ((word->length <= 0) || (word->name[word->length] != '\0'))
+ return (0);
+
+ if (strlen(word->name) != word->length)
+ return (0);
+
+ return (1);
+}
+
+/*
+ * f i n d E n c l o s i n g W o r d
+ * Given a pointer to something, check to make sure it's an address in the
+ * dictionary. If so, search backwards until we find something that looks
+ * like a dictionary header. If successful, return the address of the
+ * ficlWord found. Otherwise return NULL. nSEARCH_CELLS sets the maximum
+ * neighborhood this func will search before giving up
+ */
+#define nSEARCH_CELLS 100
+
+ficlWord *
+ficlDictionaryFindEnclosingWord(ficlDictionary *dictionary, ficlCell *cell)
+{
+ ficlWord *word;
+ int i;
+
+ if (!ficlDictionaryIncludes(dictionary, (void *)cell))
+ return (NULL);
+
+ for (i = nSEARCH_CELLS; i > 0; --i, --cell) {
+ word = (ficlWord *)
+ (cell + 1 - (sizeof (ficlWord) / sizeof (ficlCell)));
+ if (ficlDictionaryIsAWord(dictionary, word))
+ return (word);
+ }
+
+ return (NULL);
+}
+
+/*
+ * d i c t I n c l u d e s
+ * Returns FICL_TRUE iff the given pointer is within the address range of
+ * the dictionary.
+ */
+int
+ficlDictionaryIncludes(ficlDictionary *dictionary, void *p)
+{
+ return ((p >= (void *) &dictionary->base) &&
+ (p < (void *)(&dictionary->base + dictionary->size)));
+}
+
+/*
+ * d i c t L o o k u p
+ * Find the ficlWord that matches the given name and length.
+ * If found, returns the word's address. Otherwise returns NULL.
+ * Uses the search order list to search multiple wordlists.
+ */
+ficlWord *
+ficlDictionaryLookup(ficlDictionary *dictionary, ficlString name)
+{
+ ficlWord *word = NULL;
+ ficlHash *hash;
+ int i;
+ ficlUnsigned16 hashCode = ficlHashCode(name);
+
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary != NULL);
+
+ ficlDictionaryLock(dictionary, FICL_TRUE);
+
+ for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i) {
+ hash = dictionary->wordlists[i];
+ word = ficlHashLookup(hash, name, hashCode);
+ }
+
+ ficlDictionaryLock(dictionary, FICL_FALSE);
+ return (word);
+}
+
+/*
+ * s e e
+ * TOOLS ( "<spaces>name" -- )
+ * Display a human-readable representation of the named word's definition.
+ * The source of the representation (object-code decompilation, source
+ * block, etc.) and the particular form of the display is implementation
+ * defined.
+ */
+/*
+ * ficlSeeColon (for proctologists only)
+ * Walks a colon definition, decompiling
+ * on the fly. Knows about primitive control structures.
+ */
+char *ficlDictionaryInstructionNames[] =
+{
+#define FICL_TOKEN(token, description) description,
+#define FICL_INSTRUCTION_TOKEN(token, description, flags) description,
+#include "ficltokens.h"
+#undef FICL_TOKEN
+#undef FICL_INSTRUCTION_TOKEN
+};
+
+void
+ficlDictionarySee(ficlDictionary *dictionary, ficlWord *word,
+ ficlCallback *callback)
+{
+ char *trace;
+ ficlCell *cell = word->param;
+ ficlCell *param0 = cell;
+ char buffer[128];
+
+ for (; cell->i != ficlInstructionSemiParen; cell++) {
+ ficlWord *word = (ficlWord *)(cell->p);
+
+ trace = buffer;
+ if ((void *)cell == (void *)buffer)
+ *trace++ = '>';
+ else
+ *trace++ = ' ';
+ trace += sprintf(trace, "%3ld ", (long)(cell - param0));
+
+ if (ficlDictionaryIsAWord(dictionary, word)) {
+ ficlWordKind kind = ficlWordClassify(word);
+ ficlCell c, c2;
+
+ switch (kind) {
+ case FICL_WORDKIND_INSTRUCTION:
+ sprintf(trace, "%s (instruction %ld)",
+ ficlDictionaryInstructionNames[(long)word],
+ (long)word);
+ break;
+ case FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT:
+ c = *++cell;
+ sprintf(trace, "%s (instruction %ld), with "
+ "argument %ld (%#lx)",
+ ficlDictionaryInstructionNames[(long)word],
+ (long)word, (long)c.i, (unsigned long)c.u);
+ break;
+ case FICL_WORDKIND_INSTRUCTION_WORD:
+ sprintf(trace,
+ "%s :: executes %s (instruction word %ld)",
+ word->name,
+ ficlDictionaryInstructionNames[
+ (long)word->code], (long)word->code);
+ break;
+ case FICL_WORDKIND_LITERAL:
+ c = *++cell;
+ if (ficlDictionaryIsAWord(dictionary, c.p) &&
+ (c.i >= ficlInstructionLast)) {
+ ficlWord *word = (ficlWord *)c.p;
+ sprintf(trace, "%.*s ( %#lx literal )",
+ word->length, word->name,
+ (unsigned long)c.u);
+ } else
+ sprintf(trace,
+ "literal %ld (%#lx)", (long)c.i,
+ (unsigned long)c.u);
+ break;
+ case FICL_WORDKIND_2LITERAL:
+ c = *++cell;
+ c2 = *++cell;
+ sprintf(trace, "2literal %ld %ld (%#lx %#lx)",
+ (long)c2.i, (long)c.i, (unsigned long)c2.u,
+ (unsigned long)c.u);
+ break;
+#if FICL_WANT_FLOAT
+ case FICL_WORDKIND_FLITERAL:
+ c = *++cell;
+ sprintf(trace, "fliteral %f (%#lx)",
+ (double)c.f, (unsigned long)c.u);
+ break;
+#endif /* FICL_WANT_FLOAT */
+ case FICL_WORDKIND_STRING_LITERAL: {
+ ficlCountedString *counted;
+ counted = (ficlCountedString *)(void *)++cell;
+ cell = (ficlCell *)
+ ficlAlignPointer(counted->text +
+ counted->length + 1) - 1;
+ sprintf(trace, "s\" %.*s\"", counted->length,
+ counted->text);
+ }
+ break;
+ case FICL_WORDKIND_CSTRING_LITERAL: {
+ ficlCountedString *counted;
+ counted = (ficlCountedString *)(void *)++cell;
+ cell = (ficlCell *)
+ ficlAlignPointer(counted->text +
+ counted->length + 1) - 1;
+ sprintf(trace, "c\" %.*s\"", counted->length,
+ counted->text);
+ }
+ break;
+ case FICL_WORDKIND_BRANCH0:
+ c = *++cell;
+ sprintf(trace, "branch0 %ld",
+ (long)(cell + c.i - param0));
+ break;
+ case FICL_WORDKIND_BRANCH:
+ c = *++cell;
+ sprintf(trace, "branch %ld",
+ (long)(cell + c.i - param0));
+ break;
+
+ case FICL_WORDKIND_QDO:
+ c = *++cell;
+ sprintf(trace, "?do (leave %ld)",
+ (long)((ficlCell *)c.p - param0));
+ break;
+ case FICL_WORDKIND_DO:
+ c = *++cell;
+ sprintf(trace, "do (leave %ld)",
+ (long)((ficlCell *)c.p - param0));
+ break;
+ case FICL_WORDKIND_LOOP:
+ c = *++cell;
+ sprintf(trace, "loop (branch %ld)",
+ (long)(cell + c.i - param0));
+ break;
+ case FICL_WORDKIND_OF:
+ c = *++cell;
+ sprintf(trace, "of (branch %ld)",
+ (long)(cell + c.i - param0));
+ break;
+ case FICL_WORDKIND_PLOOP:
+ c = *++cell;
+ sprintf(trace, "+loop (branch %ld)",
+ (long)(cell + c.i - param0));
+ break;
+ default:
+ sprintf(trace, "%.*s", word->length,
+ word->name);
+ break;
+ }
+ } else {
+ /* probably not a word - punt and print value */
+ sprintf(trace, "%ld ( %#lx )", (long)cell->i,
+ (unsigned long)cell->u);
+ }
+
+ ficlCallbackTextOut(callback, buffer);
+ ficlCallbackTextOut(callback, "\n");
+ }
+
+ ficlCallbackTextOut(callback, ";\n");
+}
+
+/*
+ * d i c t R e s e t S e a r c h O r d e r
+ * Initialize the dictionary search order list to sane state
+ */
+void
+ficlDictionaryResetSearchOrder(ficlDictionary *dictionary)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary);
+ dictionary->compilationWordlist = dictionary->forthWordlist;
+ dictionary->wordlistCount = 1;
+ dictionary->wordlists[0] = dictionary->forthWordlist;
+}
+
+/*
+ * d i c t S e t F l a g s
+ * Changes the flags field of the most recently defined word:
+ * Set all bits that are ones in the set parameter.
+ */
+void
+ficlDictionarySetFlags(ficlDictionary *dictionary, ficlUnsigned8 set)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
+ dictionary->smudge->flags |= set;
+}
+
+
+/*
+ * d i c t C l e a r F l a g s
+ * Changes the flags field of the most recently defined word:
+ * Clear all bits that are ones in the clear parameter.
+ */
+void
+ficlDictionaryClearFlags(ficlDictionary *dictionary, ficlUnsigned8 clear)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
+ dictionary->smudge->flags &= ~clear;
+}
+
+/*
+ * d i c t S e t I m m e d i a t e
+ * Set the most recently defined word as IMMEDIATE
+ */
+void
+ficlDictionarySetImmediate(ficlDictionary *dictionary)
+{
+ FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
+ dictionary->smudge->flags |= FICL_WORD_IMMEDIATE;
+}
+
+/*
+ * d i c t U n s m u d g e
+ * Completes the definition of a word by linking it
+ * into the main list
+ */
+void
+ficlDictionaryUnsmudge(ficlDictionary *dictionary)
+{
+ ficlWord *word = dictionary->smudge;
+ ficlHash *hash = dictionary->compilationWordlist;
+
+ FICL_DICTIONARY_ASSERT(dictionary, hash);
+ FICL_DICTIONARY_ASSERT(dictionary, word);
+
+ /*
+ * :noname words never get linked into the list...
+ */
+ if (word->length > 0)
+ ficlHashInsertWord(hash, word);
+ word->flags &= ~(FICL_WORD_SMUDGED);
+}
+
+/*
+ * d i c t W h e r e
+ * Returns the value of the HERE pointer -- the address
+ * of the next free ficlCell in the dictionary
+ */
+ficlCell *
+ficlDictionaryWhere(ficlDictionary *dictionary)
+{
+ return (dictionary->here);
+}