Bring in ficl version 2.03. No version bump for loader.

This commit is contained in:
Daniel C. Sobral 1999-09-29 04:43:16 +00:00
parent 0212898e1c
commit de271252c9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=51786
21 changed files with 1503 additions and 833 deletions

View File

@ -37,7 +37,7 @@
#ifdef BOOT_FORTH
#include "ficl.h"
#define RETURN(x) stackPushINT32(bf_vm->pStack,!x); return(x)
#define RETURN(x) stackPushINT(bf_vm->pStack,!x); return(x)
extern FICL_VM *bf_vm;
#else

View File

@ -84,7 +84,7 @@ bf_command(FICL_VM *vm)
panic("callout for unknown command '%s'", name);
/* Check whether we have been compiled or are being interpreted */
if (stackPopINT32(vm->pStack)) {
if (stackPopINT(vm->pStack)) {
/*
* Get parameters from stack, in the format:
* an un ... a2 u2 a1 u1 n --
@ -92,7 +92,7 @@ bf_command(FICL_VM *vm)
* address/size for strings, and they will be concatenated
* in LIFO order.
*/
nstrings = stackPopINT32(vm->pStack);
nstrings = stackPopINT(vm->pStack);
for (i = 0, len = 0; i < nstrings; i++)
len += stackFetch(vm->pStack, i * 2).i + 1;
line = malloc(strlen(name) + len + 1);
@ -100,7 +100,7 @@ bf_command(FICL_VM *vm)
if (nstrings)
for (i = 0; i < nstrings; i++) {
len = stackPopINT32(vm->pStack);
len = stackPopINT(vm->pStack);
cp = stackPopPtr(vm->pStack);
strcat(line, " ");
strncat(line, cp, len);
@ -131,7 +131,7 @@ bf_command(FICL_VM *vm)
}
free(line);
/* This is going to be thrown!!! */
stackPushINT32(vm->pStack,result);
stackPushINT(vm->pStack,result);
}
/*
@ -232,17 +232,17 @@ bf_init(void)
char create_buf[41]; /* 31 characters-long builtins */
int fd;
ficlInitSystem(8000); /* Default dictionary ~4000 cells */
ficlInitSystem(10000); /* Default dictionary ~4000 cells */
bf_vm = ficlNewVM();
/* Builtin constructor word */
ficlExec(bf_vm, BUILTIN_CONSTRUCTOR, -1);
ficlExec(bf_vm, BUILTIN_CONSTRUCTOR);
/* make all commands appear as Forth words */
SET_FOREACH(cmdp, Xcommand_set) {
ficlBuild((*cmdp)->c_name, bf_command, FW_DEFAULT);
sprintf(create_buf, "builtin: %s", (*cmdp)->c_name);
ficlExec(bf_vm, create_buf, -1);
ficlExec(bf_vm, create_buf);
}
/* Export some version numbers so that code can detect the loader/host version */
@ -271,9 +271,7 @@ bf_run(char *line)
id = bf_vm->sourceID;
bf_vm->sourceID.i = -1;
vmPushIP(bf_vm, &pInterp);
result = ficlExec(bf_vm, line, -1);
vmPopIP(bf_vm);
result = ficlExec(bf_vm, line);
bf_vm->sourceID = id;
DEBUG("ficlExec '%s' = %d", line, result);

View File

@ -9,7 +9,8 @@ SRCS= ${BASE_SRCS} softcore.c
CLEANFILES= softcore.c testmain
# Standard softwords
SOFTWORDS= softcore.fr jhlocal.fr marker.fr freebsd.fr
SOFTWORDS= softcore.fr jhlocal.fr marker.fr freebsd.fr ficllocal.fr \
ifbrack.fr
# Optional OO extension softwords
#SOFTWORDS+= oo.fr classes.fr

View File

@ -7,6 +7,8 @@
**
*******************************************************************/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdio.h>
#include <stdlib.h>
@ -22,9 +24,10 @@
******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith
*/
UNS64 ficlLongMul(UNS32 x, UNS32 y)
#if PORTABLE_LONGMULDIV == 0
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
{
UNS64 q;
DPUNS q;
u_int64_t qx;
qx = (u_int64_t)x * (u_int64_t) y;
@ -35,7 +38,7 @@ UNS64 ficlLongMul(UNS32 x, UNS32 y)
return q;
}
UNSQR ficlLongDiv(UNS64 q, UNS32 y)
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
{
UNSQR result;
u_int64_t qx, qh;
@ -48,6 +51,7 @@ UNSQR ficlLongDiv(UNS64 q, UNS32 y)
return result;
}
#endif
void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
{
@ -88,8 +92,8 @@ ficlOutb(FICL_VM *pVM)
u_char c;
u_int32_t port;
port=stackPopUNS32(pVM->pStack);
c=(u_char)stackPopINT32(pVM->pStack);
port=stackPopUNS(pVM->pStack);
c=(u_char)stackPopINT(pVM->pStack);
outb(port,c);
}
@ -103,9 +107,9 @@ ficlInb(FICL_VM *pVM)
u_char c;
u_int32_t port;
port=stackPopUNS32(pVM->pStack);
port=stackPopUNS(pVM->pStack);
c=inb(port);
stackPushINT32(pVM->pStack,c);
stackPushINT(pVM->pStack,c);
}
#endif
#endif

View File

