/*******************************************************************
** f l o a t . c
** Forth Inspired Command Language
** ANS Forth FLOAT word-set written in C
** Author: Guy Carver & John Sadler (john_sadler@alum.mit.edu)
** Created: Apr 2001
** $Id: float.c,v 1.8 2001/12/05 07:21:34 jsadler 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
**    documentation and/or other materials provided with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
*/

/* $FreeBSD: src/sys/boot/ficl/float.c,v 1.1 2002/04/09 17:45:11 dcs Exp $ */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include "ficl.h"

#if FICL_WANT_FLOAT

/*******************************************************************
** Do float addition r1 + r2.
** f+ ( r1 r2 -- r )
*******************************************************************/
static void Fadd(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 1);
#endif

    f = POPFLOAT();
    f += GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do float subtraction r1 - r2.
** f- ( r1 r2 -- r )
*******************************************************************/
static void Fsub(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 1);
#endif

    f = POPFLOAT();
    f = GETTOPF().f - f;
    SETTOPF(f);
}

/*******************************************************************
** Do float multiplication r1 * r2.
** f* ( r1 r2 -- r )
*******************************************************************/
static void Fmul(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 1);
#endif

    f = POPFLOAT();
    f *= GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do float negation.
** fnegate ( r -- r )
*******************************************************************/
static void Fnegate(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 1);
#endif

    f = -GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do float division r1 / r2.
** f/ ( r1 r2 -- r )
*******************************************************************/
static void Fdiv(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 1);
#endif

    f = POPFLOAT();
    f = GETTOPF().f / f;
    SETTOPF(f);
}

