3 * Forth Inspired Command Language
4 * Author: John Sadler (john_sadler@alum.mit.edu)
5 * Created: 19 July 1997
6 * Dedicated to RHS, in loving memory
7 * $Id: ficl.h,v 1.25 2010/10/03 09:52:12 asau Exp $
10 * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11 * All rights reserved.
13 * Get the latest Ficl release at http://ficl.sourceforge.net
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.
20 * L I C E N S E and D I S C L A I M E R
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
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.
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
47 * Ficl (Forth-inspired command language) is an ANS Forth
48 * interpreter written in C. Unlike traditional Forths, this
49 * interpreter is designed to be embedded into other systems
50 * as a command/macro/development prototype language.
52 * Where Forths usually view themselves as the center of the system
53 * and expect the rest of the system to be coded in Forth, Ficl
54 * acts as a component of the system. It is easy to export
55 * code written in C or ASM to Ficl in the style of TCL, or to invoke
56 * Ficl code from a compiled module. This allows you to do incremental
57 * development in a way that combines the best features of threaded
58 * languages (rapid development, quick code/test/debug cycle,
59 * reasonably fast) with the best features of C (everyone knows it,
60 * easier to support large blocks of code, efficient, type checking).
62 * Ficl provides facilities for interoperating
63 * with programs written in C: C functions can be exported to Ficl,
64 * and Ficl commands can be executed via a C calling interface. The
65 * interpreter is re-entrant, so it can be used in multiple instances
66 * in a multitasking system. Unlike Forth, Ficl's outer interpreter
67 * expects a text block as input, and returns to the caller after each
68 * text block, so the "data pump" is somewhere in external code. This
69 * is more like TCL than Forth, which usually expects to be at the center
70 * of the system, requesting input at its convenience. Each Ficl virtual
71 * machine can be bound to a different I/O channel, and is independent
72 * of all others in in the same address space except that all virtual
73 * machines share a common dictionary (a sort or open symbol table that
74 * defines all of the elements of the language).
76 * Code is written in ANSI C for portability.
78 * Summary of Ficl features and constraints:
79 * - Standard: Implements the ANSI Forth CORE word set and part
80 * of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and
81 * TOOLS EXT, LOCAL and LOCAL ext and various extras.
82 * - Extensible: you can export code written in Forth, C,
83 * or asm in a straightforward way. Ficl provides open
84 * facilities for extending the language in an application
85 * specific way. You can even add new control structures!
86 * - Ficl and C can interact in two ways: Ficl can encapsulate
87 * C code, or C code can invoke Ficl code.
88 * - Thread-safe, re-entrant: The shared system dictionary
89 * uses a locking mechanism that you can either supply
90 * or stub out to provide exclusive access. Each Ficl
91 * virtual machine has an otherwise complete state, and
92 * each can be bound to a separate I/O channel (or none at all).
93 * - Simple encapsulation into existing systems: a basic implementation
94 * requires three function calls (see the example program in testmain.c).
95 * - ROMable: Ficl is designed to work in RAM-based and ROM code / RAM data
96 * environments. It does require somewhat more memory than a pure
97 * ROM implementation because it builds its system dictionary in
98 * RAM at startup time.
99 * - Written an ANSI C to be as simple as I can make it to understand,
100 * support, debug, and port. Compiles without complaint at /Az /W4
101 * (require ANSI C, max warnings) under Microsoft VC++ 5.
102 * - Does full 32 bit math (but you need to implement
103 * two mixed precision math primitives (see sysdep.c))
104 * - Indirect threaded interpreter is not the fastest kind of
105 * Forth there is (see pForth 68K for a really fast subroutine
106 * threaded interpreter), but it's the cleanest match to a
107 * pure C implementation.
109 * P O R T I N G F i c l
111 * To install Ficl on your target system, you need an ANSI C compiler
112 * and its runtime library. Inspect the system dependent macros and
113 * functions in sysdep.h and sysdep.c and edit them to suit your
114 * system. For example, INT16 is a short on some compilers and an
115 * int on others. Check the default CELL alignment controlled by
116 * FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree,
117 * ficlLockDictionary, and ficlCallbackDefaultTextOut to work with your
118 * operating system. Finally, use testmain.c as a guide to installing the
119 * Ficl system and one or more virtual machines into your code. You do not
120 * need to include testmain.c in your build.
124 * 1. Unimplemented system dependent CORE word: key
125 * 2. Ficl uses the PAD in some CORE words - this violates the standard,
126 * but it's cleaner for a multithreaded system. I'll have to make a
127 * second pad for reference by the word PAD to fix this.
129 * F o r M o r e I n f o r m a t i o n
132 * http://ficl.sourceforge.net
133 * Check this website for Forth literature (including the ANSI standard)
134 * http://www.taygeta.com/forthlit.html
135 * and here for software and more links
136 * http://www.taygeta.com/forth.html
145 #include <sys/stdint.h>
153 extern void pager_open(void);
154 extern int pager_output(const char *);
155 extern void pager_close(void);
161 * Put all your local defines in ficllocal.h,
162 * rather than editing the makefile/project/etc.
163 * ficllocal.h will always ship as an inert file.
166 #include "ficllocal.h"
167 #include "ficlplatform/unix.h"
171 * B U I L D C O N T R O L S
173 * First, the FICL_WANT_* settings.
174 * These are all optional settings that you may or may not
181 * If set to nonzero, build the smallest possible Ficl interpreter.
183 #if !defined(FICL_WANT_MINIMAL)
184 #define FICL_WANT_MINIMAL (0)
187 #if FICL_WANT_MINIMAL
188 #define FICL_WANT_SOFTWORDS (0)
189 #define FICL_WANT_FILE (0)
190 #define FICL_WANT_FLOAT (0)
191 #define FICL_WANT_USER (0)
192 #define FICL_WANT_LOCALS (0)
193 #define FICL_WANT_DEBUGGER (0)
194 #define FICL_WANT_OOP (0)
195 #define FICL_WANT_PLATFORM (0)
196 #define FICL_WANT_MULTITHREADED (0)
197 #define FICL_WANT_EXTENDED_PREFIX (0)
199 #define FICL_ROBUST (0)
201 #endif /* FICL_WANT_MINIMAL */
205 * Includes words defined in ficlCompilePlatform
206 * (see ficlplatform/win32.c and ficlplatform/unix.c for example)
208 #if !defined(FICL_WANT_PLATFORM)
209 #define FICL_WANT_PLATFORM (1)
210 #endif /* FICL_WANT_PLATFORM */
213 * FICL_WANT_LZ4_SOFTCORE
214 * If nonzero, the softcore words are stored compressed
215 * with patent-unencumbered LZ4 compression.
216 * This results in a smaller Ficl interpreter, and adds
217 * only a *tiny* runtime speed hit.
219 * Original LZ77 contributed by Larry Hastings.
220 * Updated to LZ4 which is even more space efficient.
222 #if !defined(FICL_WANT_LZ4_SOFTCORE)
223 #define FICL_WANT_LZ4_SOFTCORE (1)
224 #endif /* FICL_WANT_LZ4_SOFTCORE */
228 * Includes the FILE and FILE-EXT wordset and associated code.
229 * Turn this off if you do not have a file system!
230 * Contributed by Larry Hastings
232 #if !defined(FICL_WANT_FILE)
233 #define FICL_WANT_FILE (0)
234 #endif /* FICL_WANT_FILE */
238 * Includes a floating point stack for the VM, and words to do float operations.
239 * Contributed by Guy Carver
241 #if !defined(FICL_WANT_FLOAT)
242 #define FICL_WANT_FLOAT (1)
243 #endif /* FICL_WANT_FLOAT */
247 * Inludes a simple source level debugger
249 #if !defined(FICL_WANT_DEBUGGER)
250 #define FICL_WANT_DEBUGGER (1)
251 #endif /* FICL_WANT_DEBUGGER */
254 * FICL_EXTENDED_PREFIX
255 * Enables a bunch of extra prefixes in prefix.c
256 * and prefix.fr (if included as part of softcore.c)
258 #if !defined(FICL_WANT_EXTENDED_PREFIX)
259 #define FICL_WANT_EXTENDED_PREFIX (1)
260 #endif /* FICL_WANT_EXTENDED_PREFIX */
264 * Enables user variables: per-instance variables bound to the VM.
265 * Kind of like thread-local storage. Could be implemented in a
266 * VM private dictionary, but I've chosen the lower overhead
267 * approach of an array of CELLs instead.
269 #if !defined(FICL_WANT_USER)
270 #define FICL_WANT_USER (1)
271 #endif /* FICL_WANT_USER */
275 * Controls the creation of the LOCALS wordset
276 * and a private dictionary for local variable compilation.
278 #if !defined FICL_WANT_LOCALS
279 #define FICL_WANT_LOCALS (1)
280 #endif /* FICL_WANT_LOCALS */
284 * Inludes object oriented programming support (in softwords)
285 * OOP support requires locals and user variables!
287 #if !defined(FICL_WANT_OOP)
288 #define FICL_WANT_OOP ((FICL_WANT_LOCALS) && (FICL_WANT_USER))
289 #endif /* FICL_WANT_OOP */
292 * FICL_WANT_SOFTWORDS
293 * Controls inclusion of all softwords in softcore.c.
295 #if !defined(FICL_WANT_SOFTWORDS)
296 #define FICL_WANT_SOFTWORDS (1)
297 #endif /* FICL_WANT_SOFTWORDS */
300 * FICL_WANT_MULTITHREADED
301 * Enables dictionary mutual exclusion wia the
302 * ficlLockDictionary() system dependent function.
304 * Note: this implementation is experimental and poorly
305 * tested. Further, it's unnecessary unless you really
306 * intend to have multiple SESSIONS (poor choice of name
307 * on my part) - that is, threads that modify the dictionary
310 #if !defined FICL_WANT_MULTITHREADED
311 #define FICL_WANT_MULTITHREADED (0)
312 #endif /* FICL_WANT_MULTITHREADED */
316 * Do you want to optimize for size, or for speed?
317 * Note that this doesn't affect Ficl very much one way
318 * or the other at the moment.
319 * Contributed by Larry Hastings
321 #define FICL_OPTIMIZE_FOR_SPEED (1)
322 #define FICL_OPTIMIZE_FOR_SIZE (2)
323 #if !defined(FICL_WANT_OPTIMIZE)
324 #define FICL_WANT_OPTIMIZE FICL_OPTIMIZE_FOR_SPEED
325 #endif /* FICL_WANT_OPTIMIZE */
329 * Ficl OO support for calling vtable methods. Win32 only.
330 * Contributed by Guy Carver
332 #if !defined(FICL_WANT_VCALL)
333 #define FICL_WANT_VCALL (0)
334 #endif /* FICL_WANT_VCALL */
337 * P L A T F O R M S E T T I N G S
339 * The FICL_PLATFORM_* settings.
340 * These indicate attributes about the local platform.
345 * String constant describing the current hardware architecture.
347 #if !defined(FICL_PLATFORM_ARCHITECTURE)
348 #define FICL_PLATFORM_ARCHITECTURE "unknown"
353 * String constant describing the current operating system.
355 #if !defined(FICL_PLATFORM_OS)
356 #define FICL_PLATFORM_OS "unknown"
360 * FICL_PLATFORM_HAS_2INTEGER
361 * Indicates whether or not the current architecture
362 * supports a native double-width integer type.
363 * If you set this to 1 in your ficlplatform/ *.h file,
364 * you *must* create typedefs for the following two types:
367 * If this is set to 0, Ficl will implement double-width
368 * integer math in C, which is both bigger *and* slower
369 * (the double whammy!). Make sure your compiler really
370 * genuinely doesn't support native double-width integers
371 * before setting this to 0.
373 #if !defined(FICL_PLATFORM_HAS_2INTEGER)
374 #define FICL_PLATFORM_HAS_2INTEGER (0)
378 * FICL_PLATFORM_HAS_FTRUNCATE
379 * Indicates whether or not the current platform provides
380 * the ftruncate() function (available on most UNIXes).
381 * This function is necessary to provide the complete
382 * File-Access wordset.
384 * If your platform does not have ftruncate() per se,
385 * but does have some method of truncating files, you
386 * should be able to implement ftruncate() yourself and
387 * set this constant to 1. For an example of this see
388 * "ficlplatform/win32.c".
390 #if !defined(FICL_PLATFORM_HAS_FTRUNCATE)
391 #define FICL_PLATFORM_HAS_FTRUNCATE (0)
395 * FICL_PLATFORM_INLINE
396 * Must be defined, should be a function prototype type-modifying
397 * keyword that makes a function "inline". Ficl does not assume
398 * that the local platform supports inline functions; it therefore
399 * only uses "inline" where "static" would also work, and uses "static"
400 * in the absence of another keyword.
402 #if !defined FICL_PLATFORM_INLINE
403 #define FICL_PLATFORM_INLINE inline
404 #endif /* !defined FICL_PLATFORM_INLINE */
407 * FICL_PLATFORM_EXTERN
408 * Must be defined, should be a keyword used to declare
409 * a function prototype as being a genuine prototype.
410 * You should only have to fiddle with this setting if
411 * you're not using an ANSI-compliant compiler, in which
414 #if !defined FICL_PLATFORM_EXTERN
415 #define FICL_PLATFORM_EXTERN extern
416 #endif /* !defined FICL_PLATFORM_EXTERN */
419 * FICL_PLATFORM_BASIC_TYPES
421 * If not defined yet,
423 #if !defined(FICL_PLATFORM_BASIC_TYPES)
424 typedef char ficlInteger8
;
425 typedef unsigned char ficlUnsigned8
;
426 typedef short ficlInteger16
;
427 typedef unsigned short ficlUnsigned16
;
428 typedef long ficlInteger32
;
429 typedef unsigned long ficlUnsigned32
;
431 typedef ficlInteger32 ficlInteger
;
432 typedef ficlUnsigned32 ficlUnsigned
;
433 typedef float ficlFloat
;
435 #endif /* !defined(FICL_PLATFORM_BASIC_TYPES) */
438 * FICL_ROBUST enables bounds checking of stacks and the dictionary.
439 * This will detect stack over and underflows and dictionary overflows.
440 * Any exceptional condition will result in an assertion failure.
441 * (As generated by the ANSI assert macro)
442 * FICL_ROBUST == 1 --> stack checking in the outer interpreter
443 * FICL_ROBUST == 2 also enables checking in many primitives
446 #if !defined FICL_ROBUST
447 #define FICL_ROBUST (2)
448 #endif /* FICL_ROBUST */
451 * FICL_DEFAULT_STACK_SIZE Specifies the default size (in CELLs) of
452 * a new virtual machine's stacks, unless overridden at
455 #if !defined FICL_DEFAULT_STACK_SIZE
456 #define FICL_DEFAULT_STACK_SIZE (128)
460 * FICL_DEFAULT_DICTIONARY_SIZE specifies the number of ficlCells to allocate
461 * for the system dictionary by default. The value
462 * can be overridden at startup time as well.
464 #if !defined FICL_DEFAULT_DICTIONARY_SIZE
465 #define FICL_DEFAULT_DICTIONARY_SIZE (12288)
469 * FICL_DEFAULT_ENVIRONMENT_SIZE specifies the number of cells
470 * to allot for the environment-query dictionary.
472 #if !defined FICL_DEFAULT_ENVIRONMENT_SIZE
473 #define FICL_DEFAULT_ENVIRONMENT_SIZE (512)
477 * FICL_MAX_WORDLISTS specifies the maximum number of wordlists in
478 * the dictionary search order. See Forth DPANS sec 16.3.3
479 * (file://dpans16.htm#16.3.3)
481 #if !defined FICL_MAX_WORDLISTS
482 #define FICL_MAX_WORDLISTS (16)
486 * FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM
487 * structure that stores pointers to parser extension functions. I would
488 * never expect to have more than 8 of these, so that's the default limit.
489 * Too many of these functions will probably exact a nasty performance penalty.
491 #if !defined FICL_MAX_PARSE_STEPS
492 #define FICL_MAX_PARSE_STEPS (8)
496 * Maximum number of local variables per definition.
497 * This only affects the size of the locals dictionary,
498 * and there's only one per entire ficlSystem, so it
499 * doesn't make sense to be a piker here.
501 #if (!defined(FICL_MAX_LOCALS)) && FICL_WANT_LOCALS
502 #define FICL_MAX_LOCALS (64)
506 * The pad is a small scratch area for text manipulation. ANS Forth
507 * requires it to hold at least 84 characters.
509 #if !defined FICL_PAD_SIZE
510 #define FICL_PAD_SIZE (256)
514 * ANS Forth requires that a word's name contain {1..31} characters.
516 #if !defined FICL_NAME_LENGTH
517 #define FICL_NAME_LENGTH (31)
521 * Default size of hash table. For most uniform
522 * performance, use a prime number!
524 #if !defined FICL_HASH_SIZE
525 #define FICL_HASH_SIZE (241)
529 * Default number of USER flags.
531 #if (!defined(FICL_USER_CELLS)) && FICL_WANT_USER
532 #define FICL_USER_CELLS (16)
536 * Forward declarations... read on.
539 typedef struct ficlWord ficlWord
;
541 typedef struct ficlVm ficlVm
;
542 struct ficlDictionary
;
543 typedef struct ficlDictionary ficlDictionary
;
545 typedef struct ficlSystem ficlSystem
;
546 struct ficlSystemInformation
;
547 typedef struct ficlSystemInformation ficlSystemInformation
;
549 typedef struct ficlCallback ficlCallback
;
550 struct ficlCountedString
;
551 typedef struct ficlCountedString ficlCountedString
;
553 typedef struct ficlString ficlString
;
557 * System dependent routines:
558 * Edit the implementations in your appropriate ficlplatform/ *.c to be
559 * compatible with your runtime environment.
561 * ficlCallbackDefaultTextOut sends a zero-terminated string to the
562 * default output device - used for system error messages.
564 * ficlMalloc(), ficlRealloc() and ficlFree() have the same semantics
565 * as the functions malloc(), realloc(), and free() from the standard C library.
567 FICL_PLATFORM_EXTERN
void ficlCallbackDefaultTextOut(ficlCallback
*callback
,
569 FICL_PLATFORM_EXTERN
void *ficlMalloc(size_t size
);
570 FICL_PLATFORM_EXTERN
void ficlFree(void *p
);
571 FICL_PLATFORM_EXTERN
void *ficlRealloc(void *p
, size_t size
);
574 * the Good Stuff starts here...
576 #define FICL_VERSION "4.1.0"
577 #define FICL_VERSION_MAJOR 4
578 #define FICL_VERSION_MINOR 1
580 #if !defined(FICL_PROMPT)
581 #define FICL_PROMPT "ok> "
585 * ANS Forth requires false to be zero, and true to be the ones
586 * complement of false... that unifies logical and bitwise operations
589 #define FICL_TRUE ((unsigned long)~(0L))
590 #define FICL_FALSE (0)
591 #define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE)
594 #if !defined FICL_IGNORE /* Macro to silence unused param warnings */
595 #define FICL_IGNORE(x) (void)x
596 #endif /* !defined FICL_IGNORE */
599 #define NULL ((void *)0)
603 * 2integer structures
605 #if FICL_PLATFORM_HAS_2INTEGER
607 #define FICL_2INTEGER_SET(high, low, doublei) \
608 ((doublei) = (ficl2Integer)(((ficlUnsigned)(low)) | \
609 (((ficl2Integer)(high)) << FICL_BITS_PER_CELL)))
610 #define FICL_2UNSIGNED_SET(high, low, doubleu) \
611 ((doubleu) = ((ficl2Unsigned)(low)) | \
612 (((ficl2Unsigned)(high)) << FICL_BITS_PER_CELL))
613 #define FICL_2UNSIGNED_GET_LOW(doubleu) \
614 ((ficlUnsigned)(doubleu & ((((ficl2Integer)1) << \
615 FICL_BITS_PER_CELL) - 1)))
616 #define FICL_2UNSIGNED_GET_HIGH(doubleu) \
617 ((ficlUnsigned)(doubleu >> FICL_BITS_PER_CELL))
618 #define FICL_2UNSIGNED_NOT_ZERO(doubleu) ((doubleu) != 0)
620 #define FICL_INTEGER_TO_2INTEGER(i, doublei) ((doublei) = (i))
621 #define FICL_UNSIGNED_TO_2UNSIGNED(u, doubleu) ((doubleu) = (u))
623 #define ficl2IntegerIsNegative(doublei) ((doublei) < 0)
624 #define ficl2IntegerNegate(doublei) (-(doublei))
626 #define ficl2IntegerMultiply(x, y) \
627 (((ficl2Integer)(x)) * ((ficl2Integer)(y)))
628 #define ficl2IntegerDecrement(x) (((ficl2Integer)(x)) - 1)
630 #define ficl2UnsignedAdd(x, y) (((ficl2Unsigned)(x)) + ((ficl2Unsigned)(y)))
631 #define ficl2UnsignedSubtract(x, y) \
632 (((ficl2Unsigned)(x)) - ((ficl2Unsigned)(y)))
633 #define ficl2UnsignedMultiply(x, y) \
634 (((ficl2Unsigned)(x)) * ((ficl2Unsigned)(y)))
635 #define ficl2UnsignedMultiplyAccumulate(u, mul, add) (((u) * (mul)) + (add))
636 #define ficl2UnsignedArithmeticShiftLeft(x) ((x) << 1)
637 #define ficl2UnsignedArithmeticShiftRight(x) ((x) >> 1)
638 #define ficl2UnsignedCompare(x, y) ficl2UnsignedSubtract(x, y)
639 #define ficl2UnsignedOr(x, y) ((x) | (y))
641 #else /* FICL_PLATFORM_HAS_2INTEGER */
656 #define FICL_2INTEGER_SET(hi, lo, doublei) \
657 { ficl2Integer x; x.low = (lo); x.high = (hi); (doublei) = x; }
658 #define FICL_2UNSIGNED_SET(hi, lo, doubleu) \
659 { ficl2Unsigned x; x.low = (lo); x.high = (hi); (doubleu) = x; }
660 #define FICL_2UNSIGNED_GET_LOW(doubleu) ((doubleu).low)
661 #define FICL_2UNSIGNED_GET_HIGH(doubleu) ((doubleu).high)
662 #define FICL_2UNSIGNED_NOT_ZERO(doubleu) ((doubleu).high || (doubleu).low)
664 #define FICL_INTEGER_TO_2INTEGER(i, doublei) \
665 { ficlInteger __x = (ficlInteger)(i); \
666 FICL_2INTEGER_SET((__x < 0) ? -1L : 0, __x, doublei) }
667 #define FICL_UNSIGNED_TO_2UNSIGNED(u, doubleu) \
668 FICL_2UNSIGNED_SET(0, u, doubleu)
670 FICL_PLATFORM_EXTERN
int ficl2IntegerIsNegative(ficl2Integer x
);
671 FICL_PLATFORM_EXTERN ficl2Integer
ficl2IntegerNegate(ficl2Integer x
);
673 FICL_PLATFORM_EXTERN ficl2Integer
ficl2IntegerMultiply(ficlInteger x
,
675 FICL_PLATFORM_EXTERN ficl2Integer
ficl2IntegerDecrement(ficl2Integer x
);
677 FICL_PLATFORM_EXTERN ficl2Unsigned
ficl2UnsignedAdd(ficl2Unsigned x
,
679 FICL_PLATFORM_EXTERN ficl2Unsigned
ficl2UnsignedSubtract(ficl2Unsigned x
,
681 FICL_PLATFORM_EXTERN ficl2Unsigned
ficl2UnsignedMultiply(ficlUnsigned x
,
683 FICL_PLATFORM_EXTERN ficl2Unsigned
684 ficl2UnsignedMultiplyAccumulate(ficl2Unsigned u
, ficlUnsigned mul
,
686 FICL_PLATFORM_EXTERN ficl2Unsigned
687 ficl2UnsignedArithmeticShiftLeft(ficl2Unsigned x
);
688 FICL_PLATFORM_EXTERN ficl2Unsigned
689 ficl2UnsignedArithmeticShiftRight(ficl2Unsigned x
);
690 FICL_PLATFORM_EXTERN
int ficl2UnsignedCompare(ficl2Unsigned x
,
692 FICL_PLATFORM_EXTERN ficl2Unsigned
693 ficl2UnsignedOr(ficl2Unsigned x
, ficl2Unsigned y
);
695 #endif /* FICL_PLATFORM_HAS_2INTEGER */
698 * These structures represent the result of division.
702 ficl2Unsigned quotient
;
703 ficlUnsigned remainder
;
704 } __attribute__((may_alias
)) ficl2UnsignedQR
;
708 ficl2Integer quotient
;
709 ficlInteger remainder
;
710 } __attribute__((may_alias
)) ficl2IntegerQR
;
713 #define FICL_2INTEGERQR_TO_2UNSIGNEDQR(doubleiqr) \
714 (*(ficl2UnsignedQR *)(&(doubleiqr)))
715 #define FICL_2UNSIGNEDQR_TO_2INTEGERQR(doubleuqr) \
716 (*(ficl2IntegerQR *)(&(doubleuqr)))
719 * 64 bit integer math support routines: multiply two UNS32s
720 * to get a 64 bit product, & divide the product by an UNS32
721 * to get an UNS32 quotient and remainder. Much easier in asm
722 * on a 32 bit CPU than in C, which usually doesn't support
723 * the double length result (but it should).
725 FICL_PLATFORM_EXTERN ficl2IntegerQR
726 ficl2IntegerDivideFloored(ficl2Integer num
, ficlInteger den
);
727 FICL_PLATFORM_EXTERN ficl2IntegerQR
728 ficl2IntegerDivideSymmetric(ficl2Integer num
, ficlInteger den
);
730 FICL_PLATFORM_EXTERN ficl2UnsignedQR
731 ficl2UnsignedDivide(ficl2Unsigned q
, ficlUnsigned y
);
734 * A ficlCell is the main storage type. It must be large enough
735 * to contain a pointer or a scalar. In order to accommodate
736 * 32 bit and 64 bit processors, use abstract types for int,
737 * unsigned, and float.
739 * A ficlUnsigned, ficlInteger, and ficlFloat *MUST* be the same
740 * size as a "void *" on the target system. (Sorry, but that's
741 * a design constraint of FORTH.)
743 typedef union ficlCell
747 #if (FICL_WANT_FLOAT)
752 } __attribute__((may_alias
)) ficlCell
;
755 #define FICL_BITS_PER_CELL (sizeof (ficlCell) * 8)
758 * FICL_PLATFORM_ALIGNMENT is the number of bytes to which
759 * the dictionary pointer address must be aligned. This value
760 * is usually either 2 or 4, depending on the memory architecture
761 * of the target system; 4 is safe on any 16 or 32 bit
762 * machine. 8 would be appropriate for a 64 bit machine.
764 #if !defined FICL_PLATFORM_ALIGNMENT
765 #define FICL_PLATFORM_ALIGNMENT (4)
769 * PTRtoCELL is a cast through void * intended to satisfy the
770 * most outrageously pedantic compiler... (I won't mention
773 #define FICL_POINTER_TO_CELL(p) ((ficlCell *)(void *)p)
776 * FORTH defines the "counted string" data type. This is
777 * a "Pascal-style" string, where the first byte is an unsigned
778 * count of characters, followed by the characters themselves.
779 * The Ficl structure for this is ficlCountedString.
780 * Ficl also often zero-terminates them so that they work with the
781 * usual C runtime library string functions... strlen(), strcmp(),
782 * and the like. (Belt & suspenders? You decide.)
784 * The problem is, this limits strings to 255 characters, which
785 * can be a bit constricting to us wordy types. So FORTH only
786 * uses counted strings for backwards compatibility, and all new
787 * words are "c-addr u" style, where the address and length are
788 * stored separately, and the length is a full unsigned "cell" size.
789 * (For more on this trend, see DPANS94 section A.3.1.3.4.)
790 * Ficl represents this with the ficlString structure. Note that
791 * these are frequently *not* zero-terminated! Don't depend on
792 * it--that way lies madness.
795 struct ficlCountedString
797 ficlUnsigned8 length
;
801 #define FICL_COUNTED_STRING_GET_LENGTH(cs) ((cs).length)
802 #define FICL_COUNTED_STRING_GET_POINTER(cs) ((cs).text)
804 #define FICL_COUNTED_STRING_MAX (256)
805 #define FICL_POINTER_TO_COUNTED_STRING(p) ((ficlCountedString *)(void *)p)
814 #define FICL_STRING_GET_LENGTH(fs) ((fs).length)
815 #define FICL_STRING_GET_POINTER(fs) ((fs).text)
816 #define FICL_STRING_SET_LENGTH(fs, l) ((fs).length = (ficlUnsigned)(l))
817 #define FICL_STRING_SET_POINTER(fs, p) ((fs).text = (char *)(p))
818 #define FICL_STRING_SET_FROM_COUNTED_STRING(string, countedstring) \
819 {(string).text = (countedstring).text; \
820 (string).length = (countedstring).length; }
822 * Init a FICL_STRING from a pointer to a zero-terminated string
824 #define FICL_STRING_SET_FROM_CSTRING(string, cstring) \
825 {(string).text = (cstring); (string).length = strlen(cstring); }
828 * Ficl uses this little structure to hold the address of
829 * the block of text it's working on and an index to the next
830 * unconsumed character in the string. Traditionally, this is
831 * done by a Text Input Buffer, so I've called this struct TIB.
833 * Since this structure also holds the size of the input buffer,
834 * and since evaluate requires that, let's put the size here.
835 * The size is stored as an end-pointer because that is what the
836 * null-terminated string aware functions find most easy to deal
838 * Notice, though, that nobody really uses this except evaluate,
839 * so it might just be moved to ficlVm instead. (sobral)
849 * Stacks get heavy use in Ficl and Forth...
850 * Each virtual machine implements two of them:
851 * one holds parameters (data), and the other holds return
852 * addresses and control flow information for the virtual
853 * machine. (Note: C's automatic stack is implicitly used,
854 * but not modeled because it doesn't need to be...)
855 * Here's an abstract type for a stack
857 typedef struct ficlStack
859 ficlUnsigned size
; /* size of the stack, in cells */
860 ficlCell
*frame
; /* link reg for stack frame */
861 ficlCell
*top
; /* stack pointer */
862 ficlVm
*vm
; /* used for debugging */
863 char *name
; /* used for debugging */
864 ficlCell base
[1]; /* Top of stack */
868 * Stack methods... many map closely to required Forth words.
870 FICL_PLATFORM_EXTERN ficlStack
*
871 ficlStackCreate(ficlVm
*vm
, char *name
, unsigned nCells
);
872 FICL_PLATFORM_EXTERN
void ficlStackDestroy(ficlStack
*stack
);
873 FICL_PLATFORM_EXTERN
int ficlStackDepth(ficlStack
*stack
);
874 FICL_PLATFORM_EXTERN
void ficlStackDrop(ficlStack
*stack
, int n
);
875 FICL_PLATFORM_EXTERN ficlCell
ficlStackFetch(ficlStack
*stack
, int n
);
876 FICL_PLATFORM_EXTERN ficlCell
ficlStackGetTop(ficlStack
*stack
);
877 FICL_PLATFORM_EXTERN
void ficlStackPick(ficlStack
*stack
, int n
);
878 FICL_PLATFORM_EXTERN ficlCell
ficlStackPop(ficlStack
*stack
);
879 FICL_PLATFORM_EXTERN
void ficlStackPush(ficlStack
*stack
, ficlCell c
);
880 FICL_PLATFORM_EXTERN
void ficlStackReset(ficlStack
*stack
);
881 FICL_PLATFORM_EXTERN
void ficlStackRoll(ficlStack
*stack
, int n
);
882 FICL_PLATFORM_EXTERN
void ficlStackSetTop(ficlStack
*stack
, ficlCell c
);
883 FICL_PLATFORM_EXTERN
void ficlStackStore(ficlStack
*stack
, int n
, ficlCell c
);
886 FICL_PLATFORM_EXTERN
void ficlStackLink(ficlStack
*stack
, int nCells
);
887 FICL_PLATFORM_EXTERN
void ficlStackUnlink(ficlStack
*stack
);
888 #endif /* FICL_WANT_LOCALS */
890 FICL_PLATFORM_EXTERN
void *ficlStackPopPointer(ficlStack
*stack
);
891 FICL_PLATFORM_EXTERN ficlUnsigned
ficlStackPopUnsigned(ficlStack
*stack
);
892 FICL_PLATFORM_EXTERN ficlInteger
ficlStackPopInteger(ficlStack
*stack
);
893 FICL_PLATFORM_EXTERN
void ficlStackPushPointer(ficlStack
*stack
, void *ptr
);
894 FICL_PLATFORM_EXTERN
void
895 ficlStackPushUnsigned(ficlStack
*stack
, ficlUnsigned u
);
896 FICL_PLATFORM_EXTERN
void ficlStackPushInteger(ficlStack
*stack
, ficlInteger i
);
898 #if (FICL_WANT_FLOAT)
899 FICL_PLATFORM_EXTERN ficlFloat
ficlStackPopFloat(ficlStack
*stack
);
900 FICL_PLATFORM_EXTERN
void ficlStackPushFloat(ficlStack
*stack
, ficlFloat f
);
903 FICL_PLATFORM_EXTERN
void
904 ficlStackPush2Integer(ficlStack
*stack
, ficl2Integer i64
);
905 FICL_PLATFORM_EXTERN ficl2Integer
ficlStackPop2Integer(ficlStack
*stack
);
906 FICL_PLATFORM_EXTERN
void
907 ficlStackPush2Unsigned(ficlStack
*stack
, ficl2Unsigned u64
);
908 FICL_PLATFORM_EXTERN ficl2Unsigned
ficlStackPop2Unsigned(ficlStack
*stack
);
911 FICL_PLATFORM_EXTERN
void
912 ficlStackCheck(ficlStack
*stack
, int popCells
, int pushCells
);
913 #define FICL_STACK_CHECK(stack, popCells, pushCells) \
914 ficlStackCheck(stack, popCells, pushCells)
915 #else /* FICL_ROBUST >= 1 */
916 #define FICL_STACK_CHECK(stack, popCells, pushCells)
917 #endif /* FICL_ROBUST >= 1 */
919 typedef ficlInteger (*ficlStackWalkFunction
)(void *constant
, ficlCell
*cell
);
920 FICL_PLATFORM_EXTERN
void
921 ficlStackWalk(ficlStack
*stack
, ficlStackWalkFunction callback
,
922 void *context
, ficlInteger bottomToTop
);
923 FICL_PLATFORM_EXTERN
void ficlStackDisplay(ficlStack
*stack
,
924 ficlStackWalkFunction callback
, void *context
);
926 typedef ficlWord
**ficlIp
; /* the VM's instruction pointer */
927 typedef void (*ficlPrimitive
)(ficlVm
*vm
);
928 typedef void (*ficlOutputFunction
)(ficlCallback
*callback
, char *text
);
931 * Each VM has a placeholder for an output function -
932 * this makes it possible to have each VM do I/O
933 * through a different device. If you specify no
934 * ficlOutputFunction, it defaults to ficlCallbackDefaultTextOut.
936 * You can also set a specific handler just for errors.
937 * If you don't specify one, it defaults to using textOut.
943 ficlOutputFunction textOut
;
944 ficlOutputFunction errorOut
;
949 FICL_PLATFORM_EXTERN
void
950 ficlCallbackTextOut(ficlCallback
*callback
, char *text
);
951 FICL_PLATFORM_EXTERN
void
952 ficlCallbackErrorOut(ficlCallback
*callback
, char *text
);
955 * For backwards compatibility.
958 (*ficlCompatibilityOutputFunction
)(ficlVm
*vm
, char *text
, int newline
);
959 FICL_PLATFORM_EXTERN
void
960 ficlCompatibilityTextOutCallback(ficlCallback
*callback
, char *text
,
961 ficlCompatibilityOutputFunction oldFunction
);
964 * Starting with Ficl 4.0, Ficl uses a "switch-threaded" inner loop,
965 * where each primitive word is represented with a numeric constant,
966 * and words are (more or less) arrays of these constants. In Ficl
967 * these constants are an enumerated type called ficlInstruction.
971 #define FICL_TOKEN(token, description) token,
972 #define FICL_INSTRUCTION_TOKEN(token, description, flags) token,
973 #include "ficltokens.h"
975 #undef FICL_INSTRUCTION_TOKEN
979 ficlInstructionFourByteTrick
= 0x10000000
981 typedef intptr_t ficlInstruction
;
984 * The virtual machine (VM) contains the state for one interpreter.
985 * Defined operations include:
986 * Create & initialize
988 * Execute a block of text
989 * Parse a word out of the input stream
990 * Call return, and branch
997 ficlCallback callback
;
998 ficlVm
*link
; /* Ficl keeps a VM list for simple teardown */
999 jmp_buf *exceptionHandler
; /* crude exception mechanism... */
1000 short restart
; /* Set TRUE to restart runningWord */
1001 ficlIp ip
; /* instruction pointer */
1002 /* address of currently running word (often just *(ip-1) ) */
1003 ficlWord
*runningWord
;
1004 ficlUnsigned state
; /* compiling or interpreting */
1005 ficlUnsigned base
; /* number conversion base */
1006 ficlStack
*dataStack
;
1007 ficlStack
*returnStack
; /* return stack */
1009 ficlStack
*floatStack
; /* float stack (optional) */
1011 ficlCell sourceId
; /* -1 if EVALUATE, 0 if normal input, >0 if a file */
1012 ficlTIB tib
; /* address of incoming text string */
1014 ficlCell user
[FICL_USER_CELLS
];
1016 char pad
[FICL_PAD_SIZE
]; /* the scratch area (see above) */
1020 * Each VM operates in one of two non-error states: interpreting
1021 * or compiling. When interpreting, words are simply executed.
1022 * When compiling, most words in the input stream have their
1023 * addresses inserted into the word under construction. Some words
1024 * (known as IMMEDIATE) are executed in the compile state, too.
1026 /* values of STATE */
1027 #define FICL_VM_STATE_INTERPRET (0)
1028 #define FICL_VM_STATE_COMPILE (1)
1031 * Exit codes for vmThrow
1033 /* tell ficlVmExecuteXT to exit inner loop */
1034 #define FICL_VM_STATUS_INNER_EXIT (-256)
1035 /* hungry - normal exit */
1036 #define FICL_VM_STATUS_OUT_OF_TEXT (-257)
1037 /* word needs more text to succeed -- re-run it */
1038 #define FICL_VM_STATUS_RESTART (-258)
1039 /* user wants to quit */
1040 #define FICL_VM_STATUS_USER_EXIT (-259)
1041 /* interpreter found an error */
1042 #define FICL_VM_STATUS_ERROR_EXIT (-260)
1043 /* debugger breakpoint */
1044 #define FICL_VM_STATUS_BREAK (-261)
1045 /* like FICL_VM_STATUS_ERROR_EXIT -- abort */
1046 #define FICL_VM_STATUS_ABORT (-1)
1047 /* like FICL_VM_STATUS_ERROR_EXIT -- abort" */
1048 #define FICL_VM_STATUS_ABORTQ (-2)
1049 /* like FICL_VM_STATUS_ERROR_EXIT, but leave dataStack & base alone */
1050 #define FICL_VM_STATUS_QUIT (-56)
1052 FICL_PLATFORM_EXTERN
void ficlVmBranchRelative(ficlVm
*vm
, int offset
);
1053 FICL_PLATFORM_EXTERN ficlVm
*
1054 ficlVmCreate(ficlVm
*vm
, unsigned nPStack
, unsigned nRStack
);
1055 FICL_PLATFORM_EXTERN
void ficlVmDestroy(ficlVm
*vm
);
1056 FICL_PLATFORM_EXTERN ficlDictionary
*ficlVmGetDictionary(ficlVm
*vm
);
1057 FICL_PLATFORM_EXTERN
char *
1058 ficlVmGetString(ficlVm
*vm
, ficlCountedString
*spDest
, char delimiter
);
1059 FICL_PLATFORM_EXTERN ficlString
ficlVmGetWord(ficlVm
*vm
);
1060 FICL_PLATFORM_EXTERN ficlString
ficlVmGetWord0(ficlVm
*vm
);
1061 FICL_PLATFORM_EXTERN
int ficlVmGetWordToPad(ficlVm
*vm
);
1062 FICL_PLATFORM_EXTERN
void ficlVmInnerLoop(ficlVm
*vm
, ficlWord
*word
);
1063 FICL_PLATFORM_EXTERN ficlString
ficlVmParseString(ficlVm
*vm
, char delimiter
);
1064 FICL_PLATFORM_EXTERN ficlString
1065 ficlVmParseStringEx(ficlVm
*vm
, char delimiter
, char fSkipLeading
);
1066 FICL_PLATFORM_EXTERN ficlCell
ficlVmPop(ficlVm
*vm
);
1067 FICL_PLATFORM_EXTERN
void ficlVmPush(ficlVm
*vm
, ficlCell c
);
1068 FICL_PLATFORM_EXTERN
void ficlVmPopIP(ficlVm
*vm
);
1069 FICL_PLATFORM_EXTERN
void ficlVmPushIP(ficlVm
*vm
, ficlIp newIP
);
1070 FICL_PLATFORM_EXTERN
void ficlVmQuit(ficlVm
*vm
);
1071 FICL_PLATFORM_EXTERN
void ficlVmReset(ficlVm
*vm
);
1072 FICL_PLATFORM_EXTERN
void
1073 ficlVmSetTextOut(ficlVm
*vm
, ficlOutputFunction textOut
);
1074 FICL_PLATFORM_EXTERN
void ficlVmThrow(ficlVm
*vm
, int except
);
1075 FICL_PLATFORM_EXTERN
void ficlVmThrowError(ficlVm
*vm
, char *fmt
, ...);
1076 FICL_PLATFORM_EXTERN
void
1077 ficlVmThrowErrorVararg(ficlVm
*vm
, char *fmt
, va_list list
);
1078 FICL_PLATFORM_EXTERN
void ficlVmTextOut(ficlVm
*vm
, char *text
);
1079 FICL_PLATFORM_EXTERN
void ficlVmErrorOut(ficlVm
*vm
, char *text
);
1081 #define ficlVmGetContext(vm) ((vm)->callback.context)
1082 #define ficlVmGetDataStack(vm) ((vm)->dataStack)
1083 #define ficlVmGetFloatStack(vm) ((vm)->floatStack)
1084 #define ficlVmGetReturnStack(vm) ((vm)->returnStack)
1085 #define ficlVmGetRunningWord(vm) ((vm)->runningWord)
1087 FICL_PLATFORM_EXTERN
void ficlVmDisplayDataStack(ficlVm
*vm
);
1088 FICL_PLATFORM_EXTERN
void ficlVmDisplayDataStackSimple(ficlVm
*vm
);
1089 FICL_PLATFORM_EXTERN
void ficlVmDisplayReturnStack(ficlVm
*vm
);
1091 FICL_PLATFORM_EXTERN
void ficlVmDisplayFloatStack(ficlVm
*vm
);
1092 #endif /* FICL_WANT_FLOAT */
1095 * f i c l E v a l u a t e
1096 * Evaluates a block of input text in the context of the
1097 * specified interpreter. Also sets SOURCE-ID properly.
1099 * PLEASE USE THIS FUNCTION when throwing a hard-coded
1100 * string to the Ficl interpreter.
1102 FICL_PLATFORM_EXTERN
int ficlVmEvaluate(ficlVm
*vm
, char *s
);
1105 * f i c l V m E x e c *
1106 * Evaluates a block of input text in the context of the
1107 * specified interpreter. Emits any requested output to the
1108 * interpreter's output function. If the input string is NULL
1109 * terminated, you can pass -1 as nChars rather than count it.
1110 * Execution returns when the text block has been executed,
1111 * or an error occurs.
1112 * Returns one of the FICL_VM_STATUS_... codes defined in ficl.h:
1113 * FICL_VM_STATUS_OUT_OF_TEXT is the normal exit condition
1114 * FICL_VM_STATUS_ERROR_EXIT means that the interpreter encountered a syntax
1115 * error and the vm has been reset to recover (some or all
1116 * of the text block got ignored
1117 * FICL_VM_STATUS_USER_EXIT means that the user executed the "bye" command
1118 * to shut down the interpreter. This would be a good
1119 * time to delete the vm, etc -- or you can ignore this
1121 * FICL_VM_STATUS_ABORT and FICL_VM_STATUS_ABORTQ are generated by 'abort'
1122 * and 'abort"' commands.
1123 * Preconditions: successful execution of ficlInitSystem,
1124 * Successful creation and init of the VM by ficlNewVM (or equivalent)
1126 * If you call ficlExec() or one of its brothers, you MUST
1127 * ensure vm->sourceId was set to a sensible value.
1128 * ficlExec() explicitly DOES NOT manage SOURCE-ID for you.
1130 FICL_PLATFORM_EXTERN
int ficlVmExecuteString(ficlVm
*vm
, ficlString s
);
1131 FICL_PLATFORM_EXTERN
int ficlVmExecuteXT(ficlVm
*vm
, ficlWord
*pWord
);
1132 FICL_PLATFORM_EXTERN
void
1133 ficlVmExecuteInstruction(ficlVm
*vm
, ficlInstruction i
);
1134 FICL_PLATFORM_EXTERN
void ficlVmExecuteWord(ficlVm
*vm
, ficlWord
*pWord
);
1135 FICL_PLATFORM_EXTERN
int ficlExecFD(ficlVm
*vm
, int fd
);
1137 FICL_PLATFORM_EXTERN
void
1138 ficlVmDictionaryAllot(ficlVm
*vm
, ficlDictionary
*dictionary
, int n
);
1139 FICL_PLATFORM_EXTERN
void
1140 ficlVmDictionaryAllotCells(ficlVm
*vm
, ficlDictionary
*dictionary
, int cells
);
1142 FICL_PLATFORM_EXTERN
int ficlVmParseWord(ficlVm
*vm
, ficlString s
);
1145 * TIB access routines...
1146 * ANS forth seems to require the input buffer to be represented
1147 * as a pointer to the start of the buffer, and an index to the
1148 * next character to read.
1149 * PushTib points the VM to a new input string and optionally
1150 * returns a copy of the current state
1151 * PopTib restores the TIB state given a saved TIB from PushTib
1152 * GetInBuf returns a pointer to the next unused char of the TIB
1154 FICL_PLATFORM_EXTERN
void
1155 ficlVmPushTib(ficlVm
*vm
, char *text
, ficlInteger nChars
, ficlTIB
*pSaveTib
);
1156 FICL_PLATFORM_EXTERN
void ficlVmPopTib(ficlVm
*vm
, ficlTIB
*pTib
);
1157 #define ficlVmGetInBuf(vm) ((vm)->tib.text + (vm)->tib.index)
1158 #define ficlVmGetInBufLen(vm) ((vm)->tib.end - (vm)->tib.text)
1159 #define ficlVmGetInBufEnd(vm) ((vm)->tib.end)
1160 #define ficlVmGetTibIndex(vm) ((vm)->tib.index)
1161 #define ficlVmSetTibIndex(vm, i) ((vm)->tib.index = i)
1162 #define ficlVmUpdateTib(vm, str) \
1163 ((vm)->tib.index = (str) - (vm)->tib.text)
1165 #if FICL_ROBUST >= 1
1166 FICL_PLATFORM_EXTERN
void
1167 ficlVmDictionaryCheck(ficlVm
*vm
, ficlDictionary
*dictionary
, int n
);
1168 FICL_PLATFORM_EXTERN
void
1169 ficlVmDictionarySimpleCheck(ficlVm
*vm
, ficlDictionary
*dictionary
, int n
);
1170 #define FICL_VM_DICTIONARY_CHECK(vm, dictionary, n) \
1171 ficlVmDictionaryCheck(vm, dictionary, n)
1172 #define FICL_VM_DICTIONARY_SIMPLE_CHECK(vm, dictionary, n) \
1173 ficlVmDictionarySimpleCheck(vm, dictionary, n)
1175 #define FICL_VM_DICTIONARY_CHECK(vm, dictionary, n)
1176 #define FICL_VM_DICTIONARY_SIMPLE_CHECK(vm, dictionary, n)
1177 #endif /* FICL_ROBUST >= 1 */
1179 FICL_PLATFORM_EXTERN
void ficlPrimitiveLiteralIm(ficlVm
*vm
);
1182 * A FICL_CODE points to a function that gets called to help execute
1183 * a word in the dictionary. It always gets passed a pointer to the
1184 * running virtual machine, and from there it can get the address
1185 * of the parameter area of the word it's supposed to operate on.
1186 * For precompiled words, the code is all there is. For user defined
1187 * words, the code assumes that the word's parameter area is a list
1188 * of pointers to the code fields of other words to execute, and
1189 * may also contain inline data. The first parameter is always
1190 * a pointer to a code field.
1194 * Ficl models memory as a contiguous space divided into
1195 * words in a linked list called the dictionary.
1196 * A ficlWord starts each entry in the list.
1197 * Version 1.02: space for the name characters is allotted from
1198 * the dictionary ahead of the word struct, rather than using
1199 * a fixed size array for each name.
1203 struct ficlWord
*link
; /* Previous word in the dictionary */
1204 ficlUnsigned16 hash
;
1205 /* Immediate, Smudge, Compile-only, IsOjbect, Instruction */
1206 ficlUnsigned8 flags
;
1207 ficlUnsigned8 length
; /* Number of chars in word name */
1208 char *name
; /* First nFICLNAME chars of word name */
1209 ficlPrimitive code
; /* Native code to execute the word */
1210 ficlInstruction semiParen
; /* Native code to execute the word */
1211 ficlCell param
[1]; /* First data cell of the word */
1215 * ficlWord.flag bitfield values:
1219 * FICL_WORD_IMMEDIATE:
1220 * This word is always executed immediately when
1221 * encountered, even when compiling.
1223 #define FICL_WORD_IMMEDIATE (1)
1226 * FICL_WORD_COMPILE_ONLY:
1227 * This word is only valid during compilation.
1228 * Ficl will throw a runtime error if this word executed
1229 * while not compiling.
1231 #define FICL_WORD_COMPILE_ONLY (2)
1235 * This word's definition is in progress.
1236 * The word is hidden from dictionary lookups
1237 * until it is "un-smudged".
1239 #define FICL_WORD_SMUDGED (4)
1243 * This word is an object or object member variable.
1244 * (Currently only used by "my=[".)
1246 #define FICL_WORD_OBJECT (8)
1249 * FICL_WORD_INSTRUCTION
1250 * This word represents a ficlInstruction, not a normal word.
1251 * param[0] is the instruction.
1252 * When compiled, Ficl will simply copy over the instruction,
1253 * rather than executing the word as normal.
1255 * (Do *not* use this flag for words that need their PFA pushed
1256 * before executing!)
1258 #define FICL_WORD_INSTRUCTION (16)
1261 * FICL_WORD_COMPILE_ONLY_IMMEDIATE
1262 * Most words that are "immediate" are also
1265 #define FICL_WORD_COMPILE_ONLY_IMMEDIATE \
1266 (FICL_WORD_IMMEDIATE | FICL_WORD_COMPILE_ONLY)
1267 #define FICL_WORD_DEFAULT (0)
1270 * Worst-case size of a word header: FICL_NAME_LENGTH chars in name
1272 #define FICL_CELLS_PER_WORD \
1273 ((sizeof (ficlWord) + FICL_NAME_LENGTH + sizeof (ficlCell)) \
1274 / (sizeof (ficlCell)))
1276 FICL_PLATFORM_EXTERN
int ficlWordIsImmediate(ficlWord
*word
);
1277 FICL_PLATFORM_EXTERN
int ficlWordIsCompileOnly(ficlWord
*word
);
1279 #if FICL_ROBUST >= 1
1280 FICL_PLATFORM_EXTERN
void
1281 ficlCallbackAssert(ficlCallback
*callback
, int expression
,
1282 char *expressionString
, char *filename
, int line
);
1283 #define FICL_ASSERT(callback, expression) \
1284 (ficlCallbackAssert((callback), (expression) != 0, \
1285 #expression, __FILE__, __LINE__))
1287 #define FICL_ASSERT(callback, expression)
1288 #endif /* FICL_ROBUST >= 1 */
1290 #define FICL_VM_ASSERT(vm, expression) \
1291 FICL_ASSERT((ficlCallback *)(vm), (expression))
1292 #define FICL_SYSTEM_ASSERT(system, expression) \
1293 FICL_ASSERT((ficlCallback *)(system), (expression))
1296 * Generally useful string manipulators omitted by ANSI C...
1297 * ltoa complements strtol
1300 FICL_PLATFORM_EXTERN
int ficlIsPowerOfTwo(ficlUnsigned u
);
1301 FICL_PLATFORM_EXTERN
char *
1302 ficlLtoa(ficlInteger value
, char *string
, int radix
);
1303 FICL_PLATFORM_EXTERN
char *
1304 ficlUltoa(ficlUnsigned value
, char *string
, int radix
);
1305 FICL_PLATFORM_EXTERN
char ficlDigitToCharacter(int value
);
1306 FICL_PLATFORM_EXTERN
char *ficlStringReverse(char *string
);
1307 FICL_PLATFORM_EXTERN
char *ficlStringSkipSpace(char *s
, char *end
);
1308 FICL_PLATFORM_EXTERN
char *ficlStringCaseFold(char *s
);
1309 FICL_PLATFORM_EXTERN
int ficlStrincmp(char *s1
, char *s2
, ficlUnsigned length
);
1310 FICL_PLATFORM_EXTERN
void *ficlAlignPointer(void *ptr
);
1313 * Ficl hash table - variable size.
1315 * If size is 1, the table degenerates into a linked list.
1316 * A WORDLIST (see the search order word set in DPANS) is
1317 * just a pointer to a FICL_HASH in this implementation.
1319 typedef struct ficlHash
1321 struct ficlHash
*link
; /* link to parent class wordlist for OO */
1322 char *name
; /* optional pointer to \0 terminated wordlist name */
1323 unsigned size
; /* number of buckets in the hash */
1327 FICL_PLATFORM_EXTERN
void ficlHashForget(ficlHash
*hash
, void *where
);
1328 FICL_PLATFORM_EXTERN ficlUnsigned16
ficlHashCode(ficlString s
);
1329 FICL_PLATFORM_EXTERN
void ficlHashInsertWord(ficlHash
*hash
, ficlWord
*word
);
1330 FICL_PLATFORM_EXTERN ficlWord
*
1331 ficlHashLookup(ficlHash
*hash
, ficlString name
, ficlUnsigned16 hashCode
);
1332 FICL_PLATFORM_EXTERN
void ficlHashReset(ficlHash
*hash
);
1335 * A Dictionary is a linked list of FICL_WORDs. It is also Ficl's
1336 * memory model. Description of fields:
1338 * here -- points to the next free byte in the dictionary. This
1339 * pointer is forced to be CELL-aligned before a definition is added.
1340 * Do not assume any specific alignment otherwise - Use dictAlign().
1342 * smudge -- pointer to word currently being defined (or last defined word)
1343 * If the definition completes successfully, the word will be
1344 * linked into the hash table. If unsuccessful, dictUnsmudge
1345 * uses this pointer to restore the previous state of the dictionary.
1346 * Smudge prevents unintentional recursion as a side-effect: the
1347 * dictionary search algo examines only completed definitions, so a
1348 * word cannot invoke itself by name. See the Ficl word "recurse".
1349 * NOTE: smudge always points to the last word defined. IMMEDIATE
1350 * makes use of this fact. Smudge is initially NULL.
1352 * forthWordlist -- pointer to the default wordlist (FICL_HASH).
1353 * This is the initial compilation list, and contains all
1354 * Ficl's precompiled words.
1356 * compilationWordlist -- compilation wordlist - initially equal to
1357 * forthWordlist wordlists -- array of pointers to wordlists.
1358 * Managed as a stack.
1359 * Highest index is the first list in the search order.
1360 * wordlistCount -- number of lists in wordlists. wordlistCount-1 is the
1361 * highest filled slot in wordlists, and points to the first wordlist
1362 * in the search order
1363 * size -- number of cells in the dictionary (total)
1364 * base -- start of data area. Must be at the end of the struct.
1366 struct ficlDictionary
1369 void *context
; /* for your use, particularly with ficlDictionaryLock() */
1371 ficlHash
*forthWordlist
;
1372 ficlHash
*compilationWordlist
;
1373 ficlHash
*wordlists
[FICL_MAX_WORDLISTS
];
1375 unsigned size
; /* Number of cells in dictionary (total) */
1376 ficlSystem
*system
; /* used for debugging */
1377 ficlCell base
[1]; /* Base of dictionary memory */
1380 FICL_PLATFORM_EXTERN
void
1381 ficlDictionaryAbortDefinition(ficlDictionary
*dictionary
);
1382 FICL_PLATFORM_EXTERN
void ficlDictionaryAlign(ficlDictionary
*dictionary
);
1383 FICL_PLATFORM_EXTERN
void
1384 ficlDictionaryAllot(ficlDictionary
*dictionary
, int n
);
1385 FICL_PLATFORM_EXTERN
void
1386 ficlDictionaryAllotCells(ficlDictionary
*dictionary
, int nCells
);
1387 FICL_PLATFORM_EXTERN
void
1388 ficlDictionaryAppendCell(ficlDictionary
*dictionary
, ficlCell c
);
1389 FICL_PLATFORM_EXTERN
void
1390 ficlDictionaryAppendCharacter(ficlDictionary
*dictionary
, char c
);
1391 FICL_PLATFORM_EXTERN
void
1392 ficlDictionaryAppendUnsigned(ficlDictionary
*dictionary
, ficlUnsigned u
);
1393 FICL_PLATFORM_EXTERN
void *
1394 ficlDictionaryAppendData(ficlDictionary
*dictionary
, void *data
,
1395 ficlInteger length
);
1396 FICL_PLATFORM_EXTERN
char *
1397 ficlDictionaryAppendString(ficlDictionary
*dictionary
, ficlString s
);
1398 FICL_PLATFORM_EXTERN ficlWord
*
1399 ficlDictionaryAppendWord(ficlDictionary
*dictionary
, ficlString name
,
1400 ficlPrimitive pCode
, ficlUnsigned8 flags
);
1401 FICL_PLATFORM_EXTERN ficlWord
*
1402 ficlDictionaryAppendPrimitive(ficlDictionary
*dictionary
, char *name
,
1403 ficlPrimitive pCode
, ficlUnsigned8 flags
);
1404 FICL_PLATFORM_EXTERN ficlWord
*
1405 ficlDictionaryAppendInstruction(ficlDictionary
*dictionary
, char *name
,
1406 ficlInstruction i
, ficlUnsigned8 flags
);
1408 FICL_PLATFORM_EXTERN ficlWord
*
1409 ficlDictionaryAppendConstantInstruction(ficlDictionary
*dictionary
,
1410 ficlString name
, ficlInstruction instruction
, ficlInteger value
);
1411 FICL_PLATFORM_EXTERN ficlWord
*
1412 ficlDictionaryAppend2ConstantInstruction(ficlDictionary
*dictionary
,
1413 ficlString name
, ficlInstruction instruction
, ficl2Integer value
);
1415 FICL_PLATFORM_EXTERN ficlWord
*
1416 ficlDictionaryAppendConstant(ficlDictionary
*dictionary
, char *name
,
1418 FICL_PLATFORM_EXTERN ficlWord
*
1419 ficlDictionaryAppend2Constant(ficlDictionary
*dictionary
, char *name
,
1420 ficl2Integer value
);
1421 #define ficlDictionaryAppendConstantPointer(dictionary, name, pointer) \
1422 (ficlDictionaryAppendConstant(dictionary, name, (ficlInteger)pointer))
1424 FICL_PLATFORM_EXTERN ficlWord
*
1425 ficlDictionaryAppendFConstant(ficlDictionary
*dictionary
, char *name
,
1427 FICL_PLATFORM_EXTERN ficlWord
*
1428 ficlDictionaryAppendF2Constant(ficlDictionary
*dictionary
, char *name
,
1430 #endif /* FICL_WANT_FLOAT */
1433 FICL_PLATFORM_EXTERN ficlWord
*
1434 ficlDictionarySetConstantInstruction(ficlDictionary
*dictionary
,
1435 ficlString name
, ficlInstruction instruction
, ficlInteger value
);
1436 FICL_PLATFORM_EXTERN ficlWord
*
1437 ficlDictionarySet2ConstantInstruction(ficlDictionary
*dictionary
,
1438 ficlString name
, ficlInstruction instruction
, ficl2Integer value
);
1440 FICL_PLATFORM_EXTERN ficlWord
*
1441 ficlDictionarySetConstant(ficlDictionary
*dictionary
, char *name
,
1443 #define ficlDictionarySetConstantPointer(dictionary, name, pointer) \
1444 (ficlDictionarySetConstant(dictionary, name, (ficlInteger)pointer))
1446 FICL_PLATFORM_EXTERN ficlWord
*
1447 ficlDictionarySet2Constant(ficlDictionary
*dictionary
, char *name
,
1448 ficl2Integer value
);
1449 FICL_PLATFORM_EXTERN ficlWord
*
1450 ficlDictionarySetConstantString(ficlDictionary
*dictionary
, char *name
,
1452 FICL_PLATFORM_EXTERN ficlWord
*
1453 ficlDictionarySetPrimitive(ficlDictionary
*dictionary
, char *name
,
1454 ficlPrimitive code
, ficlUnsigned8 flags
);
1455 FICL_PLATFORM_EXTERN ficlWord
*
1456 ficlDictionarySetInstruction(ficlDictionary
*dictionary
, char *name
,
1457 ficlInstruction i
, ficlUnsigned8 flags
);
1459 FICL_PLATFORM_EXTERN ficlWord
*
1460 ficlDictionarySetFConstant(ficlDictionary
*dictionary
, char *name
,
1462 FICL_PLATFORM_EXTERN ficlWord
*
1463 ficlDictionarySetF2Constant(ficlDictionary
*dictionary
, char *name
,
1465 #endif /* FICL_WANT_FLOAT */
1467 FICL_PLATFORM_EXTERN
int
1468 ficlDictionaryCellsAvailable(ficlDictionary
*dictionary
);
1469 FICL_PLATFORM_EXTERN
int ficlDictionaryCellsUsed(ficlDictionary
*dictionary
);
1470 FICL_PLATFORM_EXTERN ficlDictionary
*
1471 ficlDictionaryCreate(ficlSystem
*system
, unsigned nCELLS
);
1472 FICL_PLATFORM_EXTERN ficlDictionary
*
1473 ficlDictionaryCreateHashed(ficlSystem
*system
, unsigned nCells
, unsigned nHash
);
1474 FICL_PLATFORM_EXTERN ficlHash
*
1475 ficlDictionaryCreateWordlist(ficlDictionary
*dictionary
, int nBuckets
);
1476 FICL_PLATFORM_EXTERN
void ficlDictionaryDestroy(ficlDictionary
*dictionary
);
1477 FICL_PLATFORM_EXTERN
void
1478 ficlDictionaryEmpty(ficlDictionary
*dictionary
, unsigned nHash
);
1479 FICL_PLATFORM_EXTERN
int
1480 ficlDictionaryIncludes(ficlDictionary
*dictionary
, void *p
);
1481 FICL_PLATFORM_EXTERN ficlWord
*
1482 ficlDictionaryLookup(ficlDictionary
*dictionary
, ficlString name
);
1483 FICL_PLATFORM_EXTERN
void
1484 ficlDictionaryResetSearchOrder(ficlDictionary
*dictionary
);
1485 FICL_PLATFORM_EXTERN
void
1486 ficlDictionarySetFlags(ficlDictionary
*dictionary
, ficlUnsigned8 set
);
1487 FICL_PLATFORM_EXTERN
void
1488 ficlDictionaryClearFlags(ficlDictionary
*dictionary
, ficlUnsigned8 clear
);
1489 FICL_PLATFORM_EXTERN
void
1490 ficlDictionarySetImmediate(ficlDictionary
*dictionary
);
1491 FICL_PLATFORM_EXTERN
void
1492 ficlDictionaryUnsmudge(ficlDictionary
*dictionary
);
1493 FICL_PLATFORM_EXTERN ficlCell
*ficlDictionaryWhere(ficlDictionary
*dictionary
);
1495 FICL_PLATFORM_EXTERN
int
1496 ficlDictionaryIsAWord(ficlDictionary
*dictionary
, ficlWord
*word
);
1497 FICL_PLATFORM_EXTERN
void
1498 ficlDictionarySee(ficlDictionary
*dictionary
, ficlWord
*word
,
1499 ficlCallback
*callback
);
1500 FICL_PLATFORM_EXTERN ficlWord
*
1501 ficlDictionaryFindEnclosingWord(ficlDictionary
*dictionary
, ficlCell
*cell
);
1504 * Stub function for dictionary access control - does nothing
1505 * by default, user can redefine to guarantee exclusive dictionary
1506 * access to a single thread for updates. All dictionary update code
1507 * must be bracketed as follows:
1508 * ficlLockDictionary(dictionary, FICL_TRUE); // any non-zero value will do
1509 * <code that updates dictionary>
1510 * ficlLockDictionary(dictionary, FICL_FALSE);
1512 * Returns zero if successful, nonzero if unable to acquire lock
1513 * before timeout (optional - could also block forever)
1515 * NOTE: this function must be implemented with lock counting
1516 * semantics: nested calls must behave properly.
1518 #if FICL_MULTITHREAD
1519 FICL_PLATFORM_EXTERN
int
1520 ficlDictionaryLock(ficlDictionary
*dictionary
, short lockIncrement
);
1522 #define ficlDictionaryLock(dictionary, lock) (void)0 /* ignore */
1528 * See words.c: interpWord
1529 * By default, Ficl goes through two attempts to parse each token from its
1530 * input stream: it first attempts to match it with a word in the dictionary,
1531 * and if that fails, it attempts to convert it into a number. This mechanism
1532 * is now extensible by additional steps. This allows extensions like floating
1533 * point and double number support to be factored cleanly.
1535 * Each parse step is a function that receives the next input token as a
1536 * STRINGINFO. If the parse step matches the token, it must apply semantics
1537 * to the token appropriate to the present value of VM.state (compiling or
1538 * interpreting), and return FICL_TRUE.
1539 * Otherwise it returns FICL_FALSE. See words.c: isNumber for an example
1541 * Note: for the sake of efficiency, it's a good idea both to limit the number
1542 * of parse steps and to code each parse step so that it rejects tokens that
1543 * do not match as quickly as possible.
1546 typedef int (*ficlParseStep
)(ficlVm
*vm
, ficlString s
);
1549 * FICL_BREAKPOINT record.
1550 * oldXT - if NULL, this breakpoint is unused. Otherwise it stores the xt
1551 * that the breakpoint overwrote. This is restored to the dictionary when the
1552 * BP executes or gets cleared
1553 * address - the location of the breakpoint (address of the instruction that
1554 * has been replaced with the breakpoint trap
1555 * oldXT - The original contents of the location with the breakpoint
1556 * Note: address is NULL when this breakpoint is empty
1558 typedef struct ficlBreakpoint
1566 * F I C L _ S Y S T E M
1567 * The top level data structure of the system - ficl_system ties a list of
1568 * virtual machines with their corresponding dictionaries. Ficl 3.0 added
1569 * support for multiple Ficl systems, allowing multiple concurrent sessions
1570 * to separate dictionaries with some constraints.
1571 * Note: the context pointer is there to provide context for applications.
1572 * It is copied to each VM's context field as that VM is created.
1574 struct ficlSystemInformation
1576 int size
; /* structure size tag for versioning */
1577 /* Initializes VM's context pointer - for application use */
1579 int dictionarySize
; /* Size of system's Dictionary, in cells */
1580 int stackSize
; /* Size of all stacks created, in cells */
1581 ficlOutputFunction textOut
; /* default textOut function */
1582 ficlOutputFunction errorOut
; /* textOut function used for errors */
1583 int environmentSize
; /* Size of Environment dictionary, in cells */
1586 #define ficlSystemInformationInitialize(x) \
1587 { memset((x), 0, sizeof (ficlSystemInformation)); \
1588 (x)->size = sizeof (ficlSystemInformation); }
1592 ficlCallback callback
;
1595 ficlDictionary
*dictionary
;
1596 ficlDictionary
*environment
;
1598 ficlWord
*interpreterLoop
[3];
1599 ficlWord
*parseList
[FICL_MAX_PARSE_STEPS
];
1601 ficlWord
*exitInnerWord
;
1602 ficlWord
*interpretWord
;
1604 #if FICL_WANT_LOCALS
1605 ficlDictionary
*locals
;
1606 ficlInteger localsCount
;
1607 ficlCell
*localsFixup
;
1610 ficlInteger stackSize
;
1612 ficlBreakpoint breakpoint
;
1615 #define ficlSystemGetContext(system) ((system)->context)
1618 * External interface to Ficl...
1621 * f i c l S y s t e m C r e a t e
1622 * Binds a global dictionary to the interpreter system and initializes
1623 * the dictionary to contain the ANSI CORE wordset.
1624 * You can specify the address and size of the allocated area.
1625 * You can also specify the text output function at creation time.
1626 * After that, Ficl manages it.
1627 * First step is to set up the static pointers to the area.
1628 * Then write the "precompiled" portion of the dictionary in.
1629 * The dictionary needs to be at least large enough to hold the
1630 * precompiled part. Try 1K cells minimum. Use "words" to find
1631 * out how much of the dictionary is used at any time.
1633 FICL_PLATFORM_EXTERN ficlSystem
*ficlSystemCreate(ficlSystemInformation
*fsi
);
1636 * f i c l S y s t e m D e s t r o y
1637 * Deletes the system dictionary and all virtual machines that
1638 * were created with ficlNewVM (see below). Call this function to
1639 * reclaim all memory used by the dictionary and VMs.
1641 FICL_PLATFORM_EXTERN
void ficlSystemDestroy(ficlSystem
*system
);
1644 * Create a new VM from the heap, and link it into the system VM list.
1645 * Initializes the VM and binds default sized stacks to it. Returns the
1646 * address of the VM, or NULL if an error occurs.
1647 * Precondition: successful execution of ficlInitSystem
1649 FICL_PLATFORM_EXTERN ficlVm
*ficlSystemCreateVm(ficlSystem
*system
);
1652 * Force deletion of a VM. You do not need to do this
1653 * unless you're creating and discarding a lot of VMs.
1654 * For systems that use a constant pool of VMs for the life
1655 * of the system, ficltermSystem takes care of VM cleanup
1658 FICL_PLATFORM_EXTERN
void ficlSystemDestroyVm(ficlVm
*vm
);
1662 * Returns the address of the most recently defined word in the system
1663 * dictionary with the given name, or NULL if no match.
1664 * Precondition: successful execution of ficlInitSystem
1666 FICL_PLATFORM_EXTERN ficlWord
*ficlSystemLookup(ficlSystem
*system
, char *name
);
1669 * f i c l G e t D i c t
1670 * Utility function - returns the address of the system dictionary.
1671 * Precondition: successful execution of ficlInitSystem
1673 ficlDictionary
*ficlSystemGetDictionary(ficlSystem
*system
);
1674 ficlDictionary
*ficlSystemGetEnvironment(ficlSystem
*system
);
1675 #if FICL_WANT_LOCALS
1676 ficlDictionary
*ficlSystemGetLocals(ficlSystem
*system
);
1680 * f i c l C o m p i l e C o r e
1681 * Builds the ANS CORE wordset into the dictionary - called by
1682 * ficlInitSystem - no need to waste dictionary space by doing it again.
1684 FICL_PLATFORM_EXTERN
void ficlSystemCompileCore(ficlSystem
*system
);
1685 FICL_PLATFORM_EXTERN
void ficlSystemCompilePrefix(ficlSystem
*system
);
1686 FICL_PLATFORM_EXTERN
void ficlSystemCompileSearch(ficlSystem
*system
);
1687 FICL_PLATFORM_EXTERN
void ficlSystemCompileSoftCore(ficlSystem
*system
);
1688 FICL_PLATFORM_EXTERN
void ficlSystemCompileTools(ficlSystem
*system
);
1689 FICL_PLATFORM_EXTERN
void ficlSystemCompileFile(ficlSystem
*system
);
1691 FICL_PLATFORM_EXTERN
void ficlSystemCompileFloat(ficlSystem
*system
);
1692 FICL_PLATFORM_EXTERN
int ficlVmParseFloatNumber(ficlVm
*vm
, ficlString s
);
1693 #endif /* FICL_WANT_FLOAT */
1694 #if FICL_WANT_PLATFORM
1695 FICL_PLATFORM_EXTERN
void ficlSystemCompilePlatform(ficlSystem
*system
);
1696 #endif /* FICL_WANT_PLATFORM */
1697 FICL_PLATFORM_EXTERN
void ficlSystemCompileExtras(ficlSystem
*system
);
1700 FICL_PLATFORM_EXTERN
int ficlVmParsePrefix(ficlVm
*vm
, ficlString s
);
1702 #if FICL_WANT_LOCALS
1703 FICL_PLATFORM_EXTERN ficlWord
*ficlSystemLookupLocal(ficlSystem
*system
,
1710 FICL_PLATFORM_EXTERN
int ficlVmParseNumber(ficlVm
*vm
, ficlString s
);
1711 FICL_PLATFORM_EXTERN
void ficlPrimitiveTick(ficlVm
*vm
);
1712 FICL_PLATFORM_EXTERN
void ficlPrimitiveParseStepParen(ficlVm
*vm
);
1713 #if FICL_WANT_LOCALS
1714 FICL_PLATFORM_EXTERN
void ficlLocalParen(ficlVm
*vm
, int isDouble
, int isFloat
);
1715 #endif /* FICL_WANT_LOCALS */
1718 * Appends a parse step function to the end of the parse list (see
1719 * FICL_PARSE_STEP notes in ficl.h for details). Returns 0 if successful,
1720 * nonzero if there's no more room in the list. Each parse step is a word in
1721 * the dictionary. Precompiled parse steps can use (PARSE-STEP) as their
1722 * CFA - see parenParseStep in words.c.
1724 FICL_PLATFORM_EXTERN
int ficlSystemAddParseStep(ficlSystem
*system
,
1725 ficlWord
*word
); /* ficl.c */
1726 FICL_PLATFORM_EXTERN
void ficlSystemAddPrimitiveParseStep(ficlSystem
*system
,
1727 char *name
, ficlParseStep pStep
);
1734 * The following supports SEE and the debugger.
1738 FICL_WORDKIND_BRANCH
,
1739 FICL_WORDKIND_BRANCH0
,
1740 FICL_WORDKIND_COLON
,
1741 FICL_WORDKIND_CONSTANT
,
1742 FICL_WORDKIND_2CONSTANT
,
1743 FICL_WORDKIND_CREATE
,
1746 FICL_WORDKIND_LITERAL
,
1747 FICL_WORDKIND_2LITERAL
,
1749 FICL_WORDKIND_FLITERAL
,
1750 #endif /* FICL_WANT_FLOAT */
1753 FICL_WORDKIND_PLOOP
,
1754 FICL_WORDKIND_PRIMITIVE
,
1756 FICL_WORDKIND_STRING_LITERAL
,
1757 FICL_WORDKIND_CSTRING_LITERAL
,
1761 FICL_WORDKIND_VARIABLE
,
1762 FICL_WORDKIND_INSTRUCTION
,
1763 FICL_WORDKIND_INSTRUCTION_WORD
,
1764 FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT
1767 ficlWordKind
ficlWordClassify(ficlWord
*word
);
1771 * Used with File-Access wordset.
1773 #define FICL_FAM_READ 1
1774 #define FICL_FAM_WRITE 2
1775 #define FICL_FAM_APPEND 4
1776 #define FICL_FAM_BINARY 8
1778 #define FICL_FAM_OPEN_MODE(fam) \
1779 ((fam) & (FICL_FAM_READ | FICL_FAM_WRITE | FICL_FAM_APPEND))
1781 typedef struct ficlFile
1787 #if defined(FICL_PLATFORM_HAS_FTRUNCATE)
1788 FICL_PLATFORM_EXTERN
int ficlFileTruncate(ficlFile
*ff
, ficlUnsigned size
);
1791 FICL_PLATFORM_EXTERN
int ficlFileStatus(char *filename
, int *status
);
1792 FICL_PLATFORM_EXTERN
long ficlFileSize(ficlFile
*ff
);
1799 #endif /* _FICL_H */