3 * Forth Inspired Command Language - programming tools
4 * Author: John Sadler (john_sadler@alum.mit.edu)
5 * Created: 20 June 2000
6 * $Id: tools.c,v 1.12 2010/08/12 13:57:22 asau Exp $
9 * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
10 * All rights reserved.
12 * Get the latest Ficl release at http://ficl.sourceforge.net
14 * I am interested in hearing from anyone who uses Ficl. If you have
15 * a problem, a success story, a defect, an enhancement request, or
16 * if you would like to contribute to the Ficl release, please
17 * contact me by email at the address above.
19 * L I C E N S E and D I S C L A I M E R
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
24 * 1. Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SEE needs information about the addresses of functions that
46 * are the CFAs of colon definitions, constants, variables, DOES>
47 * words, and so on. It gets this information from a table and supporting
48 * functions in words.c.
49 * fiColonParen fiDoDoes createParen fiVariableParen fiUserParen fiConstantParen
51 * Step and break debugger for Ficl
52 * debug ( xt -- ) Start debugging an xt
54 * Specify breakpoint default action
59 extern void exit(int);
61 static void ficlPrimitiveStepIn(ficlVm
*vm
);
62 static void ficlPrimitiveStepOver(ficlVm
*vm
);
63 static void ficlPrimitiveStepBreak(ficlVm
*vm
);
66 ficlCallbackAssert(ficlCallback
*callback
, int expression
,
67 char *expressionString
, char *filename
, int line
)
71 static char buffer
[256];
72 sprintf(buffer
, "ASSERTION FAILED at %s:%d: \"%s\"\n",
73 filename
, line
, expressionString
);
74 ficlCallbackTextOut(callback
, buffer
);
77 #else /* FICL_ROBUST >= 1 */
78 FICL_IGNORE(callback
);
79 FICL_IGNORE(expression
);
80 FICL_IGNORE(expressionString
);
81 FICL_IGNORE(filename
);
83 #endif /* FICL_ROBUST >= 1 */
88 * Set a breakpoint at the current value of IP by
89 * storing that address in a BREAKPOINT record
92 ficlVmSetBreak(ficlVm
*vm
, ficlBreakpoint
*pBP
)
94 ficlWord
*pStep
= ficlSystemLookup(vm
->callback
.system
, "step-break");
95 FICL_VM_ASSERT(vm
, pStep
);
97 pBP
->address
= vm
->ip
;
103 * d e b u g P r o m p t
106 ficlDebugPrompt(ficlVm
*vm
, int debug
)
109 setenv("prompt", "dbg> ", 1);
111 setenv("prompt", "${interpret}", 1);
116 isPrimitive(ficlWord
*word
)
118 ficlWordKind wk
= ficlWordClassify(word
);
119 return ((wk
!= COLON
) && (wk
!= DOES
));
124 * d i c t H a s h S u m m a r y
125 * Calculate a figure of merit for the dictionary hash table based
126 * on the average search depth for all the words in the dictionary,
127 * assuming uniform distribution of target keys. The figure of merit
128 * is the ratio of the total search depth for all keys in the table
129 * versus a theoretical optimum that would be achieved if the keys
130 * were distributed into the table as evenly as possible.
131 * The figure would be worse if the hash table used an open
132 * addressing scheme (i.e. collisions resolved by searching the
133 * table for an empty slot) for a given size table.
137 ficlPrimitiveHashSummary(ficlVm
*vm
)
139 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
150 int nAvg
, nRem
, nDepth
;
152 FICL_VM_DICTIONARY_CHECK(vm
, dictionary
, 0);
154 pFHash
= dictionary
->wordlists
[dictionary
->wordlistCount
- 1];
155 hash
= pFHash
->table
;
159 for (i
= 0; i
< size
; i
++) {
169 avg
+= (double)(n
* (n
+1)) / 2.0;
177 /* Calc actual avg search depth for this hash */
180 /* Calc best possible performance with this size hash */
181 nAvg
= nWords
/ size
;
182 nRem
= nWords
% size
;
183 nDepth
= size
* (nAvg
* (nAvg
+1))/2 + (nAvg
+1)*nRem
;
184 best
= (double)nDepth
/nWords
;
186 sprintf(vm
->pad
, "%d bins, %2.0f%% filled, Depth: "
187 "Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%\n",
188 size
, (double)nFilled
* 100.0 / size
, nMax
,
189 avg
, best
, 100.0 * best
/ avg
);
191 ficlVmTextOut(vm
, vm
->pad
);
196 * Here's the outer part of the decompiler. It's
197 * just a big nested conditional that checks the
198 * CFA of the word to decompile for each kind of
199 * known word-builder code, and tries to do
200 * something appropriate. If the CFA is not recognized,
201 * just indicate that it is a primitive.
204 ficlPrimitiveSeeXT(ficlVm
*vm
)
209 word
= (ficlWord
*)ficlStackPopPointer(vm
->dataStack
);
210 kind
= ficlWordClassify(word
);
213 case FICL_WORDKIND_COLON
:
214 sprintf(vm
->pad
, ": %.*s\n", word
->length
, word
->name
);
215 ficlVmTextOut(vm
, vm
->pad
);
216 ficlDictionarySee(ficlVmGetDictionary(vm
), word
,
219 case FICL_WORDKIND_DOES
:
220 ficlVmTextOut(vm
, "does>\n");
221 ficlDictionarySee(ficlVmGetDictionary(vm
),
222 (ficlWord
*)word
->param
->p
, &(vm
->callback
));
224 case FICL_WORDKIND_CREATE
:
225 ficlVmTextOut(vm
, "create\n");
227 case FICL_WORDKIND_VARIABLE
:
228 sprintf(vm
->pad
, "variable = %ld (%#lx)\n",
229 (long)word
->param
->i
, (long unsigned)word
->param
->u
);
230 ficlVmTextOut(vm
, vm
->pad
);
233 case FICL_WORDKIND_USER
:
234 sprintf(vm
->pad
, "user variable %ld (%#lx)\n",
235 (long)word
->param
->i
, (long unsigned)word
->param
->u
);
236 ficlVmTextOut(vm
, vm
->pad
);
239 case FICL_WORDKIND_CONSTANT
:
240 sprintf(vm
->pad
, "constant = %ld (%#lx)\n",
241 (long)word
->param
->i
, (long unsigned)word
->param
->u
);
242 ficlVmTextOut(vm
, vm
->pad
);
244 case FICL_WORDKIND_2CONSTANT
:
245 sprintf(vm
->pad
, "constant = %ld %ld (%#lx %#lx)\n",
246 (long)word
->param
[1].i
, (long)word
->param
->i
,
247 (long unsigned)word
->param
[1].u
,
248 (long unsigned)word
->param
->u
);
249 ficlVmTextOut(vm
, vm
->pad
);
253 sprintf(vm
->pad
, "%.*s is a primitive\n", word
->length
,
255 ficlVmTextOut(vm
, vm
->pad
);
259 if (word
->flags
& FICL_WORD_IMMEDIATE
) {
260 ficlVmTextOut(vm
, "immediate\n");
263 if (word
->flags
& FICL_WORD_COMPILE_ONLY
) {
264 ficlVmTextOut(vm
, "compile-only\n");
269 ficlPrimitiveSee(ficlVm
*vm
)
271 ficlPrimitiveTick(vm
);
272 ficlPrimitiveSeeXT(vm
);
276 * f i c l D e b u g X T
278 * Given an xt of a colon definition or a word defined by DOES>, set the
279 * VM up to debug the word: push IP, set the xt as the next thing to execute,
280 * set a breakpoint at its first instruction, and run to the breakpoint.
281 * Note: the semantics of this word are equivalent to "step in"
284 ficlPrimitiveDebugXT(ficlVm
*vm
)
286 ficlWord
*xt
= ficlStackPopPointer(vm
->dataStack
);
287 ficlWordKind wk
= ficlWordClassify(xt
);
289 ficlStackPushPointer(vm
->dataStack
, xt
);
290 ficlPrimitiveSeeXT(vm
);
293 case FICL_WORDKIND_COLON
:
294 case FICL_WORDKIND_DOES
:
296 * Run the colon code and set a breakpoint at the next
299 ficlVmExecuteWord(vm
, xt
);
300 ficlVmSetBreak(vm
, &(vm
->callback
.system
->breakpoint
));
303 ficlVmExecuteWord(vm
, xt
);
311 * Execute the next instruction, stepping into it if it's a colon definition
312 * or a does> word. This is the easy kind of step.
315 ficlPrimitiveStepIn(ficlVm
*vm
)
318 * Do one step of the inner loop
320 ficlVmExecuteWord(vm
, *vm
->ip
++);
323 * Now set a breakpoint at the next instruction
325 ficlVmSetBreak(vm
, &(vm
->callback
.system
->breakpoint
));
331 * Execute the next instruction atomically. This requires some insight into
332 * the memory layout of compiled code. Set a breakpoint at the next instruction
333 * in this word, and run until we hit it
336 ficlPrimitiveStepOver(ficlVm
*vm
)
340 ficlWord
*pStep
= ficlSystemLookup(vm
->callback
.system
, "step-break");
341 FICL_VM_ASSERT(vm
, pStep
);
344 kind
= ficlWordClassify(word
);
347 case FICL_WORDKIND_COLON
:
348 case FICL_WORDKIND_DOES
:
350 * assume that the next ficlCell holds an instruction
351 * set a breakpoint there and return to the inner interpreter
353 vm
->callback
.system
->breakpoint
.address
= vm
->ip
+ 1;
354 vm
->callback
.system
->breakpoint
.oldXT
= vm
->ip
[1];
358 ficlPrimitiveStepIn(vm
);
364 * s t e p - b r e a k
366 * Handles breakpoints for stepped execution.
367 * Upon entry, breakpoint contains the address and replaced instruction
368 * of the current breakpoint.
369 * Clear the breakpoint
370 * Get a command from the console.
371 * i (step in) - execute the current instruction and set a new breakpoint
373 * o (step over) - execute the current instruction to completion and set
374 * a new breakpoint at the IP
375 * g (go) - execute the current instruction and exit
376 * q (quit) - abort current word
377 * b (toggle breakpoint)
380 extern char *ficlDictionaryInstructionNames
[];
383 ficlPrimitiveStepBreak(ficlVm
*vm
)
391 FICL_VM_ASSERT(vm
, vm
->callback
.system
->breakpoint
.address
);
392 FICL_VM_ASSERT(vm
, vm
->callback
.system
->breakpoint
.oldXT
);
395 * Clear the breakpoint that caused me to run
396 * Restore the original instruction at the breakpoint,
399 vm
->ip
= (ficlIp
)(vm
->callback
.system
->breakpoint
.address
);
400 *vm
->ip
= vm
->callback
.system
->breakpoint
.oldXT
;
403 * If there's an onStep, do it
405 pOnStep
= ficlSystemLookup(vm
->callback
.system
, "on-step");
407 ficlVmExecuteXT(vm
, pOnStep
);
410 * Print the name of the next instruction
412 word
= vm
->callback
.system
->breakpoint
.oldXT
;
414 if ((((ficlInstruction
)word
) > ficlInstructionInvalid
) &&
415 (((ficlInstruction
)word
) < ficlInstructionLast
))
416 sprintf(vm
->pad
, "next: %s (instruction %ld)\n",
417 ficlDictionaryInstructionNames
[(long)word
],
420 sprintf(vm
->pad
, "next: %s\n", word
->name
);
421 if (strcmp(word
->name
, "interpret") == 0)
425 ficlVmTextOut(vm
, vm
->pad
);
426 ficlDebugPrompt(vm
, debug
);
431 command
= ficlVmGetWord(vm
);
433 switch (command
.text
[0]) {
435 ficlPrimitiveStepIn(vm
);
439 ficlPrimitiveStepOver(vm
);
447 xt
= ficlDictionaryFindEnclosingWord(
448 ficlVmGetDictionary(vm
), (ficlCell
*)(vm
->ip
));
450 ficlStackPushPointer(vm
->dataStack
, xt
);
451 ficlPrimitiveSeeXT(vm
);
453 ficlVmTextOut(vm
, "sorry - can't do that\n");
455 ficlVmThrow(vm
, FICL_VM_STATUS_RESTART
);
460 ficlDebugPrompt(vm
, 0);
461 ficlVmThrow(vm
, FICL_VM_STATUS_ABORT
);
465 * Take whatever's left in the TIB and feed it to a
466 * subordinate ficlVmExecuteString
470 ficlWord
*oldRunningWord
= vm
->runningWord
;
472 FICL_STRING_SET_POINTER(s
,
473 vm
->tib
.text
+ vm
->tib
.index
);
474 FICL_STRING_SET_LENGTH(s
,
475 vm
->tib
.end
- FICL_STRING_GET_POINTER(s
));
477 returnValue
= ficlVmExecuteString(vm
, s
);
479 if (returnValue
== FICL_VM_STATUS_OUT_OF_TEXT
) {
480 returnValue
= FICL_VM_STATUS_RESTART
;
481 vm
->runningWord
= oldRunningWord
;
482 ficlVmTextOut(vm
, "\n");
484 if (returnValue
== FICL_VM_STATUS_ERROR_EXIT
)
485 ficlDebugPrompt(vm
, 0);
487 ficlVmThrow(vm
, returnValue
);
495 "g -- Go (execute to completion)\n"
496 "l -- List source code\n"
497 "q -- Quit (stop debugging and abort)\n"
498 "x -- eXecute the rest of the line "
500 ficlDebugPrompt(vm
, 1);
501 ficlVmThrow(vm
, FICL_VM_STATUS_RESTART
);
505 ficlDebugPrompt(vm
, 0);
511 * Signal the system to shut down - this causes ficlExec to return
512 * VM_USEREXIT. The rest is up to you.
515 ficlPrimitiveBye(ficlVm
*vm
)
517 ficlVmThrow(vm
, FICL_VM_STATUS_USER_EXIT
);
521 * d i s p l a y S t a c k
523 * Display the parameter stack (code for ".s")
529 ficlDictionary
*dictionary
;
534 ficlStackDisplayCallback(void *c
, ficlCell
*cell
)
536 struct stackContext
*context
= (struct stackContext
*)c
;
540 snprintf(buffer
, sizeof (buffer
), "[0x%016lx %3d]: %20ld (0x%016lx)\n",
541 (unsigned long)cell
, context
->count
++, (long)cell
->i
,
542 (unsigned long)cell
->u
);
544 snprintf(buffer
, sizeof (buffer
), "[0x%08x %3d]: %12d (0x%08x)\n",
545 (unsigned)cell
, context
->count
++, cell
->i
, cell
->u
);
548 ficlVmTextOut(context
->vm
, buffer
);
553 ficlStackDisplay(ficlStack
*stack
, ficlStackWalkFunction callback
,
556 ficlVm
*vm
= stack
->vm
;
558 struct stackContext myContext
;
560 FICL_STACK_CHECK(stack
, 0, 0);
563 sprintf(buffer
, "[%s stack has %d entries, top at 0x%016lx]\n",
564 stack
->name
, ficlStackDepth(stack
), (unsigned long)stack
->top
);
566 sprintf(buffer
, "[%s stack has %d entries, top at 0x%08x]\n",
567 stack
->name
, ficlStackDepth(stack
), (unsigned)stack
->top
);
569 ficlVmTextOut(vm
, buffer
);
571 if (callback
== NULL
) {
574 context
= &myContext
;
575 callback
= ficlStackDisplayCallback
;
577 ficlStackWalk(stack
, callback
, context
, FICL_FALSE
);
580 sprintf(buffer
, "[%s stack base at 0x%016lx]\n", stack
->name
,
581 (unsigned long)stack
->base
);
583 sprintf(buffer
, "[%s stack base at 0x%08x]\n", stack
->name
,
584 (unsigned)stack
->base
);
586 ficlVmTextOut(vm
, buffer
);
590 ficlVmDisplayDataStack(ficlVm
*vm
)
592 ficlStackDisplay(vm
->dataStack
, NULL
, NULL
);
596 ficlStackDisplaySimpleCallback(void *c
, ficlCell
*cell
)
598 struct stackContext
*context
= (struct stackContext
*)c
;
601 sprintf(buffer
, "%s%ld", context
->count
? " " : "", (long)cell
->i
);
603 ficlVmTextOut(context
->vm
, buffer
);
608 ficlVmDisplayDataStackSimple(ficlVm
*vm
)
610 ficlStack
*stack
= vm
->dataStack
;
612 struct stackContext context
;
614 FICL_STACK_CHECK(stack
, 0, 0);
616 sprintf(buffer
, "[%d] ", ficlStackDepth(stack
));
617 ficlVmTextOut(vm
, buffer
);
621 ficlStackWalk(stack
, ficlStackDisplaySimpleCallback
, &context
,
626 ficlReturnStackDisplayCallback(void *c
, ficlCell
*cell
)
628 struct stackContext
*context
= (struct stackContext
*)c
;
632 sprintf(buffer
, "[0x%016lx %3d] %20ld (0x%016lx)", (unsigned long)cell
,
633 context
->count
++, cell
->i
, cell
->u
);
635 sprintf(buffer
, "[0x%08x %3d] %12d (0x%08x)", (unsigned)cell
,
636 context
->count
++, cell
->i
, cell
->u
);
640 * Attempt to find the word that contains the return
641 * stack address (as if it is part of a colon definition).
642 * If this works, also print the name of the word.
644 if (ficlDictionaryIncludes(context
->dictionary
, cell
->p
)) {
646 word
= ficlDictionaryFindEnclosingWord(context
->dictionary
,
649 int offset
= (ficlCell
*)cell
->p
- &word
->param
[0];
650 sprintf(buffer
+ strlen(buffer
), ", %s + %d ",
654 strcat(buffer
, "\n");
655 ficlVmTextOut(context
->vm
, buffer
);
660 ficlVmDisplayReturnStack(ficlVm
*vm
)
662 struct stackContext context
;
665 context
.dictionary
= ficlVmGetDictionary(vm
);
666 ficlStackDisplay(vm
->returnStack
, ficlReturnStackDisplayCallback
,
671 * f o r g e t - w i d
674 ficlPrimitiveForgetWid(ficlVm
*vm
)
676 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
679 hash
= (ficlHash
*)ficlStackPopPointer(vm
->dataStack
);
680 ficlHashForget(hash
, dictionary
->here
);
685 * TOOLS EXT ( "<spaces>name" -- )
686 * Skip leading space delimiters. Parse name delimited by a space.
687 * Find name, then delete name from the dictionary along with all
688 * words added to the dictionary after name. An ambiguous
689 * condition exists if name cannot be found.
691 * If the Search-Order word set is present, FORGET searches the
692 * compilation word list. An ambiguous condition exists if the
693 * compilation word list is deleted.
696 ficlPrimitiveForget(ficlVm
*vm
)
699 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
700 ficlHash
*hash
= dictionary
->compilationWordlist
;
702 ficlPrimitiveTick(vm
);
703 where
= ((ficlWord
*)ficlStackPopPointer(vm
->dataStack
))->name
;
704 ficlHashForget(hash
, where
);
705 dictionary
->here
= FICL_POINTER_TO_CELL(where
);
714 ficlPrimitiveWords(ficlVm
*vm
)
716 ficlDictionary
*dictionary
= ficlVmGetDictionary(vm
);
717 ficlHash
*hash
= dictionary
->wordlists
[dictionary
->wordlistCount
- 1];
727 cp
= getenv("COLUMNS");
729 * using strtol for now. TODO: refactor number conversion from
730 * ficlPrimitiveToNumber() and use it instead.
735 columns
= strtol(cp
, NULL
, 0);
738 * the pad is fixed size area, it's better to allocate
739 * dedicated buffer space to deal with custom terminal sizes.
741 pPad
= malloc(columns
+ 1);
743 ficlVmThrowError(vm
, "Error: out of memory");
746 for (i
= 0; i
< hash
->size
; i
++) {
747 for (wp
= hash
->table
[i
]; wp
!= NULL
; wp
= wp
->link
, nWords
++) {
748 if (wp
->length
== 0) /* ignore :noname defs */
751 /* prevent line wrap due to long words */
752 if (nChars
+ wp
->length
>= columns
) {
753 pPad
[nChars
++] = '\n';
756 if (pager_output(pPad
))
761 nChars
+= sprintf(pPad
+ nChars
, "%s", cp
);
763 if (nChars
> columns
- 10) {
764 pPad
[nChars
++] = '\n';
767 if (pager_output(pPad
))
770 len
= nCOLWIDTH
- nChars
% nCOLWIDTH
;
772 pPad
[nChars
++] = ' ';
775 if (nChars
> columns
- 10) {
776 pPad
[nChars
++] = '\n';
779 if (pager_output(pPad
))
786 pPad
[nChars
++] = '\n';
789 ficlVmTextOut(vm
, pPad
);
792 sprintf(pPad
, "Dictionary: %d words, %ld cells used of %u total\n",
793 nWords
, (long)(dictionary
->here
- dictionary
->base
),
804 * Print symbols defined in the environment
807 ficlPrimitiveListEnv(ficlVm
*vm
)
809 ficlDictionary
*dictionary
= vm
->callback
.system
->environment
;
810 ficlHash
*hash
= dictionary
->forthWordlist
;
816 for (i
= 0; i
< hash
->size
; i
++) {
817 for (word
= hash
->table
[i
]; word
!= NULL
;
818 word
= word
->link
, counter
++) {
819 sprintf(vm
->pad
, "%s\n", word
->name
);
820 if (pager_output(vm
->pad
))
825 sprintf(vm
->pad
, "Environment: %d words, %ld cells used of %u total\n",
826 counter
, (long)(dictionary
->here
- dictionary
->base
),
828 pager_output(vm
->pad
);
835 * This word lists the parse steps in order
838 ficlPrimitiveParseStepList(ficlVm
*vm
)
841 ficlSystem
*system
= vm
->callback
.system
;
842 FICL_VM_ASSERT(vm
, system
);
844 ficlVmTextOut(vm
, "Parse steps:\n");
845 ficlVmTextOut(vm
, "lookup\n");
847 for (i
= 0; i
< FICL_MAX_PARSE_STEPS
; i
++) {
848 if (system
->parseList
[i
] != NULL
) {
849 ficlVmTextOut(vm
, system
->parseList
[i
]->name
);
850 ficlVmTextOut(vm
, "\n");
857 * e n v C o n s t a n t
858 * Ficl interface to ficlSystemSetEnvironment and ficlSetEnvD - allow Ficl
859 * code to set environment constants...
862 ficlPrimitiveEnvConstant(ficlVm
*vm
)
865 FICL_STACK_CHECK(vm
->dataStack
, 1, 0);
867 ficlVmGetWordToPad(vm
);
868 value
= ficlStackPopUnsigned(vm
->dataStack
);
869 ficlDictionarySetConstant(ficlSystemGetEnvironment(vm
->callback
.system
),
870 vm
->pad
, (ficlUnsigned
)value
);
874 ficlPrimitiveEnv2Constant(ficlVm
*vm
)
878 FICL_STACK_CHECK(vm
->dataStack
, 2, 0);
880 ficlVmGetWordToPad(vm
);
881 value
= ficlStackPop2Integer(vm
->dataStack
);
882 ficlDictionarySet2Constant(
883 ficlSystemGetEnvironment(vm
->callback
.system
), vm
->pad
, value
);
888 * f i c l C o m p i l e T o o l s
889 * Builds wordset for debugger and TOOLS optional word set
892 ficlSystemCompileTools(ficlSystem
*system
)
894 ficlDictionary
*dictionary
= ficlSystemGetDictionary(system
);
895 ficlDictionary
*environment
= ficlSystemGetEnvironment(system
);
897 FICL_SYSTEM_ASSERT(system
, dictionary
);
898 FICL_SYSTEM_ASSERT(system
, environment
);
902 * TOOLS and TOOLS EXT
904 ficlDictionarySetPrimitive(dictionary
, ".s", ficlVmDisplayDataStack
,
906 ficlDictionarySetPrimitive(dictionary
, ".s-simple",
907 ficlVmDisplayDataStackSimple
, FICL_WORD_DEFAULT
);
908 ficlDictionarySetPrimitive(dictionary
, "bye", ficlPrimitiveBye
,
910 ficlDictionarySetPrimitive(dictionary
, "forget", ficlPrimitiveForget
,
912 ficlDictionarySetPrimitive(dictionary
, "see", ficlPrimitiveSee
,
914 ficlDictionarySetPrimitive(dictionary
, "words", ficlPrimitiveWords
,
918 * Set TOOLS environment query values
920 ficlDictionarySetConstant(environment
, "tools", FICL_TRUE
);
921 ficlDictionarySetConstant(environment
, "tools-ext", FICL_FALSE
);
926 ficlDictionarySetPrimitive(dictionary
, "r.s", ficlVmDisplayReturnStack
,
928 ficlDictionarySetPrimitive(dictionary
, ".env", ficlPrimitiveListEnv
,
930 ficlDictionarySetPrimitive(dictionary
, "env-constant",
931 ficlPrimitiveEnvConstant
, FICL_WORD_DEFAULT
);
932 ficlDictionarySetPrimitive(dictionary
, "env-2constant",
933 ficlPrimitiveEnv2Constant
, FICL_WORD_DEFAULT
);
934 ficlDictionarySetPrimitive(dictionary
, "debug-xt", ficlPrimitiveDebugXT
,
936 ficlDictionarySetPrimitive(dictionary
, "parse-order",
937 ficlPrimitiveParseStepList
, FICL_WORD_DEFAULT
);
938 ficlDictionarySetPrimitive(dictionary
, "step-break",
939 ficlPrimitiveStepBreak
, FICL_WORD_DEFAULT
);
940 ficlDictionarySetPrimitive(dictionary
, "forget-wid",
941 ficlPrimitiveForgetWid
, FICL_WORD_DEFAULT
);
942 ficlDictionarySetPrimitive(dictionary
, "see-xt", ficlPrimitiveSeeXT
,
946 ficlDictionarySetPrimitive(dictionary
, ".hash",
947 ficlPrimitiveHashSummary
, FICL_WORD_DEFAULT
);