/*******************************************************************
** Do float + integer r + n.
** f+i ( r n -- r )
*******************************************************************/
static void Faddi(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    f = (FICL_FLOAT)POPINT();
    f += GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do float - integer r - n.
** f-i ( r n -- r )
*******************************************************************/
static void Fsubi(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    f = GETTOPF().f;
    f -= (FICL_FLOAT)POPINT();
    SETTOPF(f);
}

/*******************************************************************
** Do float * integer r * n.
** f*i ( r n -- r )
*******************************************************************/
static void Fmuli(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    f = (FICL_FLOAT)POPINT();
    f *= GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do float / integer r / n.
** f/i ( r n -- r )
*******************************************************************/
static void Fdivi(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    f = GETTOPF().f;
    f /= (FICL_FLOAT)POPINT();
    SETTOPF(f);
}

/*******************************************************************
** Do integer - float n - r.
** i-f ( n r -- r )
*******************************************************************/
static void isubf(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    f = (FICL_FLOAT)POPINT();
    f -= GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do integer / float n / r.
** i/f ( n r -- r )
*******************************************************************/
static void idivf(FICL_VM *pVM)
{
    FICL_FLOAT f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1,1);
    vmCheckStack(pVM, 1, 0);
#endif

    f = (FICL_FLOAT)POPINT();
    f /= GETTOPF().f;
    SETTOPF(f);
}

/*******************************************************************
** Do integer to float conversion.
** int>float ( n -- r )
*******************************************************************/
static void itof(FICL_VM *pVM)
{
    float f;

#if FICL_ROBUST > 1
    vmCheckStack(pVM, 1, 0);
    vmCheckFStack(pVM, 0, 1);
#endif

    f = (float)POPINT();
    PUSHFLOAT(f);
}

/*******************************************************************
** Do float to integer conversion.
** float>int ( r -- n )
*******************************************************************/
static void Ftoi(FICL_VM *pVM)
{
    FICL_INT i;

#if FICL_ROBUST > 1
    vmCheckStack(pVM, 0, 1);
    vmCheckFStack(pVM, 1, 0);
#endif

    i = (FICL_INT)POPFLOAT();
    PUSHINT(i);
}

/*******************************************************************
** Floating point constant execution word.
*******************************************************************/
void FconstantParen(FICL_VM *pVM)
{
    FICL_WORD *pFW = pVM->runningWord;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 0, 1);
#endif

    PUSHFLOAT(pFW->param[0].f);
}

/*******************************************************************
** Create a floating point constant.
** fconstant ( r -"name"- )
*******************************************************************/
static void Fconstant(FICL_VM *pVM)
{
    FICL_DICT *dp = vmGetDict(pVM);
    STRINGINFO si = vmGetWord(pVM);

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
#endif

    dictAppendWord2(dp, si, FconstantParen, FW_DEFAULT);
    dictAppendCell(dp, stackPop(pVM->fStack));
}

/*******************************************************************
** Display a float in decimal format.
** f. ( r -- )
*******************************************************************/
static void FDot(FICL_VM *pVM)
{
    float f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
#endif

    f = POPFLOAT();
    sprintf(pVM->pad,"%#f ",f);
    vmTextOut(pVM, pVM->pad, 0);
}

/*******************************************************************
** Display a float in engineering format.
** fe. ( r -- )
*******************************************************************/
static void EDot(FICL_VM *pVM)
{
    float f;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
#endif

    f = POPFLOAT();
    sprintf(pVM->pad,"%#e ",f);
    vmTextOut(pVM, pVM->pad, 0);
}

/**************************************************************************
                        d i s p l a y FS t a c k
** Display the parameter stack (code for "f.s")
** f.s ( -- )
**************************************************************************/
static void displayFStack(FICL_VM *pVM)
{
    int d = stackDepth(pVM->fStack);
    int i;
    CELL *pCell;

    vmCheckFStack(pVM, 0, 0);

    vmTextOut(pVM, "F:", 0);

    if (d == 0)
        vmTextOut(pVM, "[0]", 0);
    else
    {
        ltoa(d, &pVM->pad[1], pVM->base);
        pVM->pad[0] = '[';
        strcat(pVM->pad,"] ");
        vmTextOut(pVM,pVM->pad,0);

        pCell = pVM->fStack->sp - d;
        for (i = 0; i < d; i++)
        {
            sprintf(pVM->pad,"%#f ",(*pCell++).f);
            vmTextOut(pVM,pVM->pad,0);
        }
    }
}

/*******************************************************************
** Do float stack depth.
** fdepth ( -- n )
*******************************************************************/
static void Fdepth(FICL_VM *pVM)
{
    int i;

#if FICL_ROBUST > 1
    vmCheckStack(pVM, 0, 1);
#endif

    i = stackDepth(pVM->fStack);
    PUSHINT(i);
}

/*******************************************************************
** Do float stack drop.
** fdrop ( r -- )
*******************************************************************/
static void Fdrop(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
#endif

    DROPF(1);
}

/*******************************************************************
** Do float stack 2drop.
** f2drop ( r r -- )
*******************************************************************/
static void FtwoDrop(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 0);
#endif

    DROPF(2);
}

/*******************************************************************
** Do float stack dup.
** fdup ( r -- r r )
*******************************************************************/
static void Fdup(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 2);
#endif

    PICKF(0);
}

/*******************************************************************
** Do float stack 2dup.
** f2dup ( r1 r2 -- r1 r2 r1 r2 )
*******************************************************************/
static void FtwoDup(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 4);
#endif

    PICKF(1);
    PICKF(1);
}

/*******************************************************************
** Do float stack over.
** fover ( r1 r2 -- r1 r2 r1 )
*******************************************************************/
static void Fover(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 3);
#endif

    PICKF(1);
}

/*******************************************************************
** Do float stack 2over.
** f2over ( r1 r2 r3 -- r1 r2 r3 r1 r2 )
*******************************************************************/
static void FtwoOver(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 4, 6);
#endif

    PICKF(3);
    PICKF(3);
}

