3 * Forth Inspired Command Language - dictionary methods
4 * Author: John Sadler (john_sadler@alum.mit.edu)
5 * Created: 19 July 1997
6 * $Id: dictionary.c,v 1.2 2010/09/12 15:14:52 asau Exp $
9 * This file implements the dictionary -- Ficl's model of
10 * memory management. All Ficl words are stored in the
11 * dictionary. A word is a named chunk of data with its
12 * associated code. Ficl treats all words the same, even
13 * precompiled ones, so your words become first-class
14 * extensions of the language. You can even define new
17 * 29 jun 1998 (sadler) added variable sized hash table support
20 * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
21 * All rights reserved.
23 * Get the latest Ficl release at http://ficl.sourceforge.net
25 * I am interested in hearing from anyone who uses Ficl. If you have
26 * a problem, a success story, a defect, an enhancement request, or
27 * if you would like to contribute to the Ficl release, please
28 * contact me by email at the address above.
30 * L I C E N S E and D I S C L A I M E R
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 #define FICL_SAFE_CALLBACK_FROM_SYSTEM(system) \
57 (((system) != NULL) ? &((system)->callback) : NULL)
58 #define FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary) \
59 (((dictionary) != NULL) ? (dictionary)->system : NULL)
60 #define FICL_DICTIONARY_ASSERT(dictionary, expression) \
61 FICL_SYSTEM_ASSERT(FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary), \
65 * d i c t A b o r t D e f i n i t i o n
66 * Abort a definition in process: reclaim its memory and unlink it
67 * from the dictionary list. Assumes that there is a smudged
68 * definition in process...otherwise does nothing.
69 * NOTE: this function is not smart enough to unlink a word that
70 * has been successfully defined (ie linked into a hash). It
71 * only works for defs in process. If the def has been unsmudged,
75 ficlDictionaryAbortDefinition(ficlDictionary
*dictionary
)
78 ficlDictionaryLock(dictionary
, FICL_TRUE
);
79 word
= dictionary
->smudge
;
81 if (word
->flags
& FICL_WORD_SMUDGED
)
82 dictionary
->here
= (ficlCell
*)word
->name
;
84 ficlDictionaryLock(dictionary
, FICL_FALSE
);
89 * Align the dictionary's free space pointer
92 ficlDictionaryAlign(ficlDictionary
*dictionary
)
94 dictionary
->here
= ficlAlignPointer(dictionary
->here
);
99 * Allocate or remove n chars of dictionary space, with
100 * checks for underrun and overrun
103 ficlDictionaryAllot(ficlDictionary
*dictionary
, int n
)
105 char *here
= (char *)dictionary
->here
;
107 dictionary
->here
= FICL_POINTER_TO_CELL(here
);
111 * d i c t A l l o t C e l l s
112 * Reserve space for the requested number of ficlCells in the
113 * dictionary. If nficlCells < 0 , removes space from the dictionary.
116 ficlDictionaryAllotCells(ficlDictionary
*dictionary
, int nficlCells
)
118 dictionary
->here
+= nficlCells
;
122 * d i c t A p p e n d C e l l
123 * Append the specified ficlCell to the dictionary
126 ficlDictionaryAppendCell(ficlDictionary
*dictionary
, ficlCell c
)
128 *dictionary
->here
++ = c
;
132 * d i c t A p p e n d C h a r
133 * Append the specified char to the dictionary
136 ficlDictionaryAppendCharacter(ficlDictionary
*dictionary
, char c
)
138 char *here
= (char *)dictionary
->here
;
140 dictionary
->here
= FICL_POINTER_TO_CELL(here
);
144 * d i c t A p p e n d U N S
145 * Append the specified ficlUnsigned to the dictionary
148 ficlDictionaryAppendUnsigned(ficlDictionary
*dictionary
, ficlUnsigned u
)
153 ficlDictionaryAppendCell(dictionary
, c
);
157 ficlDictionaryAppendData(ficlDictionary
*dictionary
, void *data
,
160 char *here
= (char *)dictionary
->here
;
161 char *oldHere
= here
;
162 char *from
= (char *)data
;
165 ficlDictionaryAlign(dictionary
);
166 return ((char *)dictionary
->here
);
176 dictionary
->here
= FICL_POINTER_TO_CELL(here
);
177 ficlDictionaryAlign(dictionary
);
182 * d i c t C o p y N a m e
183 * Copy up to FICL_NAME_LENGTH characters of the name specified by s into
184 * the dictionary starting at "here", then NULL-terminate the name,
185 * point "here" to the next available byte, and return the address of
186 * the beginning of the name. Used by dictAppendWord.
188 * 1. "here" is guaranteed to be aligned after this operation.
189 * 2. If the string has zero length, align and return "here"
192 ficlDictionaryAppendString(ficlDictionary
*dictionary
, ficlString s
)
194 void *data
= FICL_STRING_GET_POINTER(s
);
195 ficlInteger length
= FICL_STRING_GET_LENGTH(s
);
197 if (length
> FICL_NAME_LENGTH
)
198 length
= FICL_NAME_LENGTH
;
200 return (ficlDictionaryAppendData(dictionary
, data
, length
));
204 ficlDictionaryAppendConstantInstruction(ficlDictionary
*dictionary
,
205 ficlString name
, ficlInstruction instruction
, ficlInteger value
)
207 ficlWord
*word
= ficlDictionaryAppendWord(dictionary
, name
,
208 (ficlPrimitive
)instruction
, FICL_WORD_DEFAULT
);
211 ficlDictionaryAppendUnsigned(dictionary
, value
);
216 ficlDictionaryAppend2ConstantInstruction(ficlDictionary
*dictionary
,
217 ficlString name
, ficlInstruction instruction
, ficl2Integer value
)
219 ficlWord
*word
= ficlDictionaryAppendWord(dictionary
, name
,
220 (ficlPrimitive
)instruction
, FICL_WORD_DEFAULT
);
223 ficlDictionaryAppendUnsigned(dictionary
,
224 FICL_2UNSIGNED_GET_HIGH(value
));
225 ficlDictionaryAppendUnsigned(dictionary
,
226 FICL_2UNSIGNED_GET_LOW(value
));
232 ficlDictionaryAppendConstant(ficlDictionary
*dictionary
, char *name
,
236 FICL_STRING_SET_FROM_CSTRING(s
, name
);
237 return (ficlDictionaryAppendConstantInstruction(dictionary
, s
,
238 ficlInstructionConstantParen
, value
));
242 ficlDictionaryAppend2Constant(ficlDictionary
*dictionary
, char *name
,
246 FICL_STRING_SET_FROM_CSTRING(s
, name
);
247 return (ficlDictionaryAppend2ConstantInstruction(dictionary
, s
,
248 ficlInstruction2ConstantParen
, value
));
252 ficlDictionarySetConstantInstruction(ficlDictionary
*dictionary
,
253 ficlString name
, ficlInstruction instruction
, ficlInteger value
)
255 ficlWord
*word
= ficlDictionaryLookup(dictionary
, name
);
259 word
= ficlDictionaryAppendConstantInstruction(dictionary
,
260 name
, instruction
, value
);
262 word
->code
= (ficlPrimitive
)instruction
;
270 ficlDictionarySetConstant(ficlDictionary
*dictionary
, char *name
,
274 FICL_STRING_SET_FROM_CSTRING(s
, name
);
275 return (ficlDictionarySetConstantInstruction(dictionary
, s
,
276 ficlInstructionConstantParen
, value
));
280 ficlDictionarySet2ConstantInstruction(ficlDictionary
*dictionary
, ficlString s
,
281 ficlInstruction instruction
, ficl2Integer value
)
284 word
= ficlDictionaryLookup(dictionary
, s
);
287 * only reuse the existing word if we're sure it has space for a
291 if ((word
!= NULL
) &&
292 ((((ficlInstruction
)word
->code
) == ficlInstruction2ConstantParen
) ||
293 (((ficlInstruction
)word
->code
) == ficlInstructionF2ConstantParen
)))
295 if ((word
!= NULL
) &&
296 ((((ficlInstruction
)word
->code
) == ficlInstruction2ConstantParen
)))
297 #endif /* FICL_WANT_FLOAT */
299 word
->code
= (ficlPrimitive
)instruction
;
300 word
->param
[0].u
= FICL_2UNSIGNED_GET_HIGH(value
);
301 word
->param
[1].u
= FICL_2UNSIGNED_GET_LOW(value
);
303 word
= ficlDictionaryAppend2ConstantInstruction(dictionary
, s
,
311 ficlDictionarySet2Constant(ficlDictionary
*dictionary
, char *name
,
315 FICL_STRING_SET_FROM_CSTRING(s
, name
);
317 return (ficlDictionarySet2ConstantInstruction(dictionary
, s
,
318 ficlInstruction2ConstantParen
, value
));
322 ficlDictionarySetConstantString(ficlDictionary
*dictionary
, char *name
,
326 ficl2Integer valueAs2Integer
;
327 FICL_2INTEGER_SET(strlen(value
), (intptr_t)value
, valueAs2Integer
);
328 FICL_STRING_SET_FROM_CSTRING(s
, name
);
330 return (ficlDictionarySet2ConstantInstruction(dictionary
, s
,
331 ficlInstruction2ConstantParen
, valueAs2Integer
));
335 * d i c t A p p e n d W o r d
336 * Create a new word in the dictionary with the specified
337 * ficlString, code, and flags. Does not require a NULL-terminated
341 ficlDictionaryAppendWord(ficlDictionary
*dictionary
, ficlString name
,
342 ficlPrimitive code
, ficlUnsigned8 flags
)
344 ficlUnsigned8 length
= (ficlUnsigned8
)FICL_STRING_GET_LENGTH(name
);
348 ficlDictionaryLock(dictionary
, FICL_TRUE
);
351 * NOTE: ficlDictionaryAppendString advances "here" as a side-effect.
352 * It must execute before word is initialized.
354 nameCopy
= ficlDictionaryAppendString(dictionary
, name
);
355 word
= (ficlWord
*)dictionary
->here
;
356 dictionary
->smudge
= word
;
357 word
->hash
= ficlHashCode(name
);
359 word
->semiParen
= ficlInstructionSemiParen
;
360 word
->flags
= (ficlUnsigned8
)(flags
| FICL_WORD_SMUDGED
);
361 word
->length
= length
;
362 word
->name
= nameCopy
;
365 * Point "here" to first ficlCell of new word's param area...
367 dictionary
->here
= word
->param
;
369 if (!(flags
& FICL_WORD_SMUDGED
))
370 ficlDictionaryUnsmudge(dictionary
);
372 ficlDictionaryLock(dictionary
, FICL_FALSE
);
377 * d i c t A p p e n d W o r d
378 * Create a new word in the dictionary with the specified
379 * name, code, and flags. Name must be NULL-terminated.
382 ficlDictionaryAppendPrimitive(ficlDictionary
*dictionary
, char *name
,
383 ficlPrimitive code
, ficlUnsigned8 flags
)
386 FICL_STRING_SET_FROM_CSTRING(s
, name
);
388 return (ficlDictionaryAppendWord(dictionary
, s
, code
, flags
));
392 ficlDictionarySetPrimitive(ficlDictionary
*dictionary
, char *name
,
393 ficlPrimitive code
, ficlUnsigned8 flags
)
398 FICL_STRING_SET_FROM_CSTRING(s
, name
);
399 word
= ficlDictionaryLookup(dictionary
, s
);
402 word
= ficlDictionaryAppendPrimitive(dictionary
, name
,
405 word
->code
= (ficlPrimitive
)code
;
412 ficlDictionaryAppendInstruction(ficlDictionary
*dictionary
, char *name
,
413 ficlInstruction i
, ficlUnsigned8 flags
)
415 return (ficlDictionaryAppendPrimitive(dictionary
, name
,
416 (ficlPrimitive
)i
, (ficlUnsigned8
)(FICL_WORD_INSTRUCTION
| flags
)));
420 ficlDictionarySetInstruction(ficlDictionary
*dictionary
, char *name
,
421 ficlInstruction i
, ficlUnsigned8 flags
)
423 return (ficlDictionarySetPrimitive(dictionary
, name
,
424 (ficlPrimitive
)i
, (ficlUnsigned8
)(FICL_WORD_INSTRUCTION
| flags
)));
428 * d i c t C e l l s A v a i l
429 * Returns the number of empty ficlCells left in the dictionary
432 ficlDictionaryCellsAvailable(ficlDictionary
*dictionary
)
434 return (dictionary
->size
- ficlDictionaryCellsUsed(dictionary
));
438 * d i c t C e l l s U s e d
439 * Returns the number of ficlCells consumed in the dicionary
442 ficlDictionaryCellsUsed(ficlDictionary
*dictionary
)
444 return (dictionary
->here
- dictionary
->base
);
448 * d i c t C r e a t e
449 * Create and initialize a dictionary with the specified number
450 * of ficlCells capacity, and no hashing (hash size == 1).
453 ficlDictionaryCreate(ficlSystem
*system
, unsigned size
)
455 return (ficlDictionaryCreateHashed(system
, size
, 1));
459 ficlDictionaryCreateHashed(ficlSystem
*system
, unsigned size
,
460 unsigned bucketCount
)
462 ficlDictionary
*dictionary
;
465 nAlloc
= sizeof (ficlDictionary
) + (size
* sizeof (ficlCell
))
466 + sizeof (ficlHash
) + (bucketCount
- 1) * sizeof (ficlWord
*);
468 dictionary
= ficlMalloc(nAlloc
);
469 FICL_SYSTEM_ASSERT(system
, dictionary
!= NULL
);
471 dictionary
->size
= size
;
472 dictionary
->system
= system
;
474 ficlDictionaryEmpty(dictionary
, bucketCount
);
479 * d i c t C r e a t e W o r d l i s t
480 * Create and initialize an anonymous wordlist
483 ficlDictionaryCreateWordlist(ficlDictionary
*dictionary
, int bucketCount
)
487 ficlDictionaryAlign(dictionary
);
488 hash
= (ficlHash
*)dictionary
->here
;
489 ficlDictionaryAllot(dictionary
,
490 sizeof (ficlHash
) + (bucketCount
- 1) * sizeof (ficlWord
*));
492 hash
->size
= bucketCount
;
498 * d i c t D e l e t e
499 * Free all memory allocated for the given dictionary
502 ficlDictionaryDestroy(ficlDictionary
*dictionary
)
504 FICL_DICTIONARY_ASSERT(dictionary
, dictionary
!= NULL
);
505 ficlFree(dictionary
);
510 * Empty the dictionary, reset its hash table, and reset its search order.
511 * Clears and (re-)creates the hash table with the size specified by nHash.
514 ficlDictionaryEmpty(ficlDictionary
*dictionary
, unsigned bucketCount
)
518 dictionary
->here
= dictionary
->base
;
520 ficlDictionaryAlign(dictionary
);
521 hash
= (ficlHash
*)dictionary
->here
;
522 ficlDictionaryAllot(dictionary
,
523 sizeof (ficlHash
) + (bucketCount
- 1) * sizeof (ficlWord
*));
525 hash
->size
= bucketCount
;
528 dictionary
->forthWordlist
= hash
;
529 dictionary
->smudge
= NULL
;
530 ficlDictionaryResetSearchOrder(dictionary
);
534 * i s A F i c l W o r d
535 * Vet a candidate pointer carefully to make sure
536 * it's not some chunk o' inline data...
537 * It has to have a name, and it has to look
538 * like it's in the dictionary address range.
539 * NOTE: this excludes :noname words!
542 ficlDictionaryIsAWord(ficlDictionary
*dictionary
, ficlWord
*word
)
544 if ((((ficlInstruction
)word
) > ficlInstructionInvalid
) &&
545 (((ficlInstruction
)word
) < ficlInstructionLast
))
548 if (!ficlDictionaryIncludes(dictionary
, word
))
551 if (!ficlDictionaryIncludes(dictionary
, word
->name
))
554 if ((word
->link
!= NULL
) &&
555 !ficlDictionaryIncludes(dictionary
, word
->link
))
558 if ((word
->length
<= 0) || (word
->name
[word
->length
] != '\0'))
561 if (strlen(word
->name
) != word
->length
)
568 * f i n d E n c l o s i n g W o r d
569 * Given a pointer to something, check to make sure it's an address in the
570 * dictionary. If so, search backwards until we find something that looks
571 * like a dictionary header. If successful, return the address of the
572 * ficlWord found. Otherwise return NULL. nSEARCH_CELLS sets the maximum
573 * neighborhood this func will search before giving up
575 #define nSEARCH_CELLS 100
578 ficlDictionaryFindEnclosingWord(ficlDictionary
*dictionary
, ficlCell
*cell
)
583 if (!ficlDictionaryIncludes(dictionary
, (void *)cell
))
586 for (i
= nSEARCH_CELLS
; i
> 0; --i
, --cell
) {
588 (cell
+ 1 - (sizeof (ficlWord
) / sizeof (ficlCell
)));
589 if (ficlDictionaryIsAWord(dictionary
, word
))
597 * d i c t I n c l u d e s
598 * Returns FICL_TRUE iff the given pointer is within the address range of
602 ficlDictionaryIncludes(ficlDictionary
*dictionary
, void *p
)
604 return ((p
>= (void *) &dictionary
->base
) &&
605 (p
< (void *)(&dictionary
->base
+ dictionary
->size
)));
609 * d i c t L o o k u p
610 * Find the ficlWord that matches the given name and length.
611 * If found, returns the word's address. Otherwise returns NULL.
612 * Uses the search order list to search multiple wordlists.
615 ficlDictionaryLookup(ficlDictionary
*dictionary
, ficlString name
)
617 ficlWord
*word
= NULL
;
620 ficlUnsigned16 hashCode
= ficlHashCode(name
);
622 FICL_DICTIONARY_ASSERT(dictionary
, dictionary
!= NULL
);
624 ficlDictionaryLock(dictionary
, FICL_TRUE
);
626 for (i
= (int)dictionary
->wordlistCount
- 1; (i
>= 0) && (!word
); --i
) {
627 hash
= dictionary
->wordlists
[i
];
628 word
= ficlHashLookup(hash
, name
, hashCode
);
631 ficlDictionaryLock(dictionary
, FICL_FALSE
);
637 * TOOLS ( "<spaces>name" -- )
638 * Display a human-readable representation of the named word's definition.
639 * The source of the representation (object-code decompilation, source
640 * block, etc.) and the particular form of the display is implementation
644 * ficlSeeColon (for proctologists only)
645 * Walks a colon definition, decompiling
646 * on the fly. Knows about primitive control structures.
648 char *ficlDictionaryInstructionNames
[] =
650 #define FICL_TOKEN(token, description) description,
651 #define FICL_INSTRUCTION_TOKEN(token, description, flags) description,
652 #include "ficltokens.h"
654 #undef FICL_INSTRUCTION_TOKEN
658 ficlDictionarySee(ficlDictionary
*dictionary
, ficlWord
*word
,
659 ficlCallback
*callback
)
662 ficlCell
*cell
= word
->param
;
663 ficlCell
*param0
= cell
;
666 for (; cell
->i
!= ficlInstructionSemiParen
; cell
++) {
667 ficlWord
*word
= (ficlWord
*)(cell
->p
);
670 if ((void *)cell
== (void *)buffer
)
674 trace
+= sprintf(trace
, "%3ld ", (long)(cell
- param0
));
676 if (ficlDictionaryIsAWord(dictionary
, word
)) {
677 ficlWordKind kind
= ficlWordClassify(word
);
681 case FICL_WORDKIND_INSTRUCTION
:
682 sprintf(trace
, "%s (instruction %ld)",
683 ficlDictionaryInstructionNames
[(long)word
],
686 case FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT
:
688 sprintf(trace
, "%s (instruction %ld), with "
689 "argument %ld (%#lx)",
690 ficlDictionaryInstructionNames
[(long)word
],
691 (long)word
, (long)c
.i
, (unsigned long)c
.u
);
693 case FICL_WORDKIND_INSTRUCTION_WORD
:
695 "%s :: executes %s (instruction word %ld)",
697 ficlDictionaryInstructionNames
[
698 (long)word
->code
], (long)word
->code
);
700 case FICL_WORDKIND_LITERAL
:
702 if (ficlDictionaryIsAWord(dictionary
, c
.p
) &&
703 (c
.i
>= ficlInstructionLast
)) {
704 ficlWord
*word
= (ficlWord
*)c
.p
;
705 sprintf(trace
, "%.*s ( %#lx literal )",
706 word
->length
, word
->name
,
710 "literal %ld (%#lx)", (long)c
.i
,
713 case FICL_WORDKIND_2LITERAL
:
716 sprintf(trace
, "2literal %ld %ld (%#lx %#lx)",
717 (long)c2
.i
, (long)c
.i
, (unsigned long)c2
.u
,
721 case FICL_WORDKIND_FLITERAL
:
723 sprintf(trace
, "fliteral %f (%#lx)",
724 (double)c
.f
, (unsigned long)c
.u
);
726 #endif /* FICL_WANT_FLOAT */
727 case FICL_WORDKIND_STRING_LITERAL
: {
728 ficlCountedString
*counted
;
729 counted
= (ficlCountedString
*)(void *)++cell
;
731 ficlAlignPointer(counted
->text
+
732 counted
->length
+ 1) - 1;
733 sprintf(trace
, "s\" %.*s\"", counted
->length
,
737 case FICL_WORDKIND_CSTRING_LITERAL
: {
738 ficlCountedString
*counted
;
739 counted
= (ficlCountedString
*)(void *)++cell
;
741 ficlAlignPointer(counted
->text
+
742 counted
->length
+ 1) - 1;
743 sprintf(trace
, "c\" %.*s\"", counted
->length
,
747 case FICL_WORDKIND_BRANCH0
:
749 sprintf(trace
, "branch0 %ld",
750 (long)(cell
+ c
.i
- param0
));
752 case FICL_WORDKIND_BRANCH
:
754 sprintf(trace
, "branch %ld",
755 (long)(cell
+ c
.i
- param0
));
758 case FICL_WORDKIND_QDO
:
760 sprintf(trace
, "?do (leave %ld)",
761 (long)((ficlCell
*)c
.p
- param0
));
763 case FICL_WORDKIND_DO
:
765 sprintf(trace
, "do (leave %ld)",
766 (long)((ficlCell
*)c
.p
- param0
));
768 case FICL_WORDKIND_LOOP
:
770 sprintf(trace
, "loop (branch %ld)",
771 (long)(cell
+ c
.i
- param0
));
773 case FICL_WORDKIND_OF
:
775 sprintf(trace
, "of (branch %ld)",
776 (long)(cell
+ c
.i
- param0
));
778 case FICL_WORDKIND_PLOOP
:
780 sprintf(trace
, "+loop (branch %ld)",
781 (long)(cell
+ c
.i
- param0
));
784 sprintf(trace
, "%.*s", word
->length
,
789 /* probably not a word - punt and print value */
790 sprintf(trace
, "%ld ( %#lx )", (long)cell
->i
,
791 (unsigned long)cell
->u
);
794 ficlCallbackTextOut(callback
, buffer
);
795 ficlCallbackTextOut(callback
, "\n");
798 ficlCallbackTextOut(callback
, ";\n");
802 * d i c t R e s e t S e a r c h O r d e r
803 * Initialize the dictionary search order list to sane state
806 ficlDictionaryResetSearchOrder(ficlDictionary
*dictionary
)
808 FICL_DICTIONARY_ASSERT(dictionary
, dictionary
);
809 dictionary
->compilationWordlist
= dictionary
->forthWordlist
;
810 dictionary
->wordlistCount
= 1;
811 dictionary
->wordlists
[0] = dictionary
->forthWordlist
;
815 * d i c t S e t F l a g s
816 * Changes the flags field of the most recently defined word:
817 * Set all bits that are ones in the set parameter.
820 ficlDictionarySetFlags(ficlDictionary
*dictionary
, ficlUnsigned8 set
)
822 FICL_DICTIONARY_ASSERT(dictionary
, dictionary
->smudge
);
823 dictionary
->smudge
->flags
|= set
;
828 * d i c t C l e a r F l a g s
829 * Changes the flags field of the most recently defined word:
830 * Clear all bits that are ones in the clear parameter.
833 ficlDictionaryClearFlags(ficlDictionary
*dictionary
, ficlUnsigned8 clear
)
835 FICL_DICTIONARY_ASSERT(dictionary
, dictionary
->smudge
);
836 dictionary
->smudge
->flags
&= ~clear
;
840 * d i c t S e t I m m e d i a t e
841 * Set the most recently defined word as IMMEDIATE
844 ficlDictionarySetImmediate(ficlDictionary
*dictionary
)
846 FICL_DICTIONARY_ASSERT(dictionary
, dictionary
->smudge
);
847 dictionary
->smudge
->flags
|= FICL_WORD_IMMEDIATE
;
851 * d i c t U n s m u d g e
852 * Completes the definition of a word by linking it
856 ficlDictionaryUnsmudge(ficlDictionary
*dictionary
)
858 ficlWord
*word
= dictionary
->smudge
;
859 ficlHash
*hash
= dictionary
->compilationWordlist
;
861 FICL_DICTIONARY_ASSERT(dictionary
, hash
);
862 FICL_DICTIONARY_ASSERT(dictionary
, word
);
865 * :noname words never get linked into the list...
867 if (word
->length
> 0)
868 ficlHashInsertWord(hash
, word
);
869 word
->flags
&= ~(FICL_WORD_SMUDGED
);
874 * Returns the value of the HERE pointer -- the address
875 * of the next free ficlCell in the dictionary
878 ficlDictionaryWhere(ficlDictionary
*dictionary
)
880 return (dictionary
->here
);