@ -32,6 +32,8 @@
** send me email at the address above.
*/
/* $FreeBSD$ */
#if !defined (__SYSDEP_H__)
#define __SYSDEP_H__
@ -60,48 +62,75 @@
#endif
/*
** System dependent data type declarations...
*/
#if !defined INT32
#define INT32 int32_t
#define INT32 long
#endif
#if !defined UNS32
#define UNS32 u_int32_t
#define UNS32 unsigned long
#endif
#if !defined UNS16
#define UNS16 u_int16_t
#define UNS16 unsigned short
#endif
#if !defined UNS8
#define UNS8 u_int8_t
#define UNS8 unsigned char
#endif
#if !defined NULL
#define NULL ((void *)0)
#endif
typedef struct
{
UNS32 hi;
UNS32 lo;
} UNS64;
/*
** 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.
*/
#if !defined FICL_INT
#define FICL_INT INT32
#endif
#if !defined FICL_UNS
#define FICL_UNS UNS32
#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
{
UNS32 quot;
UNS32 rem;
FICL_UNS hi;
FICL_UNS lo;
} DPUNS;
typedef struct
{
FICL_UNS quot;
FICL_UNS rem;
} UNSQR;
typedef struct
{
INT32 hi;
INT32 lo;
} INT64;
FICL_INT hi;
FICL_INT lo;
} DPINT;
typedef struct
{
INT32 quot;
INT32 rem;
FICL_INT quot;
FICL_INT rem;
} INTQR;
@ -114,6 +143,30 @@ typedef struct
#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.
@ -192,7 +245,7 @@ typedef struct
** 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.
** machine. 3 would be appropriate for a 64 bit machine.
*/
#if !defined FICL_ALIGN
#define FICL_ALIGN 2
@ -215,9 +268,8 @@ typedef struct
struct vm;
void ficlTextOut(struct vm *pVM, char *msg, int fNewline);
void *ficlMalloc (size_t size);
void *ficlRealloc (void *p, 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
@ -241,12 +293,12 @@ int ficlLockDictionary(short fLock);
/*
** 64 bit integer math support routines: multiply two UNS32s
** to get a 64 bit prodict, & divide the product by an UNS32
** 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).
*/
UNS64 ficlLongMul(UNS32 x, UNS32 y);
UNSQR ficlLongDiv(UNS64 q, UNS32 y);
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
#endif /*__SYSDEP_H__*/

View File

@ -17,6 +17,8 @@
** 29 jun 1998 (sadler) added variable sized hash table support
*/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdio.h>
#include <stdlib.h>
@ -197,7 +199,6 @@ FICL_WORD *dictAppendWord2(FICL_DICT *pDict,
UNS8 flags)
{
FICL_COUNT len = (FICL_COUNT)SI_COUNT(si);
char *name = SI_PTR(si);
char *pName;
FICL_WORD *pFW;
@ -232,7 +233,7 @@ FICL_WORD *dictAppendWord2(FICL_DICT *pDict,
d i c t A p p e n d U N S 3 2
** Append the specified UNS32 to the dictionary
**************************************************************************/
void dictAppendUNS32(FICL_DICT *pDict, UNS32 u)
void dictAppendUNS(FICL_DICT *pDict, UNS32 u)
{
*pDict->here++ = LVALUEtoCELL(u);
return;

View File

@ -21,6 +21,8 @@
** Code is written in ANSI C for portability.
*/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdlib.h>
#else
@ -174,20 +176,30 @@ int ficlBuild(char *name, FICL_CODE code, char flags)
** time to delete the vm, etc -- or you can ignore this
** signal.
**************************************************************************/
int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
int ficlExec(FICL_VM *pVM, char *pText)
{
#ifdef FICL_TRACE
extern int isAFiclWord(FICL_WORD *pFW);
#endif
return ficlExecC(pVM, pText, -1);
}
int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size)
{
static FICL_WORD *pInterp = NULL;
int except;
FICL_WORD *tempFW;
jmp_buf vmState;
TIB saveTib;
FICL_VM VM;
FICL_STACK rStack;
if (!pInterp)
pInterp = ficlLookup("interpret");
assert(pInterp);
assert(pVM);
if (size < 0)
size = strlen(pText);
vmPushTib(pVM, pText, size, &saveTib);
/*
@ -207,106 +219,12 @@ int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
pVM->fRestart = 0;
pVM->runningWord->code(pVM);
}
/*
** the mysterious inner interpreter...
** vmThrow gets you out of this loop with a longjmp()
*/
for (;;)
{
#ifdef FICL_TRACE
CELL c;
char buffer[40];
#endif
tempFW = *pVM->ip++;
#ifdef FICL_TRACE
if (ficl_trace && isAFiclWord(tempFW))
{
extern void literalParen(FICL_VM*);
extern void stringLit(FICL_VM*);
extern void ifParen(FICL_VM*);
extern void branchParen(FICL_VM*);
extern void qDoParen(FICL_VM*);
extern void doParen(FICL_VM*);
extern void loopParen(FICL_VM*);
extern void plusLoopParen(FICL_VM*);
if (tempFW->code == literalParen)
{
c = *PTRtoCELL(pVM->ip);
if (isAFiclWord(c.p))
{
FICL_WORD *pLit = (FICL_WORD *)c.p;
sprintf(buffer, " literal %.*s (%#lx)",
pLit->nName, pLit->name, c.u);
}
else
sprintf(buffer, " literal %ld (%#lx)", c.i, c.u);
}
else if (tempFW->code == stringLit)
{
FICL_STRING *sp = PTRtoSTRING(pVM->ip);
sprintf(buffer, " s\" %.*s\"", sp->count, sp->text);
}
else if (tempFW->code == ifParen)
{
c = *PTRtoCELL(pVM->ip);
if (c.i > 0)
sprintf(buffer, " if / while (branch rel %ld)", c.i);
else
sprintf(buffer, " until (branch rel %ld)", c.i);
}
else if (tempFW->code == branchParen)
{
c = *PTRtoCELL(pVM->ip);
if (c.i > 0)
sprintf(buffer, " else (branch rel %ld)", c.i);
else
sprintf(buffer, " repeat (branch rel %ld)", c.i);
}
else if (tempFW->code == qDoParen)
{
c = *PTRtoCELL(pVM->ip);
sprintf(buffer, " ?do (leave abs %#lx)", c.u);
}
else if (tempFW->code == doParen)
{
c = *PTRtoCELL(pVM->ip);
sprintf(buffer, " do (leave abs %#lx)", c.u);
}
else if (tempFW->code == loopParen)
{
c = *PTRtoCELL(pVM->ip);
sprintf(buffer, " loop (branch rel %ld)", c.i);
}
else if (tempFW->code == plusLoopParen)
{
c = *PTRtoCELL(pVM->ip);
sprintf(buffer, " +loop (branch rel %ld)", c.i);
}
else /* default: print word's name */
{
sprintf(buffer, " %.*s", tempFW->nName, tempFW->name);
}
vmTextOut(pVM, buffer, 1);
}
else if (ficl_trace) /* probably not a word
* - punt and print value
*/
{
sprintf(buffer, " %ld (%#lx)", (PTRtoCELL(pVM->ip))->i, (PTRtoCELL(pVM->ip))->u);
vmTextOut(pVM, buffer, 1);
}
#endif FICL_TRACE
/*
** inline code for
** vmExecute(pVM, tempFW);
*/
pVM->runningWord = tempFW;
tempFW->code(pVM);
else
{ /* set VM up to interpret text */
vmPushIP(pVM, &pInterp);
}
vmInnerLoop(pVM);
break;
case VM_RESTART:
@ -315,6 +233,7 @@ int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
break;
case VM_OUTOFTEXT:
vmPopIP(pVM);
#ifdef TESTMAIN
if ((pVM->state != COMPILE) && (pVM->sourceID.i == 0))
ficlTextOut(pVM, FICL_PROMPT, 0);
@ -322,14 +241,18 @@ int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
break;
case VM_USEREXIT:
case VM_INNEREXIT:
break;
case VM_QUIT:
if (pVM->state == COMPILE)
{
dictAbortDefinition(dp);
memcpy((void*)pVM, (void*)&VM, sizeof(FICL_VM));
memcpy((void*)pVM->rStack, (void*)&rStack, sizeof(FICL_STACK));
#if FICL_WANT_LOCALS
dictEmpty(localp, localp->pForthWords->size);
#endif
}
vmQuit(pVM);
break;
case VM_ERREXIT:
@ -386,7 +309,7 @@ int ficlExecFD(FICL_VM *pVM, int fd)
break;
continue;
}
rval = ficlExec(pVM, cp, i);
rval = ficlExecC(pVM, cp, i);
if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
{
pVM->sourceID = id;
@ -398,12 +321,85 @@ int ficlExecFD(FICL_VM *pVM, int fd)
** any pending REFILLs (as required by FILE wordset)
*/
pVM->sourceID.i = -1;
ficlExec(pVM, "", 0);
ficlExec(pVM, "");
pVM->sourceID = id;
return rval;
}
/**************************************************************************
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)
{
static FICL_WORD *pQuit = NULL;
int except;
jmp_buf vmState;
jmp_buf *oldState;
if (!pQuit)
pQuit = ficlLookup("exit-inner");
assert(pVM);
assert(pQuit);
/*
** 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, &pQuit);
switch (except)
{
case 0:
vmExecute(pVM, pWord);
vmInnerLoop(pVM);
break;
case VM_INNEREXIT:
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;
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
@ -443,7 +439,7 @@ FICL_DICT *ficlGetEnv(void)
** Create an environment variable with a one-CELL payload. ficlSetEnvD
** makes one with a two-CELL payload.
**************************************************************************/
void ficlSetEnv(char *name, UNS32 value)
void ficlSetEnv(char *name, FICL_UNS value)
{
STRINGINFO si;
FICL_WORD *pFW;
@ -464,7 +460,7 @@ void ficlSetEnv(char *name, UNS32 value)
return;
}
void ficlSetEnvD(char *name, UNS32 hi, UNS32 lo)
void ficlSetEnvD(char *name, FICL_UNS hi, FICL_UNS lo)
{
FICL_WORD *pFW;
STRINGINFO si;
@ -500,6 +496,23 @@ FICL_DICT *ficlGetLoc(void)
#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.

View File

@ -27,6 +27,8 @@
** send me email at the address above.
*/
/* $FreeBSD$ */
#if !defined (__FICL_H__)
#define __FICL_H__
/*
@ -114,19 +116,6 @@
** 4. Ficl uses the pad in 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.
** 5. The whole inner interpreter is screwed up. It ought to be detached
** from ficlExec. Also, it should fall in line with exception
** handling by saving state. (sobral)
** 6. EXCEPTION should be cleaned. Right now, it doubles ficlExec's
** inner interpreter. (sobral)
** 7. colonParen must get the inner interpreter working on it's "case"
** *before* returning, so that it becomes possible to execute them
** inside other definitions without recreating the inner interpreter
** or other such hacks. (sobral)
** 8. We now have EXCEPTION word set. Let's:
** 8.1. Use the appropriate exceptions throughout the code.
** 8.2. Print the error messages at ficlExec, so someone can catch
** them first. (sobral)
**
** F o r M o r e I n f o r m a t i o n
**
@ -166,7 +155,9 @@
/*
** 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"
@ -228,9 +219,9 @@ struct ficl_dict;
/*
** the Good Stuff starts here...
*/
#define FICL_VER "2.02"
#ifndef FICL_PROMPT
# define FICL_PROMPT "ok> "
#define FICL_VER "2.03"
#if !defined (FICL_PROMPT)
#define FICL_PROMPT "ok> "
#endif
/*
@ -245,13 +236,13 @@ struct ficl_dict;
/*
** A CELL is the main storage type. It must be large enough
** to contain a pointer or a scalar. Let's be picky and make
** a 32 bit cell explicitly...
** to contain a pointer or a scalar. In order to accommodate
** 32 bit and 64 bit processors, use abstract types for i and u.
*/
typedef union _cell
{
INT32 i;
UNS32 u;
FICL_INT i;
FICL_UNS u;
void *p;
} CELL;
@ -342,7 +333,7 @@ typedef struct
*/
typedef struct _ficlStack
{
UNS32 nCells; /* size of the stack */
FICL_UNS nCells; /* size of the stack */
CELL *pFrame; /* link reg for stack frame */
CELL *sp; /* stack pointer */
CELL base[1]; /* Bottom of the stack */
@ -361,12 +352,12 @@ void stackLink (FICL_STACK *pStack, int nCells);
void stackPick (FICL_STACK *pStack, int n);
CELL stackPop (FICL_STACK *pStack);
void *stackPopPtr (FICL_STACK *pStack);
UNS32 stackPopUNS32 (FICL_STACK *pStack);
INT32 stackPopINT32 (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 stackPushUNS32(FICL_STACK *pStack, UNS32 u);
void stackPushINT32(FICL_STACK *pStack, INT32 i);
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);
@ -459,6 +450,12 @@ typedef struct vm
*/
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.
@ -501,10 +498,11 @@ int wordIsCompileOnly(FICL_WORD *pFW);
/*
** Exit codes for vmThrow
*/
#define VM_OUTOFTEXT -256 /* hungry - normal exit */
#define VM_RESTART -257 /* word needs more text to suxcceed - re-run it */
#define VM_USEREXIT -258 /* user wants to quit */
#define VM_ERREXIT -259 /* interp found an error */
#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_ABORT -1 /* like errexit -- abort */
#define VM_ABORTQ -2 /* like errexit -- abort" */
#define VM_QUIT -56 /* like errexit, but leave pStack & base alone */
@ -528,6 +526,28 @@ 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
*/
#define M_INNER_LOOP(pVM) \
for (;;) \
{ \
FICL_WORD *tempFW = *(pVM)->ip++; \
(pVM)->runningWord = tempFW; \
tempFW->code(pVM); \
}
#if INLINE_INNER_LOOP != 0
#define vmInnerLoop(pVM) M_INNER_LOOP(pVM)
#else
void vmInnerLoop(FICL_VM *pVM);
#endif
/*
** vmCheckStack needs a vm pointer because it might have to say
** something if it finds a problem. Parms popCells and pushCells
@ -546,9 +566,11 @@ void vmCheckStack(FICL_VM *pVM, int popCells, int pushCells);
** 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, INT32 size, TIB *pSaveTib);
void vmPushTib(FICL_VM *pVM, char *text, INT32 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 vmSetTibIndex(pVM, i) (pVM)->tib.index = i
#define vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp
@ -564,11 +586,13 @@ void vmPopTib(FICL_VM *pVM, TIB *pTib);
#pragma warning(disable: 4273)
#endif
char *ltoa( INT32 value, char *string, int radix );
char *ultoa(UNS32 value, char *string, int radix );
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 *skipSpace(char *cp, char *end);
char *caseFold(char *cp);
int strincmp(char *cp1, char *cp2, FICL_COUNT count);
@ -583,7 +607,7 @@ int strincmp(char *cp1, char *cp2, FICL_COUNT count);
** 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 best */
#if !defined HASHSIZE /* Default size of hash table. For most uniform */
#define HASHSIZE 127 /* performance, use a prime number! */
#endif
@ -660,7 +684,7 @@ FICL_WORD *dictAppendWord2(FICL_DICT *pDict,
STRINGINFO si,
FICL_CODE pCode,
UNS8 flags);
void dictAppendUNS32(FICL_DICT *pDict, UNS32 u);
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 nCells);
@ -709,8 +733,8 @@ void ficlTermSystem(void);
** 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 size of the input
** is not known, pass -1.
** 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:
@ -727,7 +751,9 @@ void ficlTermSystem(void);
** Preconditions: successful execution of ficlInitSystem,
** Successful creation and init of the VM by ficlNewVM (or equiv)
*/
int ficlExec(FICL_VM *pVM, char *pText, INT32 size);
int ficlExec (FICL_VM *pVM, char *pText);
int ficlExecC(FICL_VM *pVM, char *pText, INT32 nChars);
int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord);
/*
** ficlExecFD(FICL_VM *pVM, int fd);
@ -745,6 +771,12 @@ int ficlExecFD(FICL_VM *pVM, int fd);
*/
FICL_VM *ficlNewVM(void);
/*
** 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.

View File

@ -7,6 +7,8 @@
**
*******************************************************************/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdio.h>
#include <stdlib.h>
@ -22,9 +24,10 @@
******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith
*/
UNS64 ficlLongMul(UNS32 x, UNS32 y)
#if PORTABLE_LONGMULDIV == 0
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
{
UNS64 q;
DPUNS q;
u_int64_t qx;
qx = (u_int64_t)x * (u_int64_t) y;
@ -35,7 +38,7 @@ UNS64 ficlLongMul(UNS32 x, UNS32 y)
return q;
}
UNSQR ficlLongDiv(UNS64 q, UNS32 y)
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
{
UNSQR result;
u_int64_t qx, qh;
@ -48,6 +51,7 @@ UNSQR ficlLongDiv(UNS64 q, UNS32 y)
return result;
}
#endif
void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
{
@ -88,8 +92,8 @@ ficlOutb(FICL_VM *pVM)
u_char c;
u_int32_t port;
port=stackPopUNS32(pVM->pStack);
c=(u_char)stackPopINT32(pVM->pStack);
port=stackPopUNS(pVM->pStack);
c=(u_char)stackPopINT(pVM->pStack);
outb(port,c);
}
@ -103,9 +107,9 @@ ficlInb(FICL_VM *pVM)
u_char c;
u_int32_t port;
port=stackPopUNS32(pVM->pStack);
port=stackPopUNS(pVM->pStack);
c=inb(port);
stackPushINT32(pVM->pStack,c);
stackPushINT(pVM->pStack,c);
}
#endif
#endif

View File

@ -32,6 +32,8 @@
** send me email at the address above.
*/
/* $FreeBSD$ */
#if !defined (__SYSDEP_H__)
#define __SYSDEP_H__
@ -60,48 +62,75 @@
#endif
/*
** System dependent data type declarations...
*/
#if !defined INT32
#define INT32 int32_t
#define INT32 long
#endif
#if !defined UNS32
#define UNS32 u_int32_t
#define UNS32 unsigned long
#endif
#if !defined UNS16
#define UNS16 u_int16_t
#define UNS16 unsigned short
#endif
#if !defined UNS8
#define UNS8 u_int8_t
#define UNS8 unsigned char
#endif
#if !defined NULL
#define NULL ((void *)0)
#endif
typedef struct
{
UNS32 hi;
UNS32 lo;
} UNS64;
/*
** 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.
*/
#if !defined FICL_INT
#define FICL_INT INT32
#endif
#if !defined FICL_UNS
#define FICL_UNS UNS32
#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
{
UNS32 quot;
UNS32 rem;
FICL_UNS hi;
FICL_UNS lo;
} DPUNS;
typedef struct
{
FICL_UNS quot;
FICL_UNS rem;
} UNSQR;
typedef struct
{
INT32 hi;
INT32 lo;
} INT64;
FICL_INT hi;
FICL_INT lo;
} DPINT;
typedef struct
{
INT32 quot;
INT32 rem;
FICL_INT quot;
FICL_INT rem;
} INTQR;
@ -114,6 +143,30 @@ typedef struct
#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.
@ -192,7 +245,7 @@ typedef struct
** 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.
** machine. 3 would be appropriate for a 64 bit machine.
*/
#if !defined FICL_ALIGN
#define FICL_ALIGN 2
@ -215,9 +268,8 @@ typedef struct
struct vm;
void ficlTextOut(struct vm *pVM, char *msg, int fNewline);
void *ficlMalloc (size_t size);
void *ficlRealloc (void *p, 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
@ -241,12 +293,12 @@ int ficlLockDictionary(short fLock);
/*
** 64 bit integer math support routines: multiply two UNS32s
** to get a 64 bit prodict, & divide the product by an UNS32
** 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).
*/
UNS64 ficlLongMul(UNS32 x, UNS32 y);
UNSQR ficlLongDiv(UNS64 q, UNS32 y);
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
#endif /*__SYSDEP_H__*/

View File

@ -3,18 +3,21 @@
** Forth Inspired Command Language - 64 bit math support routines
** Author: 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!
*******************************************************************/
/* $FreeBSD$ */
#include "ficl.h"
#include "math64.h"
/**************************************************************************
m 6 4 A b s
** Returns the absolute value of an INT64
** Returns the absolute value of an DPINT
**************************************************************************/
INT64 m64Abs(INT64 x)
DPINT m64Abs(DPINT x)
{
if (m64IsNegative(x))
x = m64Negate(x);
@ -51,7 +54,7 @@ INT64 m64Abs(INT64 x)
** 10 -7 3 -1
** -10 -7 -3 1
**************************************************************************/
INTQR m64FlooredDivI(INT64 num, INT32 den)
INTQR m64FlooredDivI(DPINT num, FICL_INT den)
{
INTQR qr;
UNSQR uqr;
@ -71,7 +74,7 @@ INTQR m64FlooredDivI(INT64 num, INT32 den)
signQuot = -signQuot;
}
uqr = ficlLongDiv(m64CastIU(num), (UNS32)den);
uqr = ficlLongDiv(m64CastIU(num), (FICL_UNS)den);
qr = m64CastQRUI(uqr);
if (signQuot < 0)
{
@ -92,9 +95,9 @@ INTQR m64FlooredDivI(INT64 num, INT32 den)
/**************************************************************************
m 6 4 I s N e g a t i v e
** Returns TRUE if the specified INT64 has its sign bit set.
** Returns TRUE if the specified DPINT has its sign bit set.
**************************************************************************/
int m64IsNegative(INT64 x)
int m64IsNegative(DPINT x)
{
return (x.hi < 0);
}
@ -103,15 +106,15 @@ int m64IsNegative(INT64 x)
/**************************************************************************
m 6 4 M a c
** Mixed precision multiply and accumulate primitive for number building.
** Multiplies UNS64 u by UNS32 mul and adds UNS32 add. Mul is typically
** Multiplies DPUNS u by FICL_UNS mul and adds FICL_UNS 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
**************************************************************************/
UNS64 m64Mac(UNS64 u, UNS32 mul, UNS32 add)
DPUNS m64Mac(DPUNS u, FICL_UNS mul, FICL_UNS add)
{
UNS64 resultLo = ficlLongMul(u.lo, mul);
UNS64 resultHi = ficlLongMul(u.hi, mul);
DPUNS resultLo = ficlLongMul(u.lo, mul);
DPUNS resultHi = ficlLongMul(u.hi, mul);
resultLo.hi += resultHi.lo;
resultHi.lo = resultLo.lo + add;
@ -126,11 +129,11 @@ UNS64 m64Mac(UNS64 u, UNS32 mul, UNS32 add)
/**************************************************************************
m 6 4 M u l I
** Multiplies a pair of INT32s and returns an INT64 result.
** Multiplies a pair of FICL_INTs and returns an DPINT result.
**************************************************************************/
INT64 m64MulI(INT32 x, INT32 y)
DPINT m64MulI(FICL_INT x, FICL_INT y)
{
UNS64 prod;
DPUNS prod;
int sign = 1;
if (x < 0)
@ -155,9 +158,9 @@ INT64 m64MulI(INT32 x, INT32 y)
/**************************************************************************
m 6 4 N e g a t e
** Negates an INT64 by complementing and incrementing.
** Negates an DPINT by complementing and incrementing.
**************************************************************************/
INT64 m64Negate(INT64 x)
DPINT m64Negate(DPINT x)
{
x.hi = ~x.hi;
x.lo = ~x.lo;
@ -171,56 +174,56 @@ INT64 m64Negate(INT64 x)
/**************************************************************************
m 6 4 P u s h
** Push an INT64 onto the specified stack in the order required
** Push an DPINT onto the specified stack in the order required
** by ANS Forth (most significant cell on top)
** These should probably be macros...
**************************************************************************/
void i64Push(FICL_STACK *pStack, INT64 i64)
void i64Push(FICL_STACK *pStack, DPINT i64)
{
stackPushINT32(pStack, i64.lo);
stackPushINT32(pStack, i64.hi);
stackPushINT(pStack, i64.lo);
stackPushINT(pStack, i64.hi);
return;
}
void u64Push(FICL_STACK *pStack, UNS64 u64)
void u64Push(FICL_STACK *pStack, DPUNS u64)
{
stackPushINT32(pStack, u64.lo);
stackPushINT32(pStack, u64.hi);
stackPushINT(pStack, u64.lo);
stackPushINT(pStack, u64.hi);
return;
}
/**************************************************************************
m 6 4 P o p
** Pops an INT64 off the stack in the order required by ANS Forth
** Pops an DPINT off the stack in the order required by ANS Forth
** (most significant cell on top)
** These should probably be macros...
**************************************************************************/
INT64 i64Pop(FICL_STACK *pStack)
DPINT i64Pop(FICL_STACK *pStack)
{
INT64 ret;
ret.hi = stackPopINT32(pStack);
ret.lo = stackPopINT32(pStack);
DPINT ret;
ret.hi = stackPopINT(pStack);
ret.lo = stackPopINT(pStack);
return ret;
}
UNS64 u64Pop(FICL_STACK *pStack)
DPUNS u64Pop(FICL_STACK *pStack)
{
UNS64 ret;
ret.hi = stackPopINT32(pStack);
ret.lo = stackPopINT32(pStack);
DPUNS ret;
ret.hi = stackPopINT(pStack);
ret.lo = stackPopINT(pStack);
return ret;
}
/**************************************************************************
m 6 4 S y m m e t r i c D i v
** Divide an INT64 by an INT32 and return an INT32 quotient and an INT32
** remainder. The absolute values of quotient and remainder are not
** Divide an DPINT by a FICL_INT and return a FICL_INT quotient and a
** FICL_INT 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)
**************************************************************************/
INTQR m64SymmetricDivI(INT64 num, INT32 den)
INTQR m64SymmetricDivI(DPINT num, FICL_INT den)
{
INTQR qr;
UNSQR uqr;
@ -240,7 +243,7 @@ INTQR m64SymmetricDivI(INT64 num, INT32 den)
signQuot = -signQuot;
}
uqr = ficlLongDiv(m64CastIU(num), (UNS32)den);
uqr = ficlLongDiv(m64CastIU(num), (FICL_UNS)den);
qr = m64CastQRUI(uqr);
if (signRem < 0)
qr.rem = -qr.rem;
@ -254,39 +257,51 @@ INTQR m64SymmetricDivI(INT64 num, INT32 den)
/**************************************************************************
m 6 4 U M o d
** Divides an UNS64 by base (an UNS16) and returns an UNS16 remainder.
** Writes the quotient back to the original UNS64 as a side effect.
** This operation is typically used to convert an UNS64 to a text string
** Divides a DPUNS by base (an UNS16) and returns an UNS16 remainder.
** Writes the quotient back to the original DPUNS as a side effect.
** This operation is typically used to convert an DPUNS to a text string
** in any base. See words.c:numberSignS, for example.
** Mechanics: performs 4 ficlLongDivs, each of which produces 16 bits
** of the quotient. C does not provide a way to divide an UNS32 by an
** UNS16 and get an UNS32 quotient (ldiv is closest, but it's signed,
** of the quotient. C does not provide a way to divide an FICL_UNS by an
** UNS16 and get an FICL_UNS quotient (ldiv is closest, but it's signed,
** unfortunately), so I've used ficlLongDiv.
**************************************************************************/
UNS16 m64UMod(UNS64 *pUD, UNS16 base)
#if (BITS_PER_CELL == 32)
#define UMOD_SHIFT 16
#define UMOD_MASK 0x0000ffff
#elif (BITS_PER_CELL == 64)
#define UMOD_SHIFT 32
#define UMOD_MASK 0x00000000ffffffff
#endif
UNS16 m64UMod(DPUNS *pUD, UNS16 base)
{
UNS64 ud;
DPUNS ud;
UNSQR qr;
UNS64 result;
DPUNS result;
result.hi = result.lo = 0;
ud.hi = 0;
ud.lo = pUD->hi >> 16;
qr = ficlLongDiv(ud, (UNS32)base);
result.hi = qr.quot << 16;
ud.lo = pUD->hi >> UMOD_SHIFT;
qr = ficlLongDiv(ud, (FICL_UNS)base);
result.hi = qr.quot << UMOD_SHIFT;
ud.lo = (qr.rem << 16) | (pUD->hi & 0x0000ffff);
qr = ficlLongDiv(ud, (UNS32)base);
result.hi |= qr.quot & 0x0000ffff;
ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->hi & UMOD_MASK);
qr = ficlLongDiv(ud, (FICL_UNS)base);
result.hi |= qr.quot & UMOD_MASK;
ud.lo = (qr.rem << 16) | (pUD->lo >> 16);
qr = ficlLongDiv(ud, (UNS32)base);
result.lo = qr.quot << 16;
ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->lo >> UMOD_SHIFT);
qr = ficlLongDiv(ud, (FICL_UNS)base);
result.lo = qr.quot << UMOD_SHIFT;
ud.lo = (qr.rem << 16) | (pUD->lo & 0x0000ffff);
qr = ficlLongDiv(ud, (UNS32)base);
result.lo |= qr.quot & 0x0000ffff;
ud.lo = (qr.rem << UMOD_SHIFT) | (pUD->lo & UMOD_MASK);
qr = ficlLongDiv(ud, (FICL_UNS)base);
result.lo |= qr.quot & UMOD_MASK;
*pUD = result;
@ -294,3 +309,218 @@ UNS16 m64UMod(UNS64 *pUD, UNS16 base)
}
/**************************************************************************
** Contributed by
** Michael A. Gauland gaulandm@mdhost.cse.tek.com
**************************************************************************/
#if PORTABLE_LONGMULDIV != 0
/**************************************************************************
m 6 4 A d d
**
**************************************************************************/
DPUNS m64Add(DPUNS x, DPUNS y)
{
DPUNS result;
int carry;
result.hi = x.hi + y.hi;
result.lo = x.lo + y.lo;
carry = ((x.lo | y.lo) & CELL_HI_BIT) && !(result.lo & CELL_HI_BIT);
carry |= ((x.lo & y.lo) & CELL_HI_BIT);
if (carry)
{
result.hi++;
}
return result;
}
/**************************************************************************
m 6 4 S u b
**
**************************************************************************/
DPUNS m64Sub(DPUNS x, DPUNS y)
{
DPUNS result;
result.hi = x.hi - y.hi;
result.lo = x.lo - y.lo;
if (x.lo < y.lo)
{
result.hi--;
}
return result;
}
/**************************************************************************
m 6 4 A S L
** 64 bit left shift
**************************************************************************/
DPUNS m64ASL( DPUNS x )
{
DPUNS result;
result.hi = x.hi << 1;
if (x.lo & CELL_HI_BIT)
{
result.hi++;
}
result.lo = x.lo << 1;
return result;
}
/**************************************************************************
m 6 4 A S R
** 64 bit right shift (unsigned - no sign extend)
**************************************************************************/
DPUNS m64ASR( DPUNS x )
{
DPUNS result;
result.lo = x.lo >> 1;
if (x.hi & 1)
{
result.lo |= CELL_HI_BIT;
}
result.hi = x.hi >> 1;
return result;
}
/**************************************************************************
m 6 4 O r
** 64 bit bitwise OR
**************************************************************************/
DPUNS m64Or( DPUNS x, DPUNS y )
{
DPUNS result;
result.hi = x.hi | y.hi;
result.lo = x.lo | y.lo;
return result;
}
/**************************************************************************
m 6 4 C o m p a r e
** Return -1 if x < y; 0 if x==y, and 1 if x > y.
**************************************************************************/
int m64Compare(DPUNS x, DPUNS y)
{
int result;
if (x.hi > y.hi)
{
result = +1;
}
else if (x.hi < y.hi)
{
result = -1;
}
else
{
/* High parts are equal */
if (x.lo > y.lo)
{
result = +1;
}
else if (x.lo < y.lo)
{
result = -1;
}
else
{
result = 0;
}
}
return result;
}
/**************************************************************************
f i c l L o n g M u l
** Portable versions of ficlLongMul and ficlLongDiv in C
** Contributed by:
** Michael A. Gauland gaulandm@mdhost.cse.tek.com
**************************************************************************/
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
{
DPUNS result = { 0, 0 };
DPUNS addend;
addend.lo = y;
addend.hi = 0; /* No sign extension--arguments are unsigned */
while (x != 0)
{
if ( x & 1)
{
result = m64Add(result, addend);
}
x >>= 1;
addend = m64ASL(addend);
}
return result;
}
/**************************************************************************
f i c l L o n g D i v
** Portable versions of ficlLongMul and ficlLongDiv in C
** Contributed by:
** Michael A. Gauland gaulandm@mdhost.cse.tek.com
**************************************************************************/
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
{
UNSQR result;
DPUNS quotient;
DPUNS subtrahend;
DPUNS mask;
quotient.lo = 0;
quotient.hi = 0;
subtrahend.lo = y;
subtrahend.hi = 0;
mask.lo = 1;
mask.hi = 0;
while ((m64Compare(subtrahend, q) < 0) &&
(subtrahend.hi & CELL_HI_BIT) == 0)
{
mask = m64ASL(mask);
subtrahend = m64ASL(subtrahend);
}
while (mask.lo != 0 || mask.hi != 0)
{
if (m64Compare(subtrahend, q) <= 0)
{
q = m64Sub( q, subtrahend);
quotient = m64Or(quotient, mask);
}
mask = m64ASR(mask);
subtrahend = m64ASR(subtrahend);
}
result.quot = quotient.lo;
result.rem = q.lo;
return result;
}
#endif

View File

@ -24,8 +24,14 @@
** a problem, a success story, a defect, an enhancement request, or
** if you would like to contribute to the ficl release (yay!), please
** send me email at the address above.
**
** NOTE: this file depends on sysdep.h for the definition
** of PORTABLE_LONGMULDIV and several abstract types.
**
*/
/* $FreeBSD$ */
#if !defined (__MATH64_H__)
#define __MATH64_H__
@ -33,25 +39,37 @@
extern "C" {
#endif
INT64 m64Abs(INT64 x);
int m64IsNegative(INT64 x);
UNS64 m64Mac(UNS64 u, UNS32 mul, UNS32 add);
INT64 m64MulI(INT32 x, INT32 y);
INT64 m64Negate(INT64 x);
INTQR m64FlooredDivI(INT64 num, INT32 den);
void i64Push(FICL_STACK *pStack, INT64 i64);
INT64 i64Pop(FICL_STACK *pStack);
void u64Push(FICL_STACK *pStack, UNS64 u64);
UNS64 u64Pop(FICL_STACK *pStack);
INTQR m64SymmetricDivI(INT64 num, INT32 den);
UNS16 m64UMod(UNS64 *pUD, UNS16 base);
DPINT m64Abs(DPINT x);
int m64IsNegative(DPINT x);
DPUNS m64Mac(DPUNS u, FICL_UNS mul, FICL_UNS add);
DPINT m64MulI(FICL_INT x, FICL_INT y);
DPINT m64Negate(DPINT x);
INTQR m64FlooredDivI(DPINT num, FICL_INT den);
void i64Push(FICL_STACK *pStack, DPINT i64);
DPINT i64Pop(FICL_STACK *pStack);
void u64Push(FICL_STACK *pStack, DPUNS u64);
DPUNS u64Pop(FICL_STACK *pStack);
INTQR m64SymmetricDivI(DPINT num, FICL_INT den);
UNS16 m64UMod(DPUNS *pUD, UNS16 base);
#if PORTABLE_LONGMULDIV != 0 /* see sysdep.h */
DPUNS m64Add(DPUNS x, DPUNS y);
DPUNS m64ASL( DPUNS x );
DPUNS m64ASR( DPUNS x );
int m64Compare(DPUNS x, DPUNS y);
DPUNS m64Or( DPUNS x, DPUNS y );
DPUNS m64Sub(DPUNS x, DPUNS y);
#endif
#define i64Extend(i64) (i64).hi = ((i64).lo < 0) ? -1L : 0
#define m64CastIU(i64) (*(UNS64 *)(&(i64)))
#define m64CastUI(u64) (*(INT64 *)(&(u64)))
#define m64CastIU(i64) (*(DPUNS *)(&(i64)))
#define m64CastUI(u64) (*(DPINT *)(&(u64)))
#define m64CastQRIU(iqr) (*(UNSQR *)(&(iqr)))
#define m64CastQRUI(uqr) (*(INTQR *)(&(uqr)))
#define CELL_HI_BIT (1L << (BITS_PER_CELL-1))
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,49 @@
\ ** 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 --
\
\ $FreeBSD$
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

View File

@ -0,0 +1,56 @@
\ ** ficl/softwords/ifbrack.fr
\ ** ANS conditional compile directives [if] [else] [then]
\ ** Requires ficl 2.0 or greater...
\ $FreeBSD$
hidden dup >search ficl-set-current
: ?[if] ( c-addr u -- c-addr u flag )
2dup 2dup
s" [if]" compare 0= >r
s" [IF]" compare 0= r>
or
;
: ?[else] ( c-addr u -- c-addr u flag )
2dup 2dup
s" [else]" compare 0= >r
s" [ELSE]" compare 0= r>
or
;
: ?[then] ( c-addr u -- c-addr u flag )
2dup 2dup
s" [then]" compare 0= >r
s" [THEN]" compare 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
previous

View File

@ -3,6 +3,8 @@
\ ** John Sadler (john_sadler@alum.mit.edu)
\ ** September, 1998
\ $FreeBSD$
\ ** Ficl USER variables
\ ** See words.c for primitive def'n of USER
\ #if FICL_WANT_USER
@ -49,6 +51,8 @@ decimal 32 constant bl
: erase ( addr u -- ) 0 fill ;
: 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
@ -78,38 +82,6 @@ decimal 32 constant bl
loop drop
;
\ ** Some TOOLS EXT words, straight from the standard
: [else] ( -- )
1 begin \ level
begin
bl word count dup while \ level adr len
2dup s" [IF]" compare 0= >r
2dup s" [if]" compare 0= r> or
if \ level adr len
2drop 1+ \ level'
else \ level adr len
2dup s" [ELSE]" compare 0= >r
2dup s" [else]" compare 0= r> or
if \ level adr len
2drop 1- dup if 1+ then \ level'
else \ level adr len
2dup
s" [THEN]" compare 0= >r \ level adr len
s" [then]" compare 0= r> or
if \ level
1- \ level'
then
then
then ?dup 0= if exit then \ level'
repeat 2drop \ level
refill 0= until \ level
drop
; immediate
: [if] ( flag -- )
0= if postpone [else] then ; immediate
: [then] ( -- ) ; immediate
\ ** SEARCH+EXT words and ficl helpers
\
: wordlist ( -- )

View File

@ -6,6 +6,8 @@
**
*******************************************************************/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdlib.h>
#else
@ -200,12 +202,12 @@ void *stackPopPtr(FICL_STACK *pStack)
return (*--pStack->sp).p;
}
UNS32 stackPopUNS32(FICL_STACK *pStack)
FICL_UNS stackPopUNS(FICL_STACK *pStack)
{
return (*--pStack->sp).u;
}
INT32 stackPopINT32(FICL_STACK *pStack)
FICL_INT stackPopINT(FICL_STACK *pStack)
{
return (*--pStack->sp).i;
}
@ -226,12 +228,12 @@ void stackPushPtr(FICL_STACK *pStack, void *ptr)
*pStack->sp++ = LVALUEtoCELL(ptr);
}
void stackPushUNS32(FICL_STACK *pStack, UNS32 u)
void stackPushUNS(FICL_STACK *pStack, FICL_UNS u)
{
*pStack->sp++ = LVALUEtoCELL(u);
}
void stackPushINT32(FICL_STACK *pStack, INT32 i)
void stackPushINT(FICL_STACK *pStack, FICL_INT i)
{
*pStack->sp++ = LVALUEtoCELL(i);
}

View File

@ -7,6 +7,8 @@
**
*******************************************************************/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdio.h>
#include <stdlib.h>
@ -22,9 +24,10 @@
******************* FreeBSD P O R T B E G I N S H E R E ******************** Michael Smith
*/
UNS64 ficlLongMul(UNS32 x, UNS32 y)
#if PORTABLE_LONGMULDIV == 0
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y)
{
UNS64 q;
DPUNS q;
u_int64_t qx;
qx = (u_int64_t)x * (u_int64_t) y;
@ -35,7 +38,7 @@ UNS64 ficlLongMul(UNS32 x, UNS32 y)
return q;
}
UNSQR ficlLongDiv(UNS64 q, UNS32 y)
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y)
{
UNSQR result;
u_int64_t qx, qh;
@ -48,6 +51,7 @@ UNSQR ficlLongDiv(UNS64 q, UNS32 y)
return result;
}
#endif
void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
{
@ -88,8 +92,8 @@ ficlOutb(FICL_VM *pVM)
u_char c;
u_int32_t port;
port=stackPopUNS32(pVM->pStack);
c=(u_char)stackPopINT32(pVM->pStack);
port=stackPopUNS(pVM->pStack);
c=(u_char)stackPopINT(pVM->pStack);
outb(port,c);
}
@ -103,9 +107,9 @@ ficlInb(FICL_VM *pVM)
u_char c;
u_int32_t port;
port=stackPopUNS32(pVM->pStack);
port=stackPopUNS(pVM->pStack);
c=inb(port);
stackPushINT32(pVM->pStack,c);
stackPushINT(pVM->pStack,c);
}
#endif
#endif

View File

@ -32,6 +32,8 @@
** send me email at the address above.
*/
/* $FreeBSD$ */
#if !defined (__SYSDEP_H__)
#define __SYSDEP_H__
@ -60,48 +62,75 @@
#endif
/*
** System dependent data type declarations...
*/
#if !defined INT32
#define INT32 int32_t
#define INT32 long
#endif
#if !defined UNS32
#define UNS32 u_int32_t
#define UNS32 unsigned long
#endif
#if !defined UNS16
#define UNS16 u_int16_t
#define UNS16 unsigned short
#endif
#if !defined UNS8
#define UNS8 u_int8_t
#define UNS8 unsigned char
#endif
#if !defined NULL
#define NULL ((void *)0)
#endif
typedef struct
{
UNS32 hi;
UNS32 lo;
} UNS64;
/*
** 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.
*/
#if !defined FICL_INT
#define FICL_INT INT32
#endif
#if !defined FICL_UNS
#define FICL_UNS UNS32
#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
{
UNS32 quot;
UNS32 rem;
FICL_UNS hi;
FICL_UNS lo;
} DPUNS;
typedef struct
{
FICL_UNS quot;
FICL_UNS rem;
} UNSQR;
typedef struct
{
INT32 hi;
INT32 lo;
} INT64;
FICL_INT hi;
FICL_INT lo;
} DPINT;
typedef struct
{
INT32 quot;
INT32 rem;
FICL_INT quot;
FICL_INT rem;
} INTQR;
@ -114,6 +143,30 @@ typedef struct
#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.
@ -192,7 +245,7 @@ typedef struct
** 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.
** machine. 3 would be appropriate for a 64 bit machine.
*/
#if !defined FICL_ALIGN
#define FICL_ALIGN 2
@ -215,9 +268,8 @@ typedef struct
struct vm;
void ficlTextOut(struct vm *pVM, char *msg, int fNewline);
void *ficlMalloc (size_t size);
void *ficlRealloc (void *p, 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
@ -241,12 +293,12 @@ int ficlLockDictionary(short fLock);
/*
** 64 bit integer math support routines: multiply two UNS32s
** to get a 64 bit prodict, & divide the product by an UNS32
** 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).
*/
UNS64 ficlLongMul(UNS32 x, UNS32 y);
UNSQR ficlLongDiv(UNS64 q, UNS32 y);
DPUNS ficlLongMul(FICL_UNS x, FICL_UNS y);
UNSQR ficlLongDiv(DPUNS q, FICL_UNS y);
#endif /*__SYSDEP_H__*/

View File

@ -3,9 +3,12 @@
**
*/
/* $FreeBSD$ */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
@ -144,7 +147,7 @@ static void ficlLoad(FICL_VM *pVM)
if (len <= 0)
continue;
result = ficlExec(pVM, cp, len);
result = ficlExecC(pVM, cp, len);
if (result != VM_QUIT && result != VM_USEREXIT && result != VM_OUTOFTEXT )
{
pVM->sourceID = id;
@ -154,7 +157,7 @@ static void ficlLoad(FICL_VM *pVM)
}
}
/*
** Pass an empty line with SOURCE-ID == 0 to flush
** Pass an empty line with SOURCE-ID == -1 to flush
** any pending REFILLs (as required by FILE wordset)
*/
pVM->sourceID.i = -1;
@ -221,14 +224,46 @@ static void ficlBreak(FICL_VM *pVM)
return;
}
static void ficlClock(FICL_VM *pVM)
{
clock_t now = clock();
stackPushUNS(pVM->pStack, (UNS32)now);
return;
}
static void clocksPerSec(FICL_VM *pVM)
{
stackPushUNS(pVM->pStack, CLOCKS_PER_SEC);
return;
}
static void execxt(FICL_VM *pVM)
{
FICL_WORD *pFW;
#if FICL_ROBUST > 1
vmCheckStack(pVM, 1, 0);
#endif
pFW = stackPopPtr(pVM->pStack);
ficlExecXT(pVM, pFW);
return;
}
void buildTestInterface(void)
{
ficlBuild("break", ficlBreak, FW_DEFAULT);
ficlBuild("clock", ficlClock, FW_DEFAULT);
ficlBuild("cd", ficlChDir, FW_DEFAULT);
ficlBuild("execxt", execxt, FW_DEFAULT);
ficlBuild("load", ficlLoad, FW_DEFAULT);
ficlBuild("pwd", ficlGetCWD, FW_DEFAULT);
ficlBuild("system", ficlSystem, FW_DEFAULT);
ficlBuild("spewhash", spewHash, FW_DEFAULT);
ficlBuild("clocks/sec",
clocksPerSec, FW_DEFAULT);
return;
}
@ -236,7 +271,7 @@ void buildTestInterface(void)
int main(int argc, char **argv)
{
char in[256];
char in[nINBUF];
FICL_VM *pVM;
ficlInitSystem(10000);

View File

@ -1,4 +1,4 @@
/*******************************************************************
/*******************************************************************
** v m . c
** Forth Inspired Command Language - virtual machine methods
** Author: John Sadler (john_sadler@alum.mit.edu)
@ -13,6 +13,8 @@
** of the interp.
*/
/* $FreeBSD$ */
#ifdef TESTMAIN
#include <stdlib.h>
#include <stdio.h>
@ -47,11 +49,9 @@ FICL_VM *vmCreate(FICL_VM *pVM, unsigned nPStack, unsigned nRStack)
if (pVM == NULL)
{
pVM = (FICL_VM *)ficlMalloc(sizeof (FICL_VM));
pVM->pStack = NULL;
pVM->rStack = NULL;
pVM->link = NULL;
assert (pVM);
memset(pVM, 0, sizeof (FICL_VM));
}
assert (pVM);
if (pVM->pStack)
stackDelete(pVM->pStack);
@ -87,7 +87,10 @@ void vmDelete (FICL_VM *pVM)
/**************************************************************************
v m E x e c u t e
**
** Sets up the specified word to be run by the inner interpreter.
** Executes the word's code part immediately, but in the case of
** colon definition, the definition itself needs the inner interp
** to complete. This does not happen until control reaches ficlExec
**************************************************************************/
void vmExecute(FICL_VM *pVM, FICL_WORD *pWord)
{
@ -97,6 +100,24 @@ void vmExecute(FICL_VM *pVM, FICL_WORD *pWord)
}
/**************************************************************************
v m I n n e r L o o p
** the mysterious inner interpreter...
** This loop is the address interpreter that makes colon definitions
** work. Upon entry, it assumes that the IP points to an entry in
** a definition (the body of a colon word). It runs one word at a time
** until something does vmThrow. The catcher for this is expected to exist
** in the calling code.
** vmThrow gets you out of this loop with a longjmp()
** Visual C++ 5 chokes on this loop in Release mode. Aargh.
**************************************************************************/
#if INLINE_INNER_LOOP == 0
void vmInnerLoop(FICL_VM *pVM)
{
M_INNER_LOOP(pVM);
}
#endif
/**************************************************************************
v m G e t S t r i n g
** Parses a string out of the VM input buffer and copies up to the first
@ -151,22 +172,23 @@ STRINGINFO vmGetWord(FICL_VM *pVM)
**************************************************************************/
STRINGINFO vmGetWord0(FICL_VM *pVM)
{
char *pSrc = vmGetInBuf(pVM);
char *pSrc = vmGetInBuf(pVM);
char *pEnd = vmGetInBufEnd(pVM);
STRINGINFO si;
UNS32 count = 0;
char ch;
pSrc = skipSpace(pSrc,pVM->tib.end);
pSrc = skipSpace(pSrc, pEnd);
SI_SETPTR(si, pSrc);
for (ch = *pSrc; (pVM->tib.end != pSrc) && (ch != '\0') && !isspace(ch); ch = *++pSrc)
for (ch = *pSrc; (pEnd != pSrc) && !isspace(ch); ch = *++pSrc)
{
count++;
}
SI_SETLEN(si, count);
if ((pVM->tib.end != pSrc) && isspace(ch)) /* skip one trailing delimiter */
if ((pEnd != pSrc) && isspace(ch)) /* skip one trailing delimiter */
pSrc++;
vmUpdateTib(pVM, pSrc);
@ -210,16 +232,16 @@ STRINGINFO vmParseString(FICL_VM *pVM, char delim)
{
STRINGINFO si;
char *pSrc = vmGetInBuf(pVM);
char ch;
char *pEnd = vmGetInBufEnd(pVM);
char ch;
while ((pVM->tib.end != pSrc) && (*pSrc == delim)) /* skip lead delimiters */
while ((pSrc != pEnd) && (*pSrc == delim)) /* skip lead delimiters */
pSrc++;
SI_SETPTR(si, pSrc); /* mark start of text */
for (ch = *pSrc; (pVM->tib.end != pSrc)
&& (ch != delim)
&& (ch != '\0')
for (ch = *pSrc; (pSrc != pEnd)
&& (ch != delim)
&& (ch != '\r')
&& (ch != '\n'); ch = *++pSrc)
{
@ -229,7 +251,7 @@ STRINGINFO vmParseString(FICL_VM *pVM, char delim)
/* set length of result */
SI_SETLEN(si, pSrc - SI_PTR(si));
if ((pVM->tib.end != pSrc) && (*pSrc == delim)) /* gobble trailing delimiter */
if ((pSrc != pEnd) && (*pSrc == delim)) /* gobble trailing delimiter */
pSrc++;
vmUpdateTib(pVM, pSrc);
@ -264,7 +286,7 @@ void vmPushIP(FICL_VM *pVM, IPTYPE newIP)
v m P u s h T i b
** Binds the specified input string to the VM and clears >IN (the index)
**************************************************************************/
void vmPushTib(FICL_VM *pVM, char *text, INT32 size, TIB *pSaveTib)
void vmPushTib(FICL_VM *pVM, char *text, FICL_INT nChars, TIB *pSaveTib)
{
if (pSaveTib)
{
@ -272,7 +294,7 @@ void vmPushTib(FICL_VM *pVM, char *text, INT32 size, TIB *pSaveTib)
}
pVM->tib.cp = text;
pVM->tib.end = text + size;
pVM->tib.end = text + nChars;
pVM->tib.index = 0;
}
@ -361,7 +383,8 @@ void vmTextOut(FICL_VM *pVM, char *text, int fNewline)
**************************************************************************/
void vmThrow(FICL_VM *pVM, int except)
{
longjmp(*(pVM->pState), except);
if (pVM->pState)
longjmp(*(pVM->pState), except);
}
@ -432,33 +455,66 @@ char digit_to_char(int value)
}
/**************************************************************************
i s P o w e r O f T w o
** Tests whether supplied argument is an integer power of 2 (2**n)
** where 32 > n > 1, and returns n if so. Otherwise returns zero.
**************************************************************************/
int isPowerOfTwo(FICL_UNS u)
{
int i = 1;
FICL_UNS t = 2;
for (; ((t <= u) && (t != 0)); i++, t <<= 1)
{
if (u == t)
return i;
}
return 0;
}
/**************************************************************************
l t o a
**
**************************************************************************/
char *ltoa( INT32 value, char *string, int radix )
char *ltoa( FICL_INT value, char *string, int radix )
{ /* convert long to string, any base */
char *cp = string;
int sign = ((radix == 10) && (value < 0));
UNSQR result;
UNS64 v;
int pwr;
assert(radix > 1);
assert(radix < 37);
assert(string);
pwr = isPowerOfTwo((FICL_UNS)radix);
if (sign)
value = -value;
if (value == 0)
*cp++ = '0';
else if (pwr != 0)
{
FICL_UNS v = (FICL_UNS) value;
FICL_UNS mask = (FICL_UNS) ~(-1 << pwr);
while (v)
{
*cp++ = digits[v & mask];
v >>= pwr;
}
}
else
{
UNSQR result;
DPUNS v;
v.hi = 0;
v.lo = (UNS32)value;
v.lo = (FICL_UNS)value;
while (v.lo)
{
result = ficlLongDiv(v, (UNS32)radix);
result = ficlLongDiv(v, (FICL_UNS)radix);
*cp++ = digits[result.rem];
v.lo = result.quot;
}
@ -477,10 +533,10 @@ char *ltoa( INT32 value, char *string, int radix )
u l t o a
**
**************************************************************************/
char *ultoa(UNS32 value, char *string, int radix )
char *ultoa(FICL_UNS value, char *string, int radix )
{ /* convert long to string, any base */
char *cp = string;
UNS64 ud;
DPUNS ud;
UNSQR result;
assert(radix > 1);
@ -554,8 +610,8 @@ int strincmp(char *cp1, char *cp2, FICL_COUNT count)
s k i p S p a c e
** Given a string pointer, returns a pointer to the first non-space
** char of the string, or to the NULL terminator if no such char found.
** If the pointer reaches "end" first, stop there. If you don't want
** that, pass NULL.
** If the pointer reaches "end" first, stop there. Pass NULL to
** suppress this behavior.
**************************************************************************/
char *skipSpace(char *cp, char *end)
{

File diff suppressed because it is too large Load Diff