1/*******************************************************************
2** f l o a t . c
3** Forth Inspired Command Language
4** ANS Forth FLOAT word-set written in C
5** Author: Guy Carver & John Sadler (john_sadler@alum.mit.edu)
6** Created: Apr 2001
7** $Id: float.c,v 1.8 2001/12/05 07:21:34 jsadler Exp $
8*******************************************************************/
9/*
10** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11** All rights reserved.
12**
13** Get the latest Ficl release at http://ficl.sourceforge.net
14**
15** I am interested in hearing from anyone who uses ficl. If you have
16** a problem, a success story, a defect, an enhancement request, or
17** if you would like to contribute to the ficl release, please
18** contact me by email at the address above.
19**
20** L I C E N S E  and  D I S C L A I M E R
21**
22** Redistribution and use in source and binary forms, with or without
23** modification, are permitted provided that the following conditions
24** are met:
25** 1. Redistributions of source code must retain the above copyright
26**    notice, this list of conditions and the following disclaimer.
27** 2. Redistributions in binary form must reproduce the above copyright
28**    notice, this list of conditions and the following disclaimer in the
29**    documentation and/or other materials provided with the distribution.
30**
31** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41** SUCH DAMAGE.
42*/
43
44/* $FreeBSD: stable/11/stand/ficl/float.c 329175 2018-02-12 17:44:35Z kevans $ */
45
46#include "ficl.h"
47
48#if FICL_WANT_FLOAT
49#include <stdlib.h>
50#include <stdio.h>
51#include <string.h>
52#include <ctype.h>
53#include <math.h>
54
55/*******************************************************************
56** Do float addition r1 + r2.
57** f+ ( r1 r2 -- r )
58*******************************************************************/
59static void Fadd(FICL_VM *pVM)
60{
61    FICL_FLOAT f;
62
63#if FICL_ROBUST > 1
64    vmCheckFStack(pVM, 2, 1);
65#endif
66
67    f = POPFLOAT();
68    f += GETTOPF().f;
69    SETTOPF(f);
70}
71
72/*******************************************************************
73** Do float subtraction r1 - r2.
74** f- ( r1 r2 -- r )
75*******************************************************************/
76static void Fsub(FICL_VM *pVM)
77{
78    FICL_FLOAT f;
79
80#if FICL_ROBUST > 1
81    vmCheckFStack(pVM, 2, 1);
82#endif
83
84    f = POPFLOAT();
85    f = GETTOPF().f - f;
86    SETTOPF(f);
87}
88
89/*******************************************************************
90** Do float multiplication r1 * r2.
91** f* ( r1 r2 -- r )
92*******************************************************************/
93static void Fmul(FICL_VM *pVM)
94{
95    FICL_FLOAT f;
96
97#if FICL_ROBUST > 1
98    vmCheckFStack(pVM, 2, 1);
99#endif
100
101    f = POPFLOAT();
102    f *= GETTOPF().f;
103    SETTOPF(f);
104}
105
106/*******************************************************************
107** Do float negation.
108** fnegate ( r -- r )
109*******************************************************************/
110static void Fnegate(FICL_VM *pVM)
111{
112    FICL_FLOAT f;
113
114#if FICL_ROBUST > 1
115    vmCheckFStack(pVM, 1, 1);
116#endif
117
118    f = -GETTOPF().f;
119    SETTOPF(f);
120}
121
122/*******************************************************************
123** Do float division r1 / r2.
124** f/ ( r1 r2 -- r )
125*******************************************************************/
126static void Fdiv(FICL_VM *pVM)
127{
128    FICL_FLOAT f;
129
130#if FICL_ROBUST > 1
131    vmCheckFStack(pVM, 2, 1);
132#endif
133
134    f = POPFLOAT();
135    f = GETTOPF().f / f;
136    SETTOPF(f);
137}
138
139/*******************************************************************
140** Do float + integer r + n.
141** f+i ( r n -- r )
142*******************************************************************/
143static void Faddi(FICL_VM *pVM)
144{
145    FICL_FLOAT f;
146
147#if FICL_ROBUST > 1
148    vmCheckFStack(pVM, 1, 1);
149    vmCheckStack(pVM, 1, 0);
150#endif
151
152    f = (FICL_FLOAT)POPINT();
153    f += GETTOPF().f;
154    SETTOPF(f);
155}
156
157/*******************************************************************
158** Do float - integer r - n.
159** f-i ( r n -- r )
160*******************************************************************/
161static void Fsubi(FICL_VM *pVM)
162{
163    FICL_FLOAT f;
164
165#if FICL_ROBUST > 1
166    vmCheckFStack(pVM, 1, 1);
167    vmCheckStack(pVM, 1, 0);
168#endif
169
170    f = GETTOPF().f;
171    f -= (FICL_FLOAT)POPINT();
172    SETTOPF(f);
173}
174
175/*******************************************************************
176** Do float * integer r * n.
177** f*i ( r n -- r )
178*******************************************************************/
179static void Fmuli(FICL_VM *pVM)
180{
181    FICL_FLOAT f;
182
183#if FICL_ROBUST > 1
184    vmCheckFStack(pVM, 1, 1);
185    vmCheckStack(pVM, 1, 0);
186#endif
187
188    f = (FICL_FLOAT)POPINT();
189    f *= GETTOPF().f;
190    SETTOPF(f);
191}
192
193/*******************************************************************
194** Do float / integer r / n.
195** f/i ( r n -- r )
196*******************************************************************/
197static void Fdivi(FICL_VM *pVM)
198{
199    FICL_FLOAT f;
200
201#if FICL_ROBUST > 1
202    vmCheckFStack(pVM, 1, 1);
203    vmCheckStack(pVM, 1, 0);
204#endif
205
206    f = GETTOPF().f;
207    f /= (FICL_FLOAT)POPINT();
208    SETTOPF(f);
209}
210
211/*******************************************************************
212** Do integer - float n - r.
213** i-f ( n r -- r )
214*******************************************************************/
215static void isubf(FICL_VM *pVM)
216{
217    FICL_FLOAT f;
218
219#if FICL_ROBUST > 1
220    vmCheckFStack(pVM, 1, 1);
221    vmCheckStack(pVM, 1, 0);
222#endif
223
224    f = (FICL_FLOAT)POPINT();
225    f -= GETTOPF().f;
226    SETTOPF(f);
227}
228
229/*******************************************************************
230** Do integer / float n / r.
231** i/f ( n r -- r )
232*******************************************************************/
233static void idivf(FICL_VM *pVM)
234{
235    FICL_FLOAT f;
236
237#if FICL_ROBUST > 1
238    vmCheckFStack(pVM, 1,1);
239    vmCheckStack(pVM, 1, 0);
240#endif
241
242    f = (FICL_FLOAT)POPINT();
243    f /= GETTOPF().f;
244    SETTOPF(f);
245}
246
247/*******************************************************************
248** Do integer to float conversion.
249** int>float ( n -- r )
250*******************************************************************/
251static void itof(FICL_VM *pVM)
252{
253    float f;
254
255#if FICL_ROBUST > 1
256    vmCheckStack(pVM, 1, 0);
257    vmCheckFStack(pVM, 0, 1);
258#endif
259
260    f = (float)POPINT();
261    PUSHFLOAT(f);
262}
263
264/*******************************************************************
265** Do float to integer conversion.
266** float>int ( r -- n )
267*******************************************************************/
268static void Ftoi(FICL_VM *pVM)
269{
270    FICL_INT i;
271
272#if FICL_ROBUST > 1
273    vmCheckStack(pVM, 0, 1);
274    vmCheckFStack(pVM, 1, 0);
275#endif
276
277    i = (FICL_INT)POPFLOAT();
278    PUSHINT(i);
279}
280
281/*******************************************************************
282** Floating point constant execution word.
283*******************************************************************/
284void FconstantParen(FICL_VM *pVM)
285{
286    FICL_WORD *pFW = pVM->runningWord;
287
288#if FICL_ROBUST > 1
289    vmCheckFStack(pVM, 0, 1);
290#endif
291
292    PUSHFLOAT(pFW->param[0].f);
293}
294
295/*******************************************************************
296** Create a floating point constant.
297** fconstant ( r -"name"- )
298*******************************************************************/
299static void Fconstant(FICL_VM *pVM)
300{
301    FICL_DICT *dp = vmGetDict(pVM);
302    STRINGINFO si = vmGetWord(pVM);
303
304#if FICL_ROBUST > 1
305    vmCheckFStack(pVM, 1, 0);
306#endif
307
308    dictAppendWord2(dp, si, FconstantParen, FW_DEFAULT);
309    dictAppendCell(dp, stackPop(pVM->fStack));
310}
311
312/*******************************************************************
313** Display a float in decimal format.
314** f. ( r -- )
315*******************************************************************/
316static void FDot(FICL_VM *pVM)
317{
318    float f;
319
320#if FICL_ROBUST > 1
321    vmCheckFStack(pVM, 1, 0);
322#endif
323
324    f = POPFLOAT();
325    sprintf(pVM->pad,"%#f ",f);
326    vmTextOut(pVM, pVM->pad, 0);
327}
328
329/*******************************************************************
330** Display a float in engineering format.
331** fe. ( r -- )
332*******************************************************************/
333static void EDot(FICL_VM *pVM)
334{
335    float f;
336
337#if FICL_ROBUST > 1
338    vmCheckFStack(pVM, 1, 0);
339#endif
340
341    f = POPFLOAT();
342    sprintf(pVM->pad,"%#e ",f);
343    vmTextOut(pVM, pVM->pad, 0);
344}
345
346/**************************************************************************
347                        d i s p l a y FS t a c k
348** Display the parameter stack (code for "f.s")
349** f.s ( -- )
350**************************************************************************/
351static void displayFStack(FICL_VM *pVM)
352{
353    int d = stackDepth(pVM->fStack);
354    int i;
355    CELL *pCell;
356
357    vmCheckFStack(pVM, 0, 0);
358
359    vmTextOut(pVM, "F:", 0);
360
361    if (d == 0)
362        vmTextOut(pVM, "[0]", 0);
363    else
364    {
365        ltoa(d, &pVM->pad[1], pVM->base);
366        pVM->pad[0] = '[';
367        strcat(pVM->pad,"] ");
368        vmTextOut(pVM,pVM->pad,0);
369
370        pCell = pVM->fStack->sp - d;
371        for (i = 0; i < d; i++)
372        {
373            sprintf(pVM->pad,"%#f ",(*pCell++).f);
374            vmTextOut(pVM,pVM->pad,0);
375        }
376    }
377}
378
379/*******************************************************************
380** Do float stack depth.
381** fdepth ( -- n )
382*******************************************************************/
383static void Fdepth(FICL_VM *pVM)
384{
385    int i;
386
387#if FICL_ROBUST > 1
388    vmCheckStack(pVM, 0, 1);
389#endif
390
391    i = stackDepth(pVM->fStack);
392    PUSHINT(i);
393}
394
395/*******************************************************************
396** Do float stack drop.
397** fdrop ( r -- )
398*******************************************************************/
399static void Fdrop(FICL_VM *pVM)
400{
401#if FICL_ROBUST > 1
402    vmCheckFStack(pVM, 1, 0);
403#endif
404
405    DROPF(1);
406}
407
408/*******************************************************************
409** Do float stack 2drop.
410** f2drop ( r r -- )
411*******************************************************************/
412static void FtwoDrop(FICL_VM *pVM)
413{
414#if FICL_ROBUST > 1
415    vmCheckFStack(pVM, 2, 0);
416#endif
417
418    DROPF(2);
419}
420
421/*******************************************************************
422** Do float stack dup.
423** fdup ( r -- r r )
424*******************************************************************/
425static void Fdup(FICL_VM *pVM)
426{
427#if FICL_ROBUST > 1
428    vmCheckFStack(pVM, 1, 2);
429#endif
430
431    PICKF(0);
432}
433
434/*******************************************************************
435** Do float stack 2dup.
436** f2dup ( r1 r2 -- r1 r2 r1 r2 )
437*******************************************************************/
438static void FtwoDup(FICL_VM *pVM)
439{
440#if FICL_ROBUST > 1
441    vmCheckFStack(pVM, 2, 4);
442#endif
443
444    PICKF(1);
445    PICKF(1);
446}
447
448/*******************************************************************
449** Do float stack over.
450** fover ( r1 r2 -- r1 r2 r1 )
451*******************************************************************/
452static void Fover(FICL_VM *pVM)
453{
454#if FICL_ROBUST > 1
455    vmCheckFStack(pVM, 2, 3);
456#endif
457
458    PICKF(1);
459}
460
461/*******************************************************************
462** Do float stack 2over.
463** f2over ( r1 r2 r3 -- r1 r2 r3 r1 r2 )
464*******************************************************************/
465static void FtwoOver(FICL_VM *pVM)
466{
467#if FICL_ROBUST > 1
468    vmCheckFStack(pVM, 4, 6);
469#endif
470
471    PICKF(3);
472    PICKF(3);
473}
474
475/*******************************************************************
476** Do float stack pick.
477** fpick ( n -- r )
478*******************************************************************/
479static void Fpick(FICL_VM *pVM)
480{
481    CELL c = POP();
482
483#if FICL_ROBUST > 1
484    vmCheckFStack(pVM, c.i+1, c.i+2);
485#endif
486
487    PICKF(c.i);
488}
489
490/*******************************************************************
491** Do float stack ?dup.
492** f?dup ( r -- r )
493*******************************************************************/
494static void FquestionDup(FICL_VM *pVM)
495{
496    CELL c;
497
498#if FICL_ROBUST > 1
499    vmCheckFStack(pVM, 1, 2);
500#endif
501
502    c = GETTOPF();
503    if (c.f != 0)
504        PICKF(0);
505}
506
507/*******************************************************************
508** Do float stack roll.
509** froll ( n -- )
510*******************************************************************/
511static void Froll(FICL_VM *pVM)
512{
513    int i = POP().i;
514    i = (i > 0) ? i : 0;
515
516#if FICL_ROBUST > 1
517    vmCheckFStack(pVM, i+1, i+1);
518#endif
519
520    ROLLF(i);
521}
522
523/*******************************************************************
524** Do float stack -roll.
525** f-roll ( n -- )
526*******************************************************************/
527static void FminusRoll(FICL_VM *pVM)
528{
529    int i = POP().i;
530    i = (i > 0) ? i : 0;
531
532#if FICL_ROBUST > 1
533    vmCheckFStack(pVM, i+1, i+1);
534#endif
535
536    ROLLF(-i);
537}
538
539/*******************************************************************
540** Do float stack rot.
541** frot ( r1 r2 r3  -- r2 r3 r1 )
542*******************************************************************/
543static void Frot(FICL_VM *pVM)
544{
545#if FICL_ROBUST > 1
546    vmCheckFStack(pVM, 3, 3);
547#endif
548
549    ROLLF(2);
550}
551
552/*******************************************************************
553** Do float stack -rot.
554** f-rot ( r1 r2 r3  -- r3 r1 r2 )
555*******************************************************************/
556static void Fminusrot(FICL_VM *pVM)
557{
558#if FICL_ROBUST > 1
559    vmCheckFStack(pVM, 3, 3);
560#endif
561
562    ROLLF(-2);
563}
564
565/*******************************************************************
566** Do float stack swap.
567** fswap ( r1 r2 -- r2 r1 )
568*******************************************************************/
569static void Fswap(FICL_VM *pVM)
570{
571#if FICL_ROBUST > 1
572    vmCheckFStack(pVM, 2, 2);
573#endif
574
575    ROLLF(1);
576}
577
578/*******************************************************************
579** Do float stack 2swap
580** f2swap ( r1 r2 r3 r4  -- r3 r4 r1 r2 )
581*******************************************************************/
582static void FtwoSwap(FICL_VM *pVM)
583{
584#if FICL_ROBUST > 1
585    vmCheckFStack(pVM, 4, 4);
586#endif
587
588    ROLLF(3);
589    ROLLF(3);
590}
591
592/*******************************************************************
593** Get a floating point number from a variable.
594** f@ ( n -- r )
595*******************************************************************/
596static void Ffetch(FICL_VM *pVM)
597{
598    CELL *pCell;
599
600#if FICL_ROBUST > 1
601    vmCheckFStack(pVM, 0, 1);
602    vmCheckStack(pVM, 1, 0);
603#endif
604
605    pCell = (CELL *)POPPTR();
606    PUSHFLOAT(pCell->f);
607}
608
609/*******************************************************************
610** Store a floating point number into a variable.
611** f! ( r n -- )
612*******************************************************************/
613static void Fstore(FICL_VM *pVM)
614{
615    CELL *pCell;
616
617#if FICL_ROBUST > 1
618    vmCheckFStack(pVM, 1, 0);
619    vmCheckStack(pVM, 1, 0);
620#endif
621
622    pCell = (CELL *)POPPTR();
623    pCell->f = POPFLOAT();
624}
625
626/*******************************************************************
627** Add a floating point number to contents of a variable.
628** f+! ( r n -- )
629*******************************************************************/
630static void FplusStore(FICL_VM *pVM)
631{
632    CELL *pCell;
633
634#if FICL_ROBUST > 1
635    vmCheckStack(pVM, 1, 0);
636    vmCheckFStack(pVM, 1, 0);
637#endif
638
639    pCell = (CELL *)POPPTR();
640    pCell->f += POPFLOAT();
641}
642
643/*******************************************************************
644** Floating point literal execution word.
645*******************************************************************/
646static void fliteralParen(FICL_VM *pVM)
647{
648#if FICL_ROBUST > 1
649    vmCheckStack(pVM, 0, 1);
650#endif
651
652    PUSHFLOAT(*(float*)(pVM->ip));
653    vmBranchRelative(pVM, 1);
654}
655
656/*******************************************************************
657** Compile a floating point literal.
658*******************************************************************/
659static void fliteralIm(FICL_VM *pVM)
660{
661    FICL_DICT *dp = vmGetDict(pVM);
662    FICL_WORD *pfLitParen = ficlLookup(pVM->pSys, "(fliteral)");
663
664#if FICL_ROBUST > 1
665    vmCheckFStack(pVM, 1, 0);
666#endif
667
668    dictAppendCell(dp, LVALUEtoCELL(pfLitParen));
669    dictAppendCell(dp, stackPop(pVM->fStack));
670}
671
672/*******************************************************************
673** Do float 0= comparison r = 0.0.
674** f0= ( r -- T/F )
675*******************************************************************/
676static void FzeroEquals(FICL_VM *pVM)
677{
678    CELL c;
679
680#if FICL_ROBUST > 1
681    vmCheckFStack(pVM, 1, 0);                   /* Make sure something on float stack. */
682    vmCheckStack(pVM, 0, 1);                    /* Make sure room for result. */
683#endif
684
685    c.i = FICL_BOOL(POPFLOAT() == 0);
686    PUSH(c);
687}
688
689/*******************************************************************
690** Do float 0< comparison r < 0.0.
691** f0< ( r -- T/F )
692*******************************************************************/
693static void FzeroLess(FICL_VM *pVM)
694{
695    CELL c;
696
697#if FICL_ROBUST > 1
698    vmCheckFStack(pVM, 1, 0);                   /* Make sure something on float stack. */
699    vmCheckStack(pVM, 0, 1);                    /* Make sure room for result. */
700#endif
701
702    c.i = FICL_BOOL(POPFLOAT() < 0);
703    PUSH(c);
704}
705
706/*******************************************************************
707** Do float 0> comparison r > 0.0.
708** f0> ( r -- T/F )
709*******************************************************************/
710static void FzeroGreater(FICL_VM *pVM)
711{
712    CELL c;
713
714#if FICL_ROBUST > 1
715    vmCheckFStack(pVM, 1, 0);
716    vmCheckStack(pVM, 0, 1);
717#endif
718
719    c.i = FICL_BOOL(POPFLOAT() > 0);
720    PUSH(c);
721}
722
723/*******************************************************************
724** Do float = comparison r1 = r2.
725** f= ( r1 r2 -- T/F )
726*******************************************************************/
727static void FisEqual(FICL_VM *pVM)
728{
729    float x, y;
730
731#if FICL_ROBUST > 1
732    vmCheckFStack(pVM, 2, 0);
733    vmCheckStack(pVM, 0, 1);
734#endif
735
736    x = POPFLOAT();
737    y = POPFLOAT();
738    PUSHINT(FICL_BOOL(x == y));
739}
740
741/*******************************************************************
742** Do float < comparison r1 < r2.
743** f< ( r1 r2 -- T/F )
744*******************************************************************/
745static void FisLess(FICL_VM *pVM)
746{
747    float x, y;
748
749#if FICL_ROBUST > 1
750    vmCheckFStack(pVM, 2, 0);
751    vmCheckStack(pVM, 0, 1);
752#endif
753
754    y = POPFLOAT();
755    x = POPFLOAT();
756    PUSHINT(FICL_BOOL(x < y));
757}
758
759/*******************************************************************
760** Do float > comparison r1 > r2.
761** f> ( r1 r2 -- T/F )
762*******************************************************************/
763static void FisGreater(FICL_VM *pVM)
764{
765    float x, y;
766
767#if FICL_ROBUST > 1
768    vmCheckFStack(pVM, 2, 0);
769    vmCheckStack(pVM, 0, 1);
770#endif
771
772    y = POPFLOAT();
773    x = POPFLOAT();
774    PUSHINT(FICL_BOOL(x > y));
775}
776
777
778/*******************************************************************
779** Move float to param stack (assumes they both fit in a single CELL)
780** f>s
781*******************************************************************/
782static void FFrom(FICL_VM *pVM)
783{
784    CELL c;
785
786#if FICL_ROBUST > 1
787    vmCheckFStack(pVM, 1, 0);
788    vmCheckStack(pVM, 0, 1);
789#endif
790
791    c = stackPop(pVM->fStack);
792    stackPush(pVM->pStack, c);
793    return;
794}
795
796static void ToF(FICL_VM *pVM)
797{
798    CELL c;
799
800#if FICL_ROBUST > 1
801    vmCheckFStack(pVM, 0, 1);
802    vmCheckStack(pVM, 1, 0);
803#endif
804
805    c = stackPop(pVM->pStack);
806    stackPush(pVM->fStack, c);
807    return;
808}
809
810
811/**************************************************************************
812                     F l o a t P a r s e S t a t e
813** Enum to determine the current segement of a floating point number
814** being parsed.
815**************************************************************************/
816#define NUMISNEG 1
817#define EXPISNEG 2
818
819typedef enum _floatParseState
820{
821    FPS_START,
822    FPS_ININT,
823    FPS_INMANT,
824    FPS_STARTEXP,
825    FPS_INEXP
826} FloatParseState;
827
828/**************************************************************************
829                     f i c l P a r s e F l o a t N u m b e r
830** pVM -- Virtual Machine pointer.
831** si -- String to parse.
832** Returns 1 if successful, 0 if not.
833**************************************************************************/
834int ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si )
835{
836    unsigned char ch, digit;
837    char *cp;
838    FICL_COUNT count;
839    float power;
840    float accum = 0.0f;
841    float mant = 0.1f;
842    FICL_INT exponent = 0;
843    char flag = 0;
844    FloatParseState estate = FPS_START;
845
846#if FICL_ROBUST > 1
847    vmCheckFStack(pVM, 0, 1);
848#endif
849
850    /*
851    ** floating point numbers only allowed in base 10
852    */
853    if (pVM->base != 10)
854        return(0);
855
856
857    cp = SI_PTR(si);
858    count = (FICL_COUNT)SI_COUNT(si);
859
860    /* Loop through the string's characters. */
861    while ((count--) && ((ch = *cp++) != 0))
862    {
863        switch (estate)
864        {
865            /* At start of the number so look for a sign. */
866            case FPS_START:
867            {
868                estate = FPS_ININT;
869                if (ch == '-')
870                {
871                    flag |= NUMISNEG;
872                    break;
873                }
874                if (ch == '+')
875                {
876                    break;
877                }
878            } /* Note!  Drop through to FPS_ININT */
879            /*
880            **Converting integer part of number.
881            ** Only allow digits, decimal and 'E'.
882            */
883            case FPS_ININT:
884            {
885                if (ch == '.')
886                {
887                    estate = FPS_INMANT;
888                }
889                else if ((ch == 'e') || (ch == 'E'))
890                {
891                    estate = FPS_STARTEXP;
892                }
893                else
894                {
895                    digit = (unsigned char)(ch - '0');
896                    if (digit > 9)
897                        return(0);
898
899                    accum = accum * 10 + digit;
900
901                }
902                break;
903            }
904            /*
905            ** Processing the fraction part of number.
906            ** Only allow digits and 'E'
907            */
908            case FPS_INMANT:
909            {
910                if ((ch == 'e') || (ch == 'E'))
911                {
912                    estate = FPS_STARTEXP;
913                }
914                else
915                {
916                    digit = (unsigned char)(ch - '0');
917                    if (digit > 9)
918                        return(0);
919
920                    accum += digit * mant;
921                    mant *= 0.1f;
922                }
923                break;
924            }
925            /* Start processing the exponent part of number. */
926            /* Look for sign. */
927            case FPS_STARTEXP:
928            {
929                estate = FPS_INEXP;
930
931                if (ch == '-')
932                {
933                    flag |= EXPISNEG;
934                    break;
935                }
936                else if (ch == '+')
937                {
938                    break;
939                }
940            }       /* Note!  Drop through to FPS_INEXP */
941            /*
942            ** Processing the exponent part of number.
943            ** Only allow digits.
944            */
945            case FPS_INEXP:
946            {
947                digit = (unsigned char)(ch - '0');
948                if (digit > 9)
949                    return(0);
950
951                exponent = exponent * 10 + digit;
952
953                break;
954            }
955        }
956    }
957
958    /* If parser never made it to the exponent this is not a float. */
959    if (estate < FPS_STARTEXP)
960        return(0);
961
962    /* Set the sign of the number. */
963    if (flag & NUMISNEG)
964        accum = -accum;
965
966    /* If exponent is not 0 then adjust number by it. */
967    if (exponent != 0)
968    {
969        /* Determine if exponent is negative. */
970        if (flag & EXPISNEG)
971        {
972            exponent = -exponent;
973        }
974        /* power = 10^x */
975        power = (float)pow(10.0, exponent);
976        accum *= power;
977    }
978
979    PUSHFLOAT(accum);
980    if (pVM->state == COMPILE)
981        fliteralIm(pVM);
982
983    return(1);
984}
985
986#endif  /* FICL_WANT_FLOAT */
987
988/**************************************************************************
989** Add float words to a system's dictionary.
990** pSys -- Pointer to the FICL sytem to add float words to.
991**************************************************************************/
992void ficlCompileFloat(FICL_SYSTEM *pSys)
993{
994    FICL_DICT *dp = pSys->dp;
995    assert(dp);
996
997#if FICL_WANT_FLOAT
998    dictAppendWord(dp, ">float",    ToF,            FW_DEFAULT);
999    /* d>f */
1000    dictAppendWord(dp, "f!",        Fstore,         FW_DEFAULT);
1001    dictAppendWord(dp, "f*",        Fmul,           FW_DEFAULT);
1002    dictAppendWord(dp, "f+",        Fadd,           FW_DEFAULT);
1003    dictAppendWord(dp, "f-",        Fsub,           FW_DEFAULT);
1004    dictAppendWord(dp, "f/",        Fdiv,           FW_DEFAULT);
1005    dictAppendWord(dp, "f0<",       FzeroLess,      FW_DEFAULT);
1006    dictAppendWord(dp, "f0=",       FzeroEquals,    FW_DEFAULT);
1007    dictAppendWord(dp, "f<",        FisLess,        FW_DEFAULT);
1008 /*
1009    f>d
1010 */
1011    dictAppendWord(dp, "f@",        Ffetch,         FW_DEFAULT);
1012 /*
1013    falign
1014    faligned
1015 */
1016    dictAppendWord(dp, "fconstant", Fconstant,      FW_DEFAULT);
1017    dictAppendWord(dp, "fdepth",    Fdepth,         FW_DEFAULT);
1018    dictAppendWord(dp, "fdrop",     Fdrop,          FW_DEFAULT);
1019    dictAppendWord(dp, "fdup",      Fdup,           FW_DEFAULT);
1020    dictAppendWord(dp, "fliteral",  fliteralIm,     FW_IMMEDIATE);
1021/*
1022    float+
1023    floats
1024    floor
1025    fmax
1026    fmin
1027*/
1028    dictAppendWord(dp, "f?dup",     FquestionDup,   FW_DEFAULT);
1029    dictAppendWord(dp, "f=",        FisEqual,       FW_DEFAULT);
1030    dictAppendWord(dp, "f>",        FisGreater,     FW_DEFAULT);
1031    dictAppendWord(dp, "f0>",       FzeroGreater,   FW_DEFAULT);
1032    dictAppendWord(dp, "f2drop",    FtwoDrop,       FW_DEFAULT);
1033    dictAppendWord(dp, "f2dup",     FtwoDup,        FW_DEFAULT);
1034    dictAppendWord(dp, "f2over",    FtwoOver,       FW_DEFAULT);
1035    dictAppendWord(dp, "f2swap",    FtwoSwap,       FW_DEFAULT);
1036    dictAppendWord(dp, "f+!",       FplusStore,     FW_DEFAULT);
1037    dictAppendWord(dp, "f+i",       Faddi,          FW_DEFAULT);
1038    dictAppendWord(dp, "f-i",       Fsubi,          FW_DEFAULT);
1039    dictAppendWord(dp, "f*i",       Fmuli,          FW_DEFAULT);
1040    dictAppendWord(dp, "f/i",       Fdivi,          FW_DEFAULT);
1041    dictAppendWord(dp, "int>float", itof,           FW_DEFAULT);
1042    dictAppendWord(dp, "float>int", Ftoi,           FW_DEFAULT);
1043    dictAppendWord(dp, "f.",        FDot,           FW_DEFAULT);
1044    dictAppendWord(dp, "f.s",       displayFStack,  FW_DEFAULT);
1045    dictAppendWord(dp, "fe.",       EDot,           FW_DEFAULT);
1046    dictAppendWord(dp, "fover",     Fover,          FW_DEFAULT);
1047    dictAppendWord(dp, "fnegate",   Fnegate,        FW_DEFAULT);
1048    dictAppendWord(dp, "fpick",     Fpick,          FW_DEFAULT);
1049    dictAppendWord(dp, "froll",     Froll,          FW_DEFAULT);
1050    dictAppendWord(dp, "frot",      Frot,           FW_DEFAULT);
1051    dictAppendWord(dp, "fswap",     Fswap,          FW_DEFAULT);
1052    dictAppendWord(dp, "i-f",       isubf,          FW_DEFAULT);
1053    dictAppendWord(dp, "i/f",       idivf,          FW_DEFAULT);
1054
1055    dictAppendWord(dp, "float>",    FFrom,          FW_DEFAULT);
1056
1057    dictAppendWord(dp, "f-roll",    FminusRoll,     FW_DEFAULT);
1058    dictAppendWord(dp, "f-rot",     Fminusrot,      FW_DEFAULT);
1059    dictAppendWord(dp, "(fliteral)", fliteralParen, FW_COMPILE);
1060
1061    ficlSetEnv(pSys, "floating",       FICL_FALSE);  /* not all required words are present */
1062    ficlSetEnv(pSys, "floating-ext",   FICL_FALSE);
1063    ficlSetEnv(pSys, "floating-stack", FICL_DEFAULT_STACK);
1064#endif
1065    return;
1066}
1067
1068