/*
* t o o l s . c
* Forth Inspired Command Language - programming tools
* Author: John Sadler (john_sadler@alum.mit.edu)
* Created: 20 June 2000
* $Id: tools.c,v 1.12 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
* 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
*
* 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.
*/
/*
* NOTES:
* SEE needs information about the addresses of functions that
* are the CFAs of colon definitions, constants, variables, DOES>
* words, and so on. It gets this information from a table and supporting
* functions in words.c.
* fiColonParen fiDoDoes createParen fiVariableParen fiUserParen fiConstantParen
*
* Step and break debugger for Ficl
* debug ( xt -- ) Start debugging an xt
* Set a breakpoint
* Specify breakpoint default action
*/
#include "ficl.h"
extern void exit(int);
void
{
#if FICL_ROBUST >= 1
if (!expression) {
exit(-1);
}
#else /* FICL_ROBUST >= 1 */
#endif /* FICL_ROBUST >= 1 */
}
/*
* v m S e t B r e a k
* Set a breakpoint at the current value of IP by
* storing that address in a BREAKPOINT record
*/
static void
{
}
/*
* d e b u g P r o m p t
*/
static void
{
if (debug)
else
}
#if 0
static int
{
}
#endif
/*
* 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
{
unsigned size;
unsigned i;
int nMax = 0;
int nWords = 0;
int nFilled;
double best;
for (i = 0; i < size; i++) {
int n = 0;
while (word) {
++n;
++nWords;
}
if (n > nMax)
nMax = n;
if (n == 0)
--nFilled;
}
/* Calc actual avg search depth for this hash */
/* Calc best possible performance with this size hash */
"Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%\n",
}
#endif
/*
* Here's the outer part of the decompiler. It's
* just a big nested conditional that checks the
* CFA of the word to decompile for each kind of
* known word-builder code, and tries to do
* something appropriate. If the CFA is not recognized,
* just indicate that it is a primitive.
*/
static void
{
switch (kind) {
case FICL_WORDKIND_COLON:
break;
case FICL_WORDKIND_DOES:
break;
case FICL_WORDKIND_CREATE:
break;
case FICL_WORDKIND_VARIABLE:
break;
#if FICL_WANT_USER
case FICL_WORDKIND_USER:
break;
#endif
case FICL_WORDKIND_CONSTANT:
break;
case FICL_WORDKIND_2CONSTANT:
break;
default:
break;
}
}
}
}
static void
{
}
/*
* f i c l D e b u g X T
* debug ( xt -- )
* Given an xt of a colon definition or a word defined by DOES>, set the
* VM up to debug the word: push IP, set the xt as the next thing to execute,
* set a breakpoint at its first instruction, and run to the breakpoint.
* Note: the semantics of this word are equivalent to "step in"
*/
static void
{
switch (wk) {
case FICL_WORDKIND_COLON:
case FICL_WORDKIND_DOES:
/*
* Run the colon code and set a breakpoint at the next
* instruction
*/
break;
default:
break;
}
}
/*
* s t e p I n
* Ficl
* Execute the next instruction, stepping into it if it's a colon definition
* or a does> word. This is the easy kind of step.
*/
static void
{
/*
* Do one step of the inner loop
*/
/*
* Now set a breakpoint at the next instruction
*/
}
/*
* s t e p O v e r
* Ficl
* Execute the next instruction atomically. This requires some insight into
* the memory layout of compiled code. Set a breakpoint at the next instruction
* in this word, and run until we hit it
*/
static void
{
switch (kind) {
case FICL_WORDKIND_COLON:
case FICL_WORDKIND_DOES:
/*
* assume that the next ficlCell holds an instruction
* set a breakpoint there and return to the inner interpreter
*/
break;
default:
break;
}
}
/*
* s t e p - b r e a k
* Ficl
* Handles breakpoints for stepped execution.
* Upon entry, breakpoint contains the address and replaced instruction
* of the current breakpoint.
* Clear the breakpoint
* Get a command from the console.
* i (step in) - execute the current instruction and set a new breakpoint
* at the IP
* o (step over) - execute the current instruction to completion and set
* a new breakpoint at the IP
* g (go) - execute the current instruction and exit
* q (quit) - abort current word
* b (toggle breakpoint)
*/
extern char *ficlDictionaryInstructionNames[];
static void
{
/*
* Clear the breakpoint that caused me to run
* Restore the original instruction at the breakpoint,
* and restore the IP
*/
/*
* If there's an onStep, do it
*/
if (pOnStep)
/*
* Print the name of the next instruction
*/
ficlDictionaryInstructionNames[(long)word],
(long)word);
else {
debug = 0;
}
} else {
}
case 'i':
break;
case 'o':
break;
case 'g':
break;
case 'l': {
if (xt) {
} else {
}
break;
}
case 'q':
ficlDebugPrompt(vm, 0);
break;
case 'x': {
/*
* Take whatever's left in the TIB and feed it to a
* subordinate ficlVmExecuteString
*/
int returnValue;
ficlString s;
if (returnValue == FICL_VM_STATUS_OUT_OF_TEXT) {
}
if (returnValue == FICL_VM_STATUS_ERROR_EXIT)
ficlDebugPrompt(vm, 0);
break;
}
default:
"i -- step In\n"
"o -- step Over\n"
"g -- Go (execute to completion)\n"
"l -- List source code\n"
"q -- Quit (stop debugging and abort)\n"
"x -- eXecute the rest of the line "
"as Ficl words\n");
break;
}
ficlDebugPrompt(vm, 0);
}
/*
* b y e
* TOOLS
* Signal the system to shut down - this causes ficlExec to return
* VM_USEREXIT. The rest is up to you.
*/
static void
{
}
/*
* d i s p l a y S t a c k
* TOOLS
* Display the parameter stack (code for ".s")
*/
struct stackContext
{
int count;
};
static ficlInteger
{
#ifdef _LP64
(unsigned long)cell->u);
#else
#endif
return (FICL_TRUE);
}
void
void *context)
{
FICL_STACK_CHECK(stack, 0, 0);
#ifdef _LP64
#else
#endif
}
#ifdef _LP64
#else
#endif
}
void
{
}
static ficlInteger
{
return (FICL_TRUE);
}
void
{
FICL_STACK_CHECK(stack, 0, 0);
}
static ficlInteger
{
#ifdef _LP64
#else
#endif
/*
* Attempt to find the word that contains the return
* stack address (as if it is part of a colon definition).
* If this works, also print the name of the word.
*/
cell->p);
if (word) {
}
}
return (FICL_TRUE);
}
void
{
&context);
}
/*
* f o r g e t - w i d
*/
static void
{
}
/*
* f o r g e t
* TOOLS EXT ( "<spaces>name" -- )
* Skip leading space delimiters. Parse name delimited by a space.
* Find name, then delete name from the dictionary along with all
* words added to the dictionary after name. An ambiguous
* condition exists if name cannot be found.
*
* If the Search-Order word set is present, FORGET searches the
* compilation word list. An ambiguous condition exists if the
* compilation word list is deleted.
*/
static void
{
void *where;
}
/*
* w o r d s
*/
static void
{
int nChars = 0;
int len;
unsigned i;
int nWords = 0;
char *cp;
char *pPad;
int columns;
/*
* using strtol for now. TODO: refactor number conversion from
* ficlPrimitiveToNumber() and use it instead.
*/
columns = 80;
else
/*
* the pad is fixed size area, it's better to allocate
* dedicated buffer space to deal with custom terminal sizes.
*/
pager_open();
continue;
/* prevent line wrap due to long words */
nChars = 0;
if (pager_output(pPad))
goto pager_done;
}
nChars = 0;
if (pager_output(pPad))
goto pager_done;
} else {
while (len-- > 0)
}
nChars = 0;
if (pager_output(pPad))
goto pager_done;
}
}
}
if (nChars > 0) {
nChars = 0;
}
dictionary->size);
pager_close();
}
/*
* l i s t E n v
* Print symbols defined in the environment
*/
static void
{
unsigned i;
int counter = 0;
pager_open();
goto pager_done;
}
}
dictionary->size);
pager_close();
}
/*
* This word lists the parse steps in order
*/
void
{
int i;
for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) {
} else
break;
}
}
/*
* e n v C o n s t a n t
* Ficl interface to ficlSystemSetEnvironment and ficlSetEnvD - allow Ficl
* code to set environment constants...
*/
static void
{
unsigned value;
}
static void
{
}
/*
* f i c l C o m p i l e T o o l s
* Builds wordset for debugger and TOOLS optional word set
*/
void
{
/*
* TOOLS and TOOLS EXT
*/
/*
* Set TOOLS environment query values
*/
/*
* Ficl extras
*/
#if FICL_WANT_FLOAT
#endif
}