/*******************************************************************
** Do float stack pick.
** fpick ( n -- r )
*******************************************************************/
static void Fpick(FICL_VM *pVM)
{
    CELL c = POP();

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, c.i+1, c.i+2);
#endif

    PICKF(c.i);
}

/*******************************************************************
** Do float stack ?dup.
** f?dup ( r -- r )
*******************************************************************/
static void FquestionDup(FICL_VM *pVM)
{
    CELL c;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 2);
#endif

    c = GETTOPF();
    if (c.f != 0)
        PICKF(0);
}

/*******************************************************************
** Do float stack roll.
** froll ( n -- )
*******************************************************************/
static void Froll(FICL_VM *pVM)
{
    int i = POP().i;
    i = (i > 0) ? i : 0;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, i+1, i+1);
#endif

    ROLLF(i);
}

/*******************************************************************
** Do float stack -roll.
** f-roll ( n -- )
*******************************************************************/
static void FminusRoll(FICL_VM *pVM)
{
    int i = POP().i;
    i = (i > 0) ? i : 0;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, i+1, i+1);
#endif

    ROLLF(-i);
}

/*******************************************************************
** Do float stack rot.
** frot ( r1 r2 r3  -- r2 r3 r1 )
*******************************************************************/
static void Frot(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 3, 3);
#endif

    ROLLF(2);
}

/*******************************************************************
** Do float stack -rot.
** f-rot ( r1 r2 r3  -- r3 r1 r2 )
*******************************************************************/
static void Fminusrot(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 3, 3);
#endif

    ROLLF(-2);
}

/*******************************************************************
** Do float stack swap.
** fswap ( r1 r2 -- r2 r1 )
*******************************************************************/
static void Fswap(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 2);
#endif

    ROLLF(1);
}

/*******************************************************************
** Do float stack 2swap
** f2swap ( r1 r2 r3 r4  -- r3 r4 r1 r2 )
*******************************************************************/
static void FtwoSwap(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 4, 4);
#endif

    ROLLF(3);
    ROLLF(3);
}

/*******************************************************************
** Get a floating point number from a variable.
** f@ ( n -- r )
*******************************************************************/
static void Ffetch(FICL_VM *pVM)
{
    CELL *pCell;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 0, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    pCell = (CELL *)POPPTR();
    PUSHFLOAT(pCell->f);
}

/*******************************************************************
** Store a floating point number into a variable.
** f! ( r n -- )
*******************************************************************/
static void Fstore(FICL_VM *pVM)
{
    CELL *pCell;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
    vmCheckStack(pVM, 1, 0);
#endif

    pCell = (CELL *)POPPTR();
    pCell->f = POPFLOAT();
}

/*******************************************************************
** Add a floating point number to contents of a variable.
** f+! ( r n -- )
*******************************************************************/
static void FplusStore(FICL_VM *pVM)
{
    CELL *pCell;

#if FICL_ROBUST > 1
    vmCheckStack(pVM, 1, 0);
    vmCheckFStack(pVM, 1, 0);
#endif

    pCell = (CELL *)POPPTR();
    pCell->f += POPFLOAT();
}

/*******************************************************************
** Floating point literal execution word.
*******************************************************************/
static void fliteralParen(FICL_VM *pVM)
{
#if FICL_ROBUST > 1
    vmCheckStack(pVM, 0, 1);
#endif

    PUSHFLOAT(*(float*)(pVM->ip));
    vmBranchRelative(pVM, 1);
}

/*******************************************************************
** Compile a floating point literal.
*******************************************************************/
static void fliteralIm(FICL_VM *pVM)
{
    FICL_DICT *dp = vmGetDict(pVM);
    FICL_WORD *pfLitParen = ficlLookup(pVM->pSys, "(fliteral)");

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
#endif

    dictAppendCell(dp, LVALUEtoCELL(pfLitParen));
    dictAppendCell(dp, stackPop(pVM->fStack));
}

/*******************************************************************
** Do float 0= comparison r = 0.0.
** f0= ( r -- T/F )
*******************************************************************/
static void FzeroEquals(FICL_VM *pVM)
{
    CELL c;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);                   /* Make sure something on float stack. */
    vmCheckStack(pVM, 0, 1);                    /* Make sure room for result. */
#endif

    c.i = FICL_BOOL(POPFLOAT() == 0);
    PUSH(c);
}

/*******************************************************************
** Do float 0< comparison r < 0.0.
** f0< ( r -- T/F )
*******************************************************************/
static void FzeroLess(FICL_VM *pVM)
{
    CELL c;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);                   /* Make sure something on float stack. */
    vmCheckStack(pVM, 0, 1);                    /* Make sure room for result. */
#endif

    c.i = FICL_BOOL(POPFLOAT() < 0);
    PUSH(c);
}

/*******************************************************************
** Do float 0> comparison r > 0.0.
** f0> ( r -- T/F )
*******************************************************************/
static void FzeroGreater(FICL_VM *pVM)
{
    CELL c;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
    vmCheckStack(pVM, 0, 1);
#endif

    c.i = FICL_BOOL(POPFLOAT() > 0);
    PUSH(c);
}

/*******************************************************************
** Do float = comparison r1 = r2.
** f= ( r1 r2 -- T/F )
*******************************************************************/
static void FisEqual(FICL_VM *pVM)
{
    float x, y;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 0);
    vmCheckStack(pVM, 0, 1);
#endif

    x = POPFLOAT();
    y = POPFLOAT();
    PUSHINT(FICL_BOOL(x == y));
}

/*******************************************************************
** Do float < comparison r1 < r2.
** f< ( r1 r2 -- T/F )
*******************************************************************/
static void FisLess(FICL_VM *pVM)
{
    float x, y;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 0);
    vmCheckStack(pVM, 0, 1);
#endif

    y = POPFLOAT();
    x = POPFLOAT();
    PUSHINT(FICL_BOOL(x < y));
}

/*******************************************************************
** Do float > comparison r1 > r2.
** f> ( r1 r2 -- T/F )
*******************************************************************/
static void FisGreater(FICL_VM *pVM)
{
    float x, y;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 2, 0);
    vmCheckStack(pVM, 0, 1);
#endif

    y = POPFLOAT();
    x = POPFLOAT();
    PUSHINT(FICL_BOOL(x > y));
}


/*******************************************************************
** Move float to param stack (assumes they both fit in a single CELL)
** f>s 
*******************************************************************/
static void FFrom(FICL_VM *pVM)
{
    CELL c;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 1, 0);
    vmCheckStack(pVM, 0, 1);
#endif

    c = stackPop(pVM->fStack);
    stackPush(pVM->pStack, c);
    return;
}

static void ToF(FICL_VM *pVM)
{
    CELL c;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 0, 1);
    vmCheckStack(pVM, 1, 0);
#endif

    c = stackPop(pVM->pStack);
    stackPush(pVM->fStack, c);
    return;
}


/**************************************************************************
                     F l o a t P a r s e S t a t e
** Enum to determine the current segement of a floating point number
** being parsed.
**************************************************************************/
#define NUMISNEG 1
#define EXPISNEG 2

typedef enum _floatParseState
{
    FPS_START,
    FPS_ININT,
    FPS_INMANT,
    FPS_STARTEXP,
    FPS_INEXP
} FloatParseState;

/**************************************************************************
                     f i c l P a r s e F l o a t N u m b e r
** pVM -- Virtual Machine pointer.
** si -- String to parse.
** Returns 1 if successful, 0 if not.
**************************************************************************/
int ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si )
{
    unsigned char ch, digit;
    char *cp;
    FICL_COUNT count;
    float power;
    float accum = 0.0f;
    float mant = 0.1f;
    FICL_INT exponent = 0;
    char flag = 0;
    FloatParseState estate = FPS_START;

#if FICL_ROBUST > 1
    vmCheckFStack(pVM, 0, 1);
#endif

    /*
    ** floating point numbers only allowed in base 10 
    */
    if (pVM->base != 10)
        return(0);


    cp = SI_PTR(si);
    count = (FICL_COUNT)SI_COUNT(si);

    /* Loop through the string's characters. */
    while ((count--) && ((ch = *cp++) != 0))
    {
        switch (estate)
        {
            /* At start of the number so look for a sign. */
            case FPS_START:
            {
                estate = FPS_ININT;
                if (ch == '-')
                {
                    flag |= NUMISNEG;
                    break;
                }
                if (ch == '+')
                {
                    break;
                }
            } /* Note!  Drop through to FPS_ININT */
            /*
            **Converting integer part of number.
            ** Only allow digits, decimal and 'E'. 
            */
            case FPS_ININT:
            {
                if (ch == '.')
                {
                    estate = FPS_INMANT;
                }
                else if ((ch == 'e') || (ch == 'E'))
                {
                    estate = FPS_STARTEXP;
                }
                else
                {
                    digit = (unsigned char)(ch - '0');
                    if (digit > 9)
                        return(0);

                    accum = accum * 10 + digit;

                }
                break;
            }
            /*
            ** Processing the fraction part of number.
            ** Only allow digits and 'E' 
            */
            case FPS_INMANT:
            {
                if ((ch == 'e') || (ch == 'E'))
                {
                    estate = FPS_STARTEXP;
                }
                else
                {
                    digit = (unsigned char)(ch - '0');
                    if (digit > 9)
                        return(0);

                    accum += digit * mant;
                    mant *= 0.1f;
                }
                break;
            }
            /* Start processing the exponent part of number. */
            /* Look for sign. */
            case FPS_STARTEXP:
            {
                estate = FPS_INEXP;

                if (ch == '-')
                {
                    flag |= EXPISNEG;
                    break;
                }
                else if (ch == '+')
                {
                    break;
                }
            }       /* Note!  Drop through to FPS_INEXP */
            /*
            ** Processing the exponent part of number.
            ** Only allow digits. 
            */
            case FPS_INEXP:
            {
                digit = (unsigned char)(ch - '0');
                if (digit > 9)
                    return(0);

                exponent = exponent * 10 + digit;

                break;
            }
        }
    }

    /* If parser never made it to the exponent this is not a float. */
    if (estate < FPS_STARTEXP)
        return(0);

    /* Set the sign of the number. */
    if (flag & NUMISNEG)
        accum = -accum;

    /* If exponent is not 0 then adjust number by it. */
    if (exponent != 0)
    {
        /* Determine if exponent is negative. */
        if (flag & EXPISNEG)
        {
            exponent = -exponent;
        }
        /* power = 10^x */
        power = (float)pow(10.0, exponent);
        accum *= power;
    }

    PUSHFLOAT(accum);

    return(1);
}

#endif  /* FICL_WANT_FLOAT */

/**************************************************************************
** Add float words to a system's dictionary.
** pSys -- Pointer to the FICL sytem to add float words to.
**************************************************************************/
void ficlCompileFloat(FICL_SYSTEM *pSys)
{
    FICL_DICT *dp = pSys->dp;
    assert(dp);

#if FICL_WANT_FLOAT
    dictAppendWord(dp, ">float",    ToF,            FW_DEFAULT);
    /* d>f */
    dictAppendWord(dp, "f!",        Fstore,         FW_DEFAULT);
    dictAppendWord(dp, "f*",        Fmul,           FW_DEFAULT);
    dictAppendWord(dp, "f+",        Fadd,           FW_DEFAULT);
    dictAppendWord(dp, "f-",        Fsub,           FW_DEFAULT);
    dictAppendWord(dp, "f/",        Fdiv,           FW_DEFAULT);
    dictAppendWord(dp, "f0<",       FzeroLess,      FW_DEFAULT);
    dictAppendWord(dp, "f0=",       FzeroEquals,    FW_DEFAULT);
    dictAppendWord(dp, "f<",        FisLess,        FW_DEFAULT);
 /* 
    f>d 
 */
    dictAppendWord(dp, "f@",        Ffetch,         FW_DEFAULT);
 /* 
    falign 
    faligned 
 */
    dictAppendWord(dp, "fconstant", Fconstant,      FW_DEFAULT);
    dictAppendWord(dp, "fdepth",    Fdepth,         FW_DEFAULT);
    dictAppendWord(dp, "fdrop",     Fdrop,          FW_DEFAULT);
    dictAppendWord(dp, "fdup",      Fdup,           FW_DEFAULT);
    dictAppendWord(dp, "fliteral",  fliteralIm,     FW_IMMEDIATE);
/*
    float+
    floats
    floor
    fmax
    fmin
*/
    dictAppendWord(dp, "f?dup",     FquestionDup,   FW_DEFAULT);
    dictAppendWord(dp, "f=",        FisEqual,       FW_DEFAULT);
    dictAppendWord(dp, "f>",        FisGreater,     FW_DEFAULT);
    dictAppendWord(dp, "f0>",       FzeroGreater,   FW_DEFAULT);
    dictAppendWord(dp, "f2drop",    FtwoDrop,       FW_DEFAULT);
    dictAppendWord(dp, "f2dup",     FtwoDup,        FW_DEFAULT);
    dictAppendWord(dp, "f2over",    FtwoOver,       FW_DEFAULT);
    dictAppendWord(dp, "f2swap",    FtwoSwap,       FW_DEFAULT);
    dictAppendWord(dp, "f+!",       FplusStore,     FW_DEFAULT);
    dictAppendWord(dp, "f+i",       Faddi,          FW_DEFAULT);
    dictAppendWord(dp, "f-i",       Fsubi,          FW_DEFAULT);
    dictAppendWord(dp, "f*i",       Fmuli,          FW_DEFAULT);
    dictAppendWord(dp, "f/i",       Fdivi,          FW_DEFAULT);
    dictAppendWord(dp, "int>float", itof,           FW_DEFAULT);
    dictAppendWord(dp, "float>int", Ftoi,           FW_DEFAULT);
    dictAppendWord(dp, "f.",        FDot,           FW_DEFAULT);
    dictAppendWord(dp, "f.s",       displayFStack,  FW_DEFAULT);
    dictAppendWord(dp, "fe.",       EDot,           FW_DEFAULT);
    dictAppendWord(dp, "fover",     Fover,          FW_DEFAULT);
    dictAppendWord(dp, "fnegate",   Fnegate,        FW_DEFAULT);
    dictAppendWord(dp, "fpick",     Fpick,          FW_DEFAULT);
    dictAppendWord(dp, "froll",     Froll,          FW_DEFAULT);
    dictAppendWord(dp, "frot",      Frot,           FW_DEFAULT);
    dictAppendWord(dp, "fswap",     Fswap,          FW_DEFAULT);
    dictAppendWord(dp, "i-f",       isubf,          FW_DEFAULT);
    dictAppendWord(dp, "i/f",       idivf,          FW_DEFAULT);

    dictAppendWord(dp, "float>",    FFrom,          FW_DEFAULT);

    dictAppendWord(dp, "f-roll",    FminusRoll,     FW_DEFAULT);
    dictAppendWord(dp, "f-rot",     Fminusrot,      FW_DEFAULT);
    dictAppendWord(dp, "(fliteral)", fliteralParen, FW_COMPILE);

    ficlSetEnv(pSys, "floating",       FICL_FALSE);  /* not all required words are present */
    ficlSetEnv(pSys, "floating-ext",   FICL_FALSE);
    ficlSetEnv(pSys, "floating-stack", FICL_DEFAULT_STACK);
#endif
    return;
}
