xref: /illumos-gate/usr/src/common/ficl/ficl.h (revision c0bb4f73)
1afc2ba1dSToomas Soome /*
2afc2ba1dSToomas Soome  * f i c l . h
3afc2ba1dSToomas Soome  * Forth Inspired Command Language
4afc2ba1dSToomas Soome  * Author: John Sadler (john_sadler@alum.mit.edu)
5afc2ba1dSToomas Soome  * Created: 19 July 1997
6afc2ba1dSToomas Soome  * Dedicated to RHS, in loving memory
7afc2ba1dSToomas Soome  * $Id: ficl.h,v 1.25 2010/10/03 09:52:12 asau Exp $
8afc2ba1dSToomas Soome  */
9afc2ba1dSToomas Soome /*
10afc2ba1dSToomas Soome  * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11afc2ba1dSToomas Soome  * All rights reserved.
12afc2ba1dSToomas Soome  *
13afc2ba1dSToomas Soome  * Get the latest Ficl release at http://ficl.sourceforge.net
14afc2ba1dSToomas Soome  *
15afc2ba1dSToomas Soome  * I am interested in hearing from anyone who uses Ficl. If you have
16afc2ba1dSToomas Soome  * a problem, a success story, a defect, an enhancement request, or
17afc2ba1dSToomas Soome  * if you would like to contribute to the Ficl release, please
18afc2ba1dSToomas Soome  * contact me by email at the address above.
19afc2ba1dSToomas Soome  *
20afc2ba1dSToomas Soome  * L I C E N S E  and  D I S C L A I M E R
21afc2ba1dSToomas Soome  *
22afc2ba1dSToomas Soome  * Redistribution and use in source and binary forms, with or without
23afc2ba1dSToomas Soome  * modification, are permitted provided that the following conditions
24afc2ba1dSToomas Soome  * are met:
25afc2ba1dSToomas Soome  * 1. Redistributions of source code must retain the above copyright
26afc2ba1dSToomas Soome  *    notice, this list of conditions and the following disclaimer.
27afc2ba1dSToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
28afc2ba1dSToomas Soome  *    notice, this list of conditions and the following disclaimer in the
29afc2ba1dSToomas Soome  *    documentation and/or other materials provided with the distribution.
30afc2ba1dSToomas Soome  *
31afc2ba1dSToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32afc2ba1dSToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33afc2ba1dSToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34afc2ba1dSToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35afc2ba1dSToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36afc2ba1dSToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37afc2ba1dSToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38afc2ba1dSToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39afc2ba1dSToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40afc2ba1dSToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41afc2ba1dSToomas Soome  * SUCH DAMAGE.
42afc2ba1dSToomas Soome  */
43afc2ba1dSToomas Soome 
44afc2ba1dSToomas Soome #ifndef	_FICL_H
45afc2ba1dSToomas Soome #define	_FICL_H
46afc2ba1dSToomas Soome /*
47afc2ba1dSToomas Soome  * Ficl (Forth-inspired command language) is an ANS Forth
48afc2ba1dSToomas Soome  * interpreter written in C. Unlike traditional Forths, this
49afc2ba1dSToomas Soome  * interpreter is designed to be embedded into other systems
50afc2ba1dSToomas Soome  * as a command/macro/development prototype language.
51afc2ba1dSToomas Soome  *
52afc2ba1dSToomas Soome  * Where Forths usually view themselves as the center of the system
53afc2ba1dSToomas Soome  * and expect the rest of the system to be coded in Forth, Ficl
54afc2ba1dSToomas Soome  * acts as a component of the system. It is easy to export
55afc2ba1dSToomas Soome  * code written in C or ASM to Ficl in the style of TCL, or to invoke
56afc2ba1dSToomas Soome  * Ficl code from a compiled module. This allows you to do incremental
57afc2ba1dSToomas Soome  * development in a way that combines the best features of threaded
58afc2ba1dSToomas Soome  * languages (rapid development, quick code/test/debug cycle,
59afc2ba1dSToomas Soome  * reasonably fast) with the best features of C (everyone knows it,
60afc2ba1dSToomas Soome  * easier to support large blocks of code, efficient, type checking).
61afc2ba1dSToomas Soome  *
62afc2ba1dSToomas Soome  * Ficl provides facilities for interoperating
63afc2ba1dSToomas Soome  * with programs written in C: C functions can be exported to Ficl,
64afc2ba1dSToomas Soome  * and Ficl commands can be executed via a C calling interface. The
65afc2ba1dSToomas Soome  * interpreter is re-entrant, so it can be used in multiple instances
66afc2ba1dSToomas Soome  * in a multitasking system. Unlike Forth, Ficl's outer interpreter
67afc2ba1dSToomas Soome  * expects a text block as input, and returns to the caller after each
68afc2ba1dSToomas Soome  * text block, so the "data pump" is somewhere in external code. This
69afc2ba1dSToomas Soome  * is more like TCL than Forth, which usually expects to be at the center
70afc2ba1dSToomas Soome  * of the system, requesting input at its convenience. Each Ficl virtual
71afc2ba1dSToomas Soome  * machine can be bound to a different I/O channel, and is independent
72afc2ba1dSToomas Soome  * of all others in in the same address space except that all virtual
73afc2ba1dSToomas Soome  * machines share a common dictionary (a sort or open symbol table that
74afc2ba1dSToomas Soome  * defines all of the elements of the language).
75afc2ba1dSToomas Soome  *
76afc2ba1dSToomas Soome  * Code is written in ANSI C for portability.
77afc2ba1dSToomas Soome  *
78afc2ba1dSToomas Soome  * Summary of Ficl features and constraints:
79afc2ba1dSToomas Soome  * - Standard: Implements the ANSI Forth CORE word set and part
80afc2ba1dSToomas Soome  *   of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and
81afc2ba1dSToomas Soome  *   TOOLS EXT, LOCAL and LOCAL ext and various extras.
82afc2ba1dSToomas Soome  * - Extensible: you can export code written in Forth, C,
83afc2ba1dSToomas Soome  *   or asm in a straightforward way. Ficl provides open
84afc2ba1dSToomas Soome  *   facilities for extending the language in an application
85afc2ba1dSToomas Soome  *   specific way. You can even add new control structures!
86afc2ba1dSToomas Soome  * - Ficl and C can interact in two ways: Ficl can encapsulate
87afc2ba1dSToomas Soome  *   C code, or C code can invoke Ficl code.
88afc2ba1dSToomas Soome  * - Thread-safe, re-entrant: The shared system dictionary
89afc2ba1dSToomas Soome  *   uses a locking mechanism that you can either supply
90afc2ba1dSToomas Soome  *   or stub out to provide exclusive access. Each Ficl
91afc2ba1dSToomas Soome  *   virtual machine has an otherwise complete state, and
92afc2ba1dSToomas Soome  *   each can be bound to a separate I/O channel (or none at all).
93afc2ba1dSToomas Soome  * - Simple encapsulation into existing systems: a basic implementation
94afc2ba1dSToomas Soome  *   requires three function calls (see the example program in testmain.c).
95afc2ba1dSToomas Soome  * - ROMable: Ficl is designed to work in RAM-based and ROM code / RAM data
96afc2ba1dSToomas Soome  *   environments. It does require somewhat more memory than a pure
97afc2ba1dSToomas Soome  *   ROM implementation because it builds its system dictionary in
98afc2ba1dSToomas Soome  *   RAM at startup time.
99afc2ba1dSToomas Soome  * - Written an ANSI C to be as simple as I can make it to understand,
100afc2ba1dSToomas Soome  *   support, debug, and port. Compiles without complaint at /Az /W4
101afc2ba1dSToomas Soome  *   (require ANSI C, max warnings) under Microsoft VC++ 5.
102afc2ba1dSToomas Soome  * - Does full 32 bit math (but you need to implement
103afc2ba1dSToomas Soome  *   two mixed precision math primitives (see sysdep.c))
104afc2ba1dSToomas Soome  * - Indirect threaded interpreter is not the fastest kind of
105afc2ba1dSToomas Soome  *   Forth there is (see pForth 68K for a really fast subroutine
106afc2ba1dSToomas Soome  *   threaded interpreter), but it's the cleanest match to a
107afc2ba1dSToomas Soome  *   pure C implementation.
108afc2ba1dSToomas Soome  *
109afc2ba1dSToomas Soome  * P O R T I N G   F i c l
110afc2ba1dSToomas Soome  *
111afc2ba1dSToomas Soome  * To install Ficl on your target system, you need an ANSI C compiler
112afc2ba1dSToomas Soome  * and its runtime library. Inspect the system dependent macros and
113afc2ba1dSToomas Soome  * functions in sysdep.h and sysdep.c and edit them to suit your
114afc2ba1dSToomas Soome  * system. For example, INT16 is a short on some compilers and an
115afc2ba1dSToomas Soome  * int on others. Check the default CELL alignment controlled by
116afc2ba1dSToomas Soome  * FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree,
117afc2ba1dSToomas Soome  * ficlLockDictionary, and ficlCallbackDefaultTextOut to work with your
118afc2ba1dSToomas Soome  * operating system.  Finally, use testmain.c as a guide to installing the
119afc2ba1dSToomas Soome  * Ficl system and one or more virtual machines into your code. You do not
120afc2ba1dSToomas Soome  * need to include testmain.c in your build.
121afc2ba1dSToomas Soome  *
122afc2ba1dSToomas Soome  * T o   D o   L i s t
123afc2ba1dSToomas Soome  *
124afc2ba1dSToomas Soome  * 1. Unimplemented system dependent CORE word: key
125afc2ba1dSToomas Soome  * 2. Ficl uses the PAD in some CORE words - this violates the standard,
126afc2ba1dSToomas Soome  *    but it's cleaner for a multithreaded system. I'll have to make a
127afc2ba1dSToomas Soome  *    second pad for reference by the word PAD to fix this.
128afc2ba1dSToomas Soome  *
129afc2ba1dSToomas Soome  * F o r   M o r e   I n f o r m a t i o n
130afc2ba1dSToomas Soome  *
131afc2ba1dSToomas Soome  * Web home of Ficl
132afc2ba1dSToomas Soome  *   http://ficl.sourceforge.net
133afc2ba1dSToomas Soome  * Check this website for Forth literature (including the ANSI standard)
134afc2ba1dSToomas Soome  *   http://www.taygeta.com/forthlit.html
135afc2ba1dSToomas Soome  * and here for software and more links
136afc2ba1dSToomas Soome  *   http://www.taygeta.com/forth.html
137afc2ba1dSToomas Soome  */
138afc2ba1dSToomas Soome 
139afc2ba1dSToomas Soome #ifdef __cplusplus
140afc2ba1dSToomas Soome extern "C" {
141afc2ba1dSToomas Soome #endif
142afc2ba1dSToomas Soome 
14368d77045SToomas Soome #ifdef _STANDALONE
144afc2ba1dSToomas Soome #include <stand.h>
145afc2ba1dSToomas Soome #include <sys/stdint.h>
146eee59048SToomas Soome #include <sys/linker_set.h>
147afc2ba1dSToomas Soome #else
148afc2ba1dSToomas Soome #include <ctype.h>
149afc2ba1dSToomas Soome #include <stdio.h>
150afc2ba1dSToomas Soome #include <stdlib.h>
151afc2ba1dSToomas Soome #include <stdint.h>
152afc2ba1dSToomas Soome #include <string.h>
153afc2ba1dSToomas Soome 
154*c0bb4f73SToomas Soome #define	__dead2	__NORETURN
155afc2ba1dSToomas Soome extern void pager_open(void);
156afc2ba1dSToomas Soome extern int pager_output(const char *);
157afc2ba1dSToomas Soome extern void pager_close(void);
158afc2ba1dSToomas Soome #endif
159afc2ba1dSToomas Soome #include <setjmp.h>
160afc2ba1dSToomas Soome #include <stdarg.h>
161afc2ba1dSToomas Soome 
162afc2ba1dSToomas Soome /*
163afc2ba1dSToomas Soome  * Put all your local defines in ficllocal.h,
164afc2ba1dSToomas Soome  * rather than editing the makefile/project/etc.
165afc2ba1dSToomas Soome  * ficllocal.h will always ship as an inert file.
166afc2ba1dSToomas Soome  */
167afc2ba1dSToomas Soome 
168afc2ba1dSToomas Soome #include "ficllocal.h"
169afc2ba1dSToomas Soome #include "ficlplatform/unix.h"
170afc2ba1dSToomas Soome 
171afc2ba1dSToomas Soome /*
172afc2ba1dSToomas Soome  *
173afc2ba1dSToomas Soome  * B U I L D   C O N T R O L S
174afc2ba1dSToomas Soome  *
175afc2ba1dSToomas Soome  * First, the FICL_WANT_* settings.
176afc2ba1dSToomas Soome  * These are all optional settings that you may or may not
177afc2ba1dSToomas Soome  * want Ficl to use.
178afc2ba1dSToomas Soome  *
179afc2ba1dSToomas Soome  */
180afc2ba1dSToomas Soome 
181afc2ba1dSToomas Soome /*
182afc2ba1dSToomas Soome  * FICL_WANT_MINIMAL
183afc2ba1dSToomas Soome  * If set to nonzero, build the smallest possible Ficl interpreter.
184afc2ba1dSToomas Soome  */
185afc2ba1dSToomas Soome #if !defined(FICL_WANT_MINIMAL)
186afc2ba1dSToomas Soome #define	FICL_WANT_MINIMAL		(0)
187afc2ba1dSToomas Soome #endif
188afc2ba1dSToomas Soome 
189afc2ba1dSToomas Soome #if FICL_WANT_MINIMAL
190afc2ba1dSToomas Soome #define	FICL_WANT_SOFTWORDS		(0)
191afc2ba1dSToomas Soome #define	FICL_WANT_FILE			(0)
192afc2ba1dSToomas Soome #define	FICL_WANT_FLOAT			(0)
193afc2ba1dSToomas Soome #define	FICL_WANT_USER			(0)
194afc2ba1dSToomas Soome #define	FICL_WANT_LOCALS		(0)
195afc2ba1dSToomas Soome #define	FICL_WANT_DEBUGGER		(0)
196afc2ba1dSToomas Soome #define	FICL_WANT_OOP			(0)
197afc2ba1dSToomas Soome #define	FICL_WANT_PLATFORM		(0)
198afc2ba1dSToomas Soome #define	FICL_WANT_MULTITHREADED		(0)
199afc2ba1dSToomas Soome #define	FICL_WANT_EXTENDED_PREFIX	(0)
200afc2ba1dSToomas Soome 
201afc2ba1dSToomas Soome #define	FICL_ROBUST			(0)
202afc2ba1dSToomas Soome 
203afc2ba1dSToomas Soome #endif /* FICL_WANT_MINIMAL */
204afc2ba1dSToomas Soome 
205afc2ba1dSToomas Soome /*
206afc2ba1dSToomas Soome  * FICL_WANT_PLATFORM
207afc2ba1dSToomas Soome  * Includes words defined in ficlCompilePlatform
208afc2ba1dSToomas Soome  * (see ficlplatform/win32.c and ficlplatform/unix.c for example)
209afc2ba1dSToomas Soome  */
210afc2ba1dSToomas Soome #if !defined(FICL_WANT_PLATFORM)
211afc2ba1dSToomas Soome #define	FICL_WANT_PLATFORM	(1)
212afc2ba1dSToomas Soome #endif /* FICL_WANT_PLATFORM */
213afc2ba1dSToomas Soome 
214afc2ba1dSToomas Soome /*
215afc2ba1dSToomas Soome  * FICL_WANT_LZ4_SOFTCORE
216afc2ba1dSToomas Soome  * If nonzero, the softcore words are stored compressed
217afc2ba1dSToomas Soome  * with patent-unencumbered LZ4 compression.
218afc2ba1dSToomas Soome  * This results in a smaller Ficl interpreter, and adds
219afc2ba1dSToomas Soome  * only a *tiny* runtime speed hit.
220afc2ba1dSToomas Soome  *
221afc2ba1dSToomas Soome  * Original LZ77 contributed by Larry Hastings.
222afc2ba1dSToomas Soome  * Updated to LZ4 which is even more space efficient.
223afc2ba1dSToomas Soome  */
224afc2ba1dSToomas Soome #if !defined(FICL_WANT_LZ4_SOFTCORE)
225afc2ba1dSToomas Soome #define	FICL_WANT_LZ4_SOFTCORE	(1)
226afc2ba1dSToomas Soome #endif /* FICL_WANT_LZ4_SOFTCORE */
227afc2ba1dSToomas Soome 
228afc2ba1dSToomas Soome /*
229afc2ba1dSToomas Soome  * FICL_WANT_FILE
230afc2ba1dSToomas Soome  * Includes the FILE and FILE-EXT wordset and associated code.
231afc2ba1dSToomas Soome  * Turn this off if you do not have a file system!
232afc2ba1dSToomas Soome  * Contributed by Larry Hastings
233afc2ba1dSToomas Soome  */
234afc2ba1dSToomas Soome #if !defined(FICL_WANT_FILE)
235afc2ba1dSToomas Soome #define	FICL_WANT_FILE	(0)
236afc2ba1dSToomas Soome #endif /* FICL_WANT_FILE */
237afc2ba1dSToomas Soome 
238afc2ba1dSToomas Soome /*
239afc2ba1dSToomas Soome  * FICL_WANT_FLOAT
240afc2ba1dSToomas Soome  * Includes a floating point stack for the VM, and words to do float operations.
241afc2ba1dSToomas Soome  * Contributed by Guy Carver
242afc2ba1dSToomas Soome  */
243afc2ba1dSToomas Soome #if !defined(FICL_WANT_FLOAT)
244afc2ba1dSToomas Soome #define	FICL_WANT_FLOAT	(1)
245afc2ba1dSToomas Soome #endif /* FICL_WANT_FLOAT */
246afc2ba1dSToomas Soome 
247afc2ba1dSToomas Soome /*
248afc2ba1dSToomas Soome  * FICL_WANT_DEBUGGER
249afc2ba1dSToomas Soome  * Inludes a simple source level debugger
250afc2ba1dSToomas Soome  */
251afc2ba1dSToomas Soome #if !defined(FICL_WANT_DEBUGGER)
252afc2ba1dSToomas Soome #define	FICL_WANT_DEBUGGER	(1)
253afc2ba1dSToomas Soome #endif /* FICL_WANT_DEBUGGER */
254afc2ba1dSToomas Soome 
255afc2ba1dSToomas Soome /*
256afc2ba1dSToomas Soome  * FICL_EXTENDED_PREFIX
257afc2ba1dSToomas Soome  * Enables a bunch of extra prefixes in prefix.c
258afc2ba1dSToomas Soome  * and prefix.fr (if included as part of softcore.c)
259afc2ba1dSToomas Soome  */
260afc2ba1dSToomas Soome #if !defined(FICL_WANT_EXTENDED_PREFIX)
261afc2ba1dSToomas Soome #define	FICL_WANT_EXTENDED_PREFIX	(1)
262afc2ba1dSToomas Soome #endif /* FICL_WANT_EXTENDED_PREFIX */
263afc2ba1dSToomas Soome 
264afc2ba1dSToomas Soome /*
265afc2ba1dSToomas Soome  * FICL_WANT_USER
266afc2ba1dSToomas Soome  * Enables user variables: per-instance variables bound to the VM.
267afc2ba1dSToomas Soome  * Kind of like thread-local storage. Could be implemented in a
268afc2ba1dSToomas Soome  * VM private dictionary, but I've chosen the lower overhead
269afc2ba1dSToomas Soome  * approach of an array of CELLs instead.
270afc2ba1dSToomas Soome  */
271afc2ba1dSToomas Soome #if !defined(FICL_WANT_USER)
272afc2ba1dSToomas Soome #define	FICL_WANT_USER	(1)
273afc2ba1dSToomas Soome #endif /* FICL_WANT_USER */
274afc2ba1dSToomas Soome 
275afc2ba1dSToomas Soome /*
276afc2ba1dSToomas Soome  * FICL_WANT_LOCALS
277afc2ba1dSToomas Soome  * Controls the creation of the LOCALS wordset
278afc2ba1dSToomas Soome  * and a private dictionary for local variable compilation.
279afc2ba1dSToomas Soome  */
280afc2ba1dSToomas Soome #if !defined FICL_WANT_LOCALS
281afc2ba1dSToomas Soome #define	FICL_WANT_LOCALS	(1)
282afc2ba1dSToomas Soome #endif /* FICL_WANT_LOCALS */
283afc2ba1dSToomas Soome 
284afc2ba1dSToomas Soome /*
285afc2ba1dSToomas Soome  * FICL_WANT_OOP
286afc2ba1dSToomas Soome  * Inludes object oriented programming support (in softwords)
287afc2ba1dSToomas Soome  * OOP support requires locals and user variables!
288afc2ba1dSToomas Soome  */
289afc2ba1dSToomas Soome #if !defined(FICL_WANT_OOP)
290afc2ba1dSToomas Soome #define	FICL_WANT_OOP	((FICL_WANT_LOCALS) && (FICL_WANT_USER))
291afc2ba1dSToomas Soome #endif /* FICL_WANT_OOP */
292afc2ba1dSToomas Soome 
293afc2ba1dSToomas Soome /*
294afc2ba1dSToomas Soome  * FICL_WANT_SOFTWORDS
295afc2ba1dSToomas Soome  * Controls inclusion of all softwords in softcore.c.
296afc2ba1dSToomas Soome  */
297afc2ba1dSToomas Soome #if !defined(FICL_WANT_SOFTWORDS)
298afc2ba1dSToomas Soome #define	FICL_WANT_SOFTWORDS	(1)
299afc2ba1dSToomas Soome #endif /* FICL_WANT_SOFTWORDS */
300afc2ba1dSToomas Soome 
301afc2ba1dSToomas Soome /*
302afc2ba1dSToomas Soome  * FICL_WANT_MULTITHREADED
303afc2ba1dSToomas Soome  * Enables dictionary mutual exclusion wia the
304afc2ba1dSToomas Soome  * ficlLockDictionary() system dependent function.
305afc2ba1dSToomas Soome  *
306afc2ba1dSToomas Soome  * Note: this implementation is experimental and poorly
307afc2ba1dSToomas Soome  * tested. Further, it's unnecessary unless you really
308afc2ba1dSToomas Soome  * intend to have multiple SESSIONS (poor choice of name
309afc2ba1dSToomas Soome  * on my part) - that is, threads that modify the dictionary
310afc2ba1dSToomas Soome  * at the same time.
311afc2ba1dSToomas Soome  */
312afc2ba1dSToomas Soome #if !defined FICL_WANT_MULTITHREADED
313afc2ba1dSToomas Soome #define	FICL_WANT_MULTITHREADED	(0)
314afc2ba1dSToomas Soome #endif /* FICL_WANT_MULTITHREADED */
315afc2ba1dSToomas Soome 
316afc2ba1dSToomas Soome /*
317afc2ba1dSToomas Soome  * FICL_WANT_OPTIMIZE
318afc2ba1dSToomas Soome  * Do you want to optimize for size, or for speed?
319afc2ba1dSToomas Soome  * Note that this doesn't affect Ficl very much one way
320afc2ba1dSToomas Soome  * or the other at the moment.
321afc2ba1dSToomas Soome  * Contributed by Larry Hastings
322afc2ba1dSToomas Soome  */
323afc2ba1dSToomas Soome #define	FICL_OPTIMIZE_FOR_SPEED	(1)
324afc2ba1dSToomas Soome #define	FICL_OPTIMIZE_FOR_SIZE	(2)
325afc2ba1dSToomas Soome #if !defined(FICL_WANT_OPTIMIZE)
326afc2ba1dSToomas Soome #define	FICL_WANT_OPTIMIZE FICL_OPTIMIZE_FOR_SPEED
327afc2ba1dSToomas Soome #endif /* FICL_WANT_OPTIMIZE */
328afc2ba1dSToomas Soome 
329afc2ba1dSToomas Soome /*
330afc2ba1dSToomas Soome  * FICL_WANT_VCALL
331afc2ba1dSToomas Soome  * Ficl OO support for calling vtable methods.  Win32 only.
332afc2ba1dSToomas Soome  * Contributed by Guy Carver
333afc2ba1dSToomas Soome  */
334afc2ba1dSToomas Soome #if !defined(FICL_WANT_VCALL)
335afc2ba1dSToomas Soome #define	FICL_WANT_VCALL	(0)
336afc2ba1dSToomas Soome #endif /* FICL_WANT_VCALL */
337afc2ba1dSToomas Soome 
338afc2ba1dSToomas Soome /*
339afc2ba1dSToomas Soome  * P L A T F O R M   S E T T I N G S
340afc2ba1dSToomas Soome  *
341afc2ba1dSToomas Soome  * The FICL_PLATFORM_* settings.
342afc2ba1dSToomas Soome  * These indicate attributes about the local platform.
343afc2ba1dSToomas Soome  */
344afc2ba1dSToomas Soome 
345afc2ba1dSToomas Soome /*
346afc2ba1dSToomas Soome  * FICL_PLATFORM_OS
347afc2ba1dSToomas Soome  * String constant describing the current hardware architecture.
348afc2ba1dSToomas Soome  */
349afc2ba1dSToomas Soome #if !defined(FICL_PLATFORM_ARCHITECTURE)
350afc2ba1dSToomas Soome #define	FICL_PLATFORM_ARCHITECTURE	"unknown"
351afc2ba1dSToomas Soome #endif
352afc2ba1dSToomas Soome 
353afc2ba1dSToomas Soome /*
354afc2ba1dSToomas Soome  * FICL_PLATFORM_OS
355afc2ba1dSToomas Soome  * String constant describing the current operating system.
356afc2ba1dSToomas Soome  */
357afc2ba1dSToomas Soome #if !defined(FICL_PLATFORM_OS)
358afc2ba1dSToomas Soome #define	FICL_PLATFORM_OS	"unknown"
359afc2ba1dSToomas Soome #endif
360afc2ba1dSToomas Soome 
361afc2ba1dSToomas Soome /*
362afc2ba1dSToomas Soome  * FICL_PLATFORM_HAS_2INTEGER
363afc2ba1dSToomas Soome  * Indicates whether or not the current architecture
364afc2ba1dSToomas Soome  * supports a native double-width integer type.
365afc2ba1dSToomas Soome  * If you set this to 1 in your ficlplatform/ *.h file,
366afc2ba1dSToomas Soome  * you *must* create typedefs for the following two types:
367afc2ba1dSToomas Soome  *        ficl2Unsigned
368afc2ba1dSToomas Soome  *        ficl2Integer
369afc2ba1dSToomas Soome  * If this is set to 0, Ficl will implement double-width
370afc2ba1dSToomas Soome  * integer math in C, which is both bigger *and* slower
371afc2ba1dSToomas Soome  * (the double whammy!).  Make sure your compiler really
372afc2ba1dSToomas Soome  * genuinely doesn't support native double-width integers
373afc2ba1dSToomas Soome  * before setting this to 0.
374afc2ba1dSToomas Soome  */
375afc2ba1dSToomas Soome #if !defined(FICL_PLATFORM_HAS_2INTEGER)
376afc2ba1dSToomas Soome #define	FICL_PLATFORM_HAS_2INTEGER	(0)
377afc2ba1dSToomas Soome #endif
378afc2ba1dSToomas Soome 
379afc2ba1dSToomas Soome /*
380afc2ba1dSToomas Soome  * FICL_PLATFORM_HAS_FTRUNCATE
381afc2ba1dSToomas Soome  * Indicates whether or not the current platform provides
382afc2ba1dSToomas Soome  * the ftruncate() function (available on most UNIXes).
383afc2ba1dSToomas Soome  * This function is necessary to provide the complete
384afc2ba1dSToomas Soome  * File-Access wordset.
385afc2ba1dSToomas Soome  *
386afc2ba1dSToomas Soome  * If your platform does not have ftruncate() per se,
387afc2ba1dSToomas Soome  * but does have some method of truncating files, you
388afc2ba1dSToomas Soome  * should be able to implement ftruncate() yourself and
389afc2ba1dSToomas Soome  * set this constant to 1.  For an example of this see
390afc2ba1dSToomas Soome  * "ficlplatform/win32.c".
391afc2ba1dSToomas Soome  */
392afc2ba1dSToomas Soome #if !defined(FICL_PLATFORM_HAS_FTRUNCATE)
393afc2ba1dSToomas Soome #define	FICL_PLATFORM_HAS_FTRUNCATE	(0)
394afc2ba1dSToomas Soome #endif
395afc2ba1dSToomas Soome 
396afc2ba1dSToomas Soome /*
397afc2ba1dSToomas Soome  * FICL_PLATFORM_INLINE
398afc2ba1dSToomas Soome  * Must be defined, should be a function prototype type-modifying
399afc2ba1dSToomas Soome  * keyword that makes a function "inline".  Ficl does not assume
400afc2ba1dSToomas Soome  * that the local platform supports inline functions; it therefore
401afc2ba1dSToomas Soome  * only uses "inline" where "static" would also work, and uses "static"
402afc2ba1dSToomas Soome  * in the absence of another keyword.
403afc2ba1dSToomas Soome  */
404afc2ba1dSToomas Soome #if !defined FICL_PLATFORM_INLINE
405afc2ba1dSToomas Soome #define	FICL_PLATFORM_INLINE	inline
406afc2ba1dSToomas Soome #endif /* !defined FICL_PLATFORM_INLINE */
407afc2ba1dSToomas Soome 
408afc2ba1dSToomas Soome /*
409afc2ba1dSToomas Soome  * FICL_PLATFORM_EXTERN
410afc2ba1dSToomas Soome  * Must be defined, should be a keyword used to declare
411afc2ba1dSToomas Soome  * a function prototype as being a genuine prototype.
412afc2ba1dSToomas Soome  * You should only have to fiddle with this setting if
413afc2ba1dSToomas Soome  * you're not using an ANSI-compliant compiler, in which
414afc2ba1dSToomas Soome  * case, good luck!
415afc2ba1dSToomas Soome  */
416afc2ba1dSToomas Soome #if !defined FICL_PLATFORM_EXTERN
417afc2ba1dSToomas Soome #define	FICL_PLATFORM_EXTERN	extern
418afc2ba1dSToomas Soome #endif /* !defined FICL_PLATFORM_EXTERN */
419afc2ba1dSToomas Soome 
420afc2ba1dSToomas Soome /*
421afc2ba1dSToomas Soome  * FICL_PLATFORM_BASIC_TYPES
422afc2ba1dSToomas Soome  *
423afc2ba1dSToomas Soome  * If not defined yet,
424afc2ba1dSToomas Soome  */
425afc2ba1dSToomas Soome #if !defined(FICL_PLATFORM_BASIC_TYPES)
426afc2ba1dSToomas Soome typedef char ficlInteger8;
427afc2ba1dSToomas Soome typedef unsigned char ficlUnsigned8;
428afc2ba1dSToomas Soome typedef short ficlInteger16;
429afc2ba1dSToomas Soome typedef unsigned short ficlUnsigned16;
430afc2ba1dSToomas Soome typedef long ficlInteger32;
431afc2ba1dSToomas Soome typedef unsigned long ficlUnsigned32;
432afc2ba1dSToomas Soome 
433afc2ba1dSToomas Soome typedef ficlInteger32 ficlInteger;
434afc2ba1dSToomas Soome typedef ficlUnsigned32 ficlUnsigned;
435afc2ba1dSToomas Soome typedef float ficlFloat;
436afc2ba1dSToomas Soome 
437afc2ba1dSToomas Soome #endif /* !defined(FICL_PLATFORM_BASIC_TYPES) */
438afc2ba1dSToomas Soome 
439afc2ba1dSToomas Soome /*
440afc2ba1dSToomas Soome  * FICL_ROBUST enables bounds checking of stacks and the dictionary.
441afc2ba1dSToomas Soome  * This will detect stack over and underflows and dictionary overflows.
442afc2ba1dSToomas Soome  * Any exceptional condition will result in an assertion failure.
443afc2ba1dSToomas Soome  * (As generated by the ANSI assert macro)
444afc2ba1dSToomas Soome  * FICL_ROBUST == 1 --> stack checking in the outer interpreter
445afc2ba1dSToomas Soome  * FICL_ROBUST == 2 also enables checking in many primitives
446afc2ba1dSToomas Soome  */
447afc2ba1dSToomas Soome 
448afc2ba1dSToomas Soome #if !defined FICL_ROBUST
449afc2ba1dSToomas Soome #define	FICL_ROBUST	(2)
450afc2ba1dSToomas Soome #endif /* FICL_ROBUST */
451afc2ba1dSToomas Soome 
452afc2ba1dSToomas Soome /*
453afc2ba1dSToomas Soome  * FICL_DEFAULT_STACK_SIZE Specifies the default size (in CELLs) of
454afc2ba1dSToomas Soome  * a new virtual machine's stacks, unless overridden at
455afc2ba1dSToomas Soome  * create time.
456afc2ba1dSToomas Soome  */
457afc2ba1dSToomas Soome #if !defined FICL_DEFAULT_STACK_SIZE
458afc2ba1dSToomas Soome #define	FICL_DEFAULT_STACK_SIZE	(128)
459afc2ba1dSToomas Soome #endif
460afc2ba1dSToomas Soome 
461afc2ba1dSToomas Soome /*
462afc2ba1dSToomas Soome  * FICL_DEFAULT_DICTIONARY_SIZE specifies the number of ficlCells to allocate
463afc2ba1dSToomas Soome  * for the system dictionary by default. The value
464afc2ba1dSToomas Soome  * can be overridden at startup time as well.
465afc2ba1dSToomas Soome  */
466afc2ba1dSToomas Soome #if !defined FICL_DEFAULT_DICTIONARY_SIZE
467afc2ba1dSToomas Soome #define	FICL_DEFAULT_DICTIONARY_SIZE	(12288)
468afc2ba1dSToomas Soome #endif
469afc2ba1dSToomas Soome 
470afc2ba1dSToomas Soome /*
471afc2ba1dSToomas Soome  * FICL_DEFAULT_ENVIRONMENT_SIZE specifies the number of cells
472afc2ba1dSToomas Soome  * to allot for the environment-query dictionary.
473afc2ba1dSToomas Soome  */
474afc2ba1dSToomas Soome #if !defined FICL_DEFAULT_ENVIRONMENT_SIZE
475afc2ba1dSToomas Soome #define	FICL_DEFAULT_ENVIRONMENT_SIZE	(512)
476afc2ba1dSToomas Soome #endif
477afc2ba1dSToomas Soome 
478afc2ba1dSToomas Soome /*
479afc2ba1dSToomas Soome  * FICL_MAX_WORDLISTS specifies the maximum number of wordlists in
480afc2ba1dSToomas Soome  * the dictionary search order. See Forth DPANS sec 16.3.3
481afc2ba1dSToomas Soome  * (file://dpans16.htm#16.3.3)
482afc2ba1dSToomas Soome  */
483afc2ba1dSToomas Soome #if !defined FICL_MAX_WORDLISTS
484afc2ba1dSToomas Soome #define	FICL_MAX_WORDLISTS	(16)
485afc2ba1dSToomas Soome #endif
486afc2ba1dSToomas Soome 
487afc2ba1dSToomas Soome /*
488afc2ba1dSToomas Soome  * FICL_MAX_PARSE_STEPS controls the size of an array in the FICL_SYSTEM
489afc2ba1dSToomas Soome  * structure that stores pointers to parser extension functions. I would
490afc2ba1dSToomas Soome  * never expect to have more than 8 of these, so that's the default limit.
491afc2ba1dSToomas Soome  * Too many of these functions will probably exact a nasty performance penalty.
492afc2ba1dSToomas Soome  */
493afc2ba1dSToomas Soome #if !defined FICL_MAX_PARSE_STEPS
494afc2ba1dSToomas Soome #define	FICL_MAX_PARSE_STEPS	(8)
495afc2ba1dSToomas Soome #endif
496afc2ba1dSToomas Soome 
497afc2ba1dSToomas Soome /*
498afc2ba1dSToomas Soome  * Maximum number of local variables per definition.
499afc2ba1dSToomas Soome  * This only affects the size of the locals dictionary,
500afc2ba1dSToomas Soome  * and there's only one per entire ficlSystem, so it
501afc2ba1dSToomas Soome  * doesn't make sense to be a piker here.
502afc2ba1dSToomas Soome  */
503afc2ba1dSToomas Soome #if (!defined(FICL_MAX_LOCALS)) && FICL_WANT_LOCALS
504afc2ba1dSToomas Soome #define	FICL_MAX_LOCALS	(64)
505afc2ba1dSToomas Soome #endif
506afc2ba1dSToomas Soome 
507afc2ba1dSToomas Soome /*
508afc2ba1dSToomas Soome  * The pad is a small scratch area for text manipulation. ANS Forth
509afc2ba1dSToomas Soome  * requires it to hold at least 84 characters.
510afc2ba1dSToomas Soome  */
511afc2ba1dSToomas Soome #if !defined FICL_PAD_SIZE
512afc2ba1dSToomas Soome #define	FICL_PAD_SIZE	(256)
513afc2ba1dSToomas Soome #endif
514afc2ba1dSToomas Soome 
515afc2ba1dSToomas Soome /*
516afc2ba1dSToomas Soome  * ANS Forth requires that a word's name contain {1..31} characters.
517afc2ba1dSToomas Soome  */
518afc2ba1dSToomas Soome #if !defined FICL_NAME_LENGTH
519afc2ba1dSToomas Soome #define	FICL_NAME_LENGTH	(31)
520afc2ba1dSToomas Soome #endif
521afc2ba1dSToomas Soome 
522afc2ba1dSToomas Soome /*
523afc2ba1dSToomas Soome  * Default size of hash table. For most uniform
524afc2ba1dSToomas Soome  * performance, use a prime number!
525afc2ba1dSToomas Soome  */
526afc2ba1dSToomas Soome #if !defined FICL_HASH_SIZE
527afc2ba1dSToomas Soome #define	FICL_HASH_SIZE	(241)
528afc2ba1dSToomas Soome #endif
529afc2ba1dSToomas Soome 
530afc2ba1dSToomas Soome /*
531afc2ba1dSToomas Soome  * Default number of USER flags.
532afc2ba1dSToomas Soome  */
533afc2ba1dSToomas Soome #if (!defined(FICL_USER_CELLS)) && FICL_WANT_USER
534afc2ba1dSToomas Soome #define	FICL_USER_CELLS	(16)
535afc2ba1dSToomas Soome #endif
536afc2ba1dSToomas Soome 
537afc2ba1dSToomas Soome /*
538afc2ba1dSToomas Soome  * Forward declarations... read on.
539afc2ba1dSToomas Soome  */
540afc2ba1dSToomas Soome struct ficlWord;
541afc2ba1dSToomas Soome typedef struct ficlWord ficlWord;
542afc2ba1dSToomas Soome struct ficlVm;
543afc2ba1dSToomas Soome typedef struct ficlVm ficlVm;
544afc2ba1dSToomas Soome struct ficlDictionary;
545afc2ba1dSToomas Soome typedef struct ficlDictionary ficlDictionary;
546afc2ba1dSToomas Soome struct ficlSystem;
547afc2ba1dSToomas Soome typedef struct ficlSystem ficlSystem;
548afc2ba1dSToomas Soome struct ficlSystemInformation;
549afc2ba1dSToomas Soome typedef struct ficlSystemInformation ficlSystemInformation;
550afc2ba1dSToomas Soome struct ficlCallback;
551afc2ba1dSToomas Soome typedef struct ficlCallback ficlCallback;
552afc2ba1dSToomas Soome struct ficlCountedString;
553afc2ba1dSToomas Soome typedef struct ficlCountedString ficlCountedString;
554afc2ba1dSToomas Soome struct ficlString;
555afc2ba1dSToomas Soome typedef struct ficlString ficlString;
556afc2ba1dSToomas Soome 
557afc2ba1dSToomas Soome 
558afc2ba1dSToomas Soome /*
559afc2ba1dSToomas Soome  * System dependent routines:
560afc2ba1dSToomas Soome  * Edit the implementations in your appropriate ficlplatform/ *.c to be
561afc2ba1dSToomas Soome  * compatible with your runtime environment.
562afc2ba1dSToomas Soome  *
563afc2ba1dSToomas Soome  * ficlCallbackDefaultTextOut sends a zero-terminated string to the
564afc2ba1dSToomas Soome  *	default output device - used for system error messages.
565afc2ba1dSToomas Soome  *
566afc2ba1dSToomas Soome  * ficlMalloc(), ficlRealloc() and ficlFree() have the same semantics
567afc2ba1dSToomas Soome  * as the functions malloc(), realloc(), and free() from the standard C library.
568afc2ba1dSToomas Soome  */
569afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN void ficlCallbackDefaultTextOut(ficlCallback *callback,
570afc2ba1dSToomas Soome     char *text);
571afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN void *ficlMalloc(size_t size);
572afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN void  ficlFree(void *p);
573afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN void *ficlRealloc(void *p, size_t size);
574afc2ba1dSToomas Soome 
575afc2ba1dSToomas Soome /*
576afc2ba1dSToomas Soome  * the Good Stuff starts here...
577afc2ba1dSToomas Soome  */
578afc2ba1dSToomas Soome #define	FICL_VERSION	"4.1.0"
579afc2ba1dSToomas Soome #define	FICL_VERSION_MAJOR	4
580afc2ba1dSToomas Soome #define	FICL_VERSION_MINOR	1
581afc2ba1dSToomas Soome 
582afc2ba1dSToomas Soome #if !defined(FICL_PROMPT)
583afc2ba1dSToomas Soome #define	FICL_PROMPT		"ok> "
584afc2ba1dSToomas Soome #endif
585afc2ba1dSToomas Soome 
586afc2ba1dSToomas Soome /*
587afc2ba1dSToomas Soome  * ANS Forth requires false to be zero, and true to be the ones
588afc2ba1dSToomas Soome  * complement of false... that unifies logical and bitwise operations
589afc2ba1dSToomas Soome  * nicely.
590afc2ba1dSToomas Soome  */
591afc2ba1dSToomas Soome #define	FICL_TRUE	((unsigned long)~(0L))
592afc2ba1dSToomas Soome #define	FICL_FALSE	(0)
593afc2ba1dSToomas Soome #define	FICL_BOOL(x)	((x) ? FICL_TRUE : FICL_FALSE)
594afc2ba1dSToomas Soome 
595afc2ba1dSToomas Soome 
596afc2ba1dSToomas Soome #if !defined FICL_IGNORE	/* Macro to silence unused param warnings */
597afc2ba1dSToomas Soome #define	FICL_IGNORE(x)	(void)x
598afc2ba1dSToomas Soome #endif /*  !defined FICL_IGNORE */
599afc2ba1dSToomas Soome 
600afc2ba1dSToomas Soome #if !defined NULL
601afc2ba1dSToomas Soome #define	NULL	((void *)0)
602afc2ba1dSToomas Soome #endif
603afc2ba1dSToomas Soome 
604afc2ba1dSToomas Soome /*
605afc2ba1dSToomas Soome  * 2integer structures
606afc2ba1dSToomas Soome  */
607afc2ba1dSToomas Soome #if FICL_PLATFORM_HAS_2INTEGER
608afc2ba1dSToomas Soome 
609afc2ba1dSToomas Soome #define	FICL_2INTEGER_SET(high, low, doublei)	\
610afc2ba1dSToomas Soome 	((doublei) = (ficl2Integer)(((ficlUnsigned)(low)) | \
611afc2ba1dSToomas Soome 	(((ficl2Integer)(high)) << FICL_BITS_PER_CELL)))
612afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_SET(high, low, doubleu)	\
613afc2ba1dSToomas Soome 	((doubleu) = ((ficl2Unsigned)(low)) | \
614afc2ba1dSToomas Soome 	(((ficl2Unsigned)(high)) << FICL_BITS_PER_CELL))
615afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_GET_LOW(doubleu)	\
616afc2ba1dSToomas Soome 	((ficlUnsigned)(doubleu & ((((ficl2Integer)1) << \
617afc2ba1dSToomas Soome 	FICL_BITS_PER_CELL) - 1)))
618afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_GET_HIGH(doubleu)	\
619afc2ba1dSToomas Soome 	((ficlUnsigned)(doubleu >> FICL_BITS_PER_CELL))
620afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_NOT_ZERO(doubleu)	((doubleu) != 0)
621afc2ba1dSToomas Soome 
622afc2ba1dSToomas Soome #define	FICL_INTEGER_TO_2INTEGER(i, doublei)	((doublei) = (i))
623afc2ba1dSToomas Soome #define	FICL_UNSIGNED_TO_2UNSIGNED(u, doubleu)	((doubleu) = (u))
624afc2ba1dSToomas Soome 
625afc2ba1dSToomas Soome #define	ficl2IntegerIsNegative(doublei)	((doublei) < 0)
626afc2ba1dSToomas Soome #define	ficl2IntegerNegate(doublei)	(-(doublei))
627afc2ba1dSToomas Soome 
628afc2ba1dSToomas Soome #define	ficl2IntegerMultiply(x, y)	\
629afc2ba1dSToomas Soome 	(((ficl2Integer)(x)) * ((ficl2Integer)(y)))
630afc2ba1dSToomas Soome #define	ficl2IntegerDecrement(x)	(((ficl2Integer)(x)) - 1)
631afc2ba1dSToomas Soome 
632afc2ba1dSToomas Soome #define	ficl2UnsignedAdd(x, y)	(((ficl2Unsigned)(x)) + ((ficl2Unsigned)(y)))
633afc2ba1dSToomas Soome #define	ficl2UnsignedSubtract(x, y)	\
634afc2ba1dSToomas Soome 	(((ficl2Unsigned)(x)) - ((ficl2Unsigned)(y)))
635afc2ba1dSToomas Soome #define	ficl2UnsignedMultiply(x, y)	\
636afc2ba1dSToomas Soome 	(((ficl2Unsigned)(x)) * ((ficl2Unsigned)(y)))
637afc2ba1dSToomas Soome #define	ficl2UnsignedMultiplyAccumulate(u, mul, add)	(((u) * (mul)) + (add))
638afc2ba1dSToomas Soome #define	ficl2UnsignedArithmeticShiftLeft(x)	((x) << 1)
639afc2ba1dSToomas Soome #define	ficl2UnsignedArithmeticShiftRight(x)	((x) >> 1)
640afc2ba1dSToomas Soome #define	ficl2UnsignedCompare(x, y)	ficl2UnsignedSubtract(x, y)
641afc2ba1dSToomas Soome #define	ficl2UnsignedOr(x, y)	((x) | (y))
642afc2ba1dSToomas Soome 
643afc2ba1dSToomas Soome #else /* FICL_PLATFORM_HAS_2INTEGER */
644afc2ba1dSToomas Soome 
645afc2ba1dSToomas Soome typedef struct
646afc2ba1dSToomas Soome {
647afc2ba1dSToomas Soome 	ficlUnsigned high;
648afc2ba1dSToomas Soome 	ficlUnsigned low;
649afc2ba1dSToomas Soome } ficl2Unsigned;
650afc2ba1dSToomas Soome 
651afc2ba1dSToomas Soome typedef struct
652afc2ba1dSToomas Soome {
653afc2ba1dSToomas Soome 	ficlInteger high;
654afc2ba1dSToomas Soome 	ficlInteger low;
655afc2ba1dSToomas Soome } ficl2Integer;
656afc2ba1dSToomas Soome 
657afc2ba1dSToomas Soome 
658afc2ba1dSToomas Soome #define	FICL_2INTEGER_SET(hi, lo, doublei)	\
659afc2ba1dSToomas Soome 	{ ficl2Integer x; x.low = (lo); x.high = (hi); (doublei) = x; }
660afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_SET(hi, lo, doubleu)	\
661afc2ba1dSToomas Soome 	{ ficl2Unsigned x; x.low = (lo); x.high = (hi); (doubleu) = x; }
662afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_GET_LOW(doubleu)	((doubleu).low)
663afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_GET_HIGH(doubleu)	((doubleu).high)
664afc2ba1dSToomas Soome #define	FICL_2UNSIGNED_NOT_ZERO(doubleu) ((doubleu).high || (doubleu).low)
665afc2ba1dSToomas Soome 
666afc2ba1dSToomas Soome #define	FICL_INTEGER_TO_2INTEGER(i, doublei)	\
667afc2ba1dSToomas Soome 	{ ficlInteger __x = (ficlInteger)(i);	\
668afc2ba1dSToomas Soome 	FICL_2INTEGER_SET((__x < 0) ? -1L : 0, __x, doublei) }
669afc2ba1dSToomas Soome #define	FICL_UNSIGNED_TO_2UNSIGNED(u, doubleu)	\
670afc2ba1dSToomas Soome 	FICL_2UNSIGNED_SET(0, u, doubleu)
671afc2ba1dSToomas Soome 
672afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN int ficl2IntegerIsNegative(ficl2Integer x);
673afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerNegate(ficl2Integer x);
674afc2ba1dSToomas Soome 
675afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerMultiply(ficlInteger x,
676afc2ba1dSToomas Soome     ficlInteger y);
677afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Integer ficl2IntegerDecrement(ficl2Integer x);
678afc2ba1dSToomas Soome 
679afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedAdd(ficl2Unsigned x,
680afc2ba1dSToomas Soome     ficl2Unsigned y);
681afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedSubtract(ficl2Unsigned x,
682afc2ba1dSToomas Soome     ficl2Unsigned y);
683afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned ficl2UnsignedMultiply(ficlUnsigned x,
684afc2ba1dSToomas Soome     ficlUnsigned y);
685afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned
686afc2ba1dSToomas Soome     ficl2UnsignedMultiplyAccumulate(ficl2Unsigned u, ficlUnsigned mul,
687afc2ba1dSToomas Soome     ficlUnsigned add);
688afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned
689afc2ba1dSToomas Soome     ficl2UnsignedArithmeticShiftLeft(ficl2Unsigned x);
690afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned
691afc2ba1dSToomas Soome     ficl2UnsignedArithmeticShiftRight(ficl2Unsigned x);
692afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN int ficl2UnsignedCompare(ficl2Unsigned x,
693afc2ba1dSToomas Soome     ficl2Unsigned y);
694afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2Unsigned
695afc2ba1dSToomas Soome     ficl2UnsignedOr(ficl2Unsigned x, ficl2Unsigned y);
696afc2ba1dSToomas Soome 
697afc2ba1dSToomas Soome #endif /* FICL_PLATFORM_HAS_2INTEGER */
698afc2ba1dSToomas Soome 
699afc2ba1dSToomas Soome /*
700afc2ba1dSToomas Soome  * These structures represent the result of division.
701afc2ba1dSToomas Soome  */
702afc2ba1dSToomas Soome typedef struct
703afc2ba1dSToomas Soome {
704afc2ba1dSToomas Soome 	ficl2Unsigned quotient;
705afc2ba1dSToomas Soome 	ficlUnsigned remainder;
706afc2ba1dSToomas Soome } __attribute__((may_alias)) ficl2UnsignedQR;
707afc2ba1dSToomas Soome 
708afc2ba1dSToomas Soome typedef struct
709afc2ba1dSToomas Soome {
710afc2ba1dSToomas Soome 	ficl2Integer quotient;
711afc2ba1dSToomas Soome 	ficlInteger remainder;
712afc2ba1dSToomas Soome } __attribute__((may_alias)) ficl2IntegerQR;
713afc2ba1dSToomas Soome 
714afc2ba1dSToomas Soome 
715afc2ba1dSToomas Soome #define	FICL_2INTEGERQR_TO_2UNSIGNEDQR(doubleiqr)	\
716afc2ba1dSToomas Soome 	(*(ficl2UnsignedQR *)(&(doubleiqr)))
717afc2ba1dSToomas Soome #define	FICL_2UNSIGNEDQR_TO_2INTEGERQR(doubleuqr)	\
718afc2ba1dSToomas Soome 	(*(ficl2IntegerQR *)(&(doubleuqr)))
719afc2ba1dSToomas Soome 
720afc2ba1dSToomas Soome /*
721afc2ba1dSToomas Soome  * 64 bit integer math support routines: multiply two UNS32s
722afc2ba1dSToomas Soome  * to get a 64 bit product, & divide the product by an UNS32
723afc2ba1dSToomas Soome  * to get an UNS32 quotient and remainder. Much easier in asm
724afc2ba1dSToomas Soome  * on a 32 bit CPU than in C, which usually doesn't support
725afc2ba1dSToomas Soome  * the double length result (but it should).
726afc2ba1dSToomas Soome  */
727afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2IntegerQR
728afc2ba1dSToomas Soome     ficl2IntegerDivideFloored(ficl2Integer num, ficlInteger den);
729afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2IntegerQR
730afc2ba1dSToomas Soome     ficl2IntegerDivideSymmetric(ficl2Integer num, ficlInteger den);
731afc2ba1dSToomas Soome 
732afc2ba1dSToomas Soome FICL_PLATFORM_EXTERN ficl2UnsignedQR
733afc2ba1dSToomas Soome     ficl2UnsignedDivide(ficl2Unsigned q, ficlUnsigned y);
734afc2ba1dSToomas Soome 
735afc2ba1dSToomas Soome /*
736afc2ba1dSToomas Soome  * A ficlCell is the main storage type. It must be large enough
737afc2ba1dSToomas Soome  * to contain a pointer or a scalar. In order to accommodate
738afc2ba1dSToomas Soome  * 32 bit and 64 bit processors, use abstract types for int,
739afc2ba1dSToomas Soome  * unsigned, and float.
740afc2ba1dSToomas Soome  *
741afc2ba1dSToomas Soome  * A ficlUnsigned, ficlInteger, and ficlFloat *MUST* be the same
742afc2ba1dSToomas Soome  * size as a "void *" on the target system.  (Sorry, but that's
743afc2ba1dSToomas Soome  * a design constraint of FORTH.)
744afc2ba1dSToomas Soome  */
745afc2ba1dSToomas Soome typedef union ficlCell
746afc2ba1dSToomas Soome {
747afc2ba1dSToomas Soome     ficlInteger i;
748afc2ba1dSToomas Soome     ficlUnsigned u;
749afc2ba1dSToomas Soome #if (FICL_WANT_FLOAT)
750afc2ba1dSToomas Soome     ficlFloat f;
751afc2ba1dSToomas Soome #endif
752afc2ba1dSToomas Soome     void *p;
753afc2ba1dSToomas Soome     void (*fn)(void);
754afc2ba1dSToomas Soome } __attribute__((may_alias)) ficlCell;
755afc2ba1dSToomas Soome 
756afc2ba1dSToomas Soome 
757afc2ba1dSToomas Soome #define	FICL_BITS_PER_CELL	(sizeof (ficlCell) * 8)
758afc2ba1dSToomas Soome 
759afc2ba1dSToomas Soome /*
760afc2ba1dSToomas Soome  * FICL_PLATFORM_ALIGNMENT is the number of bytes to which
761afc2ba1dSToomas Soome  * the dictionary pointer address must be aligned. This value
762afc2ba1dSToomas Soome  * is usually either 2 or 4, depending on the memory architecture
763afc2ba1dSToomas Soome  * of the target system; 4 is safe on any 16 or 32 bit
764afc2ba1dSToomas Soome  * machine.  8 would be appropriate for a 64 bit machine.
765afc2ba1dSToomas Soome  */
766afc2ba1dSToomas Soome #if !defined FICL_PLATFORM_ALIGNMENT
767afc2ba1dSToomas Soome #define	FICL_PLATFORM_ALIGNMENT	(4)
768afc2ba1dSToomas Soome #endif
769afc2ba1dSToomas Soome 
770afc2ba1dSToomas Soome /*
771afc2ba1dSToomas Soome  * PTRtoCELL is a cast through void * intended to satisfy the
772afc2ba1dSToomas Soome  * most outrageously pedantic compiler... (I won't mention
773afc2ba1dSToomas Soome  * its name)
774afc2ba1dSToomas Soome  */
775afc2ba1dSToomas Soome #define	FICL_POINTER_TO_CELL(p)	((ficlCell *)(void *)p)
776afc2ba1dSToomas Soome 
777afc2ba1dSToomas Soome /*
778afc2ba1dSToomas Soome  * FORTH defines the "counted string" data type.  This is
779afc2ba1dSToomas Soome  * a "Pascal-style" string, where the first byte is an unsigned
780afc2ba1dSToomas Soome  * count of characters, followed by the characters themselves.
781afc2ba1dSToomas Soome  * The Ficl structure for this is ficlCountedString.
782afc2ba1dSToomas Soome  * Ficl also often zero-terminates them so that they work with the
783afc2ba1dSToomas Soome  * usual C runtime library string functions... strlen(), strcmp(),
784afc2ba1dSToomas Soome  * and the like.  (Belt & suspenders?  You decide.)
785afc2ba1dSToomas Soome  *
786afc2ba1dSToomas Soome  * The problem is, this limits strings to 255 characters, which
787afc2ba1dSToomas Soome  * can be a bit constricting to us wordy types.  So FORTH only
788afc2ba1dSToomas Soome  * uses counted strings for backwards compatibility, and all new
789afc2ba1dSToomas Soome  * words are "c-addr u" style, where the address and length are
790afc2ba1dSToomas Soome  * stored separately, and the length is a full unsigned "cell" size.
791afc2ba1dSToomas Soome  * (For more on this trend, see DPANS94 section A.3.1.3.4.)
792afc2ba1dSToomas Soome  * Ficl represents this with the ficlString structure.  Note that
793afc2ba1dSToomas Soome  * these are frequently *not* zero-terminated!  Don't depend on
794afc2ba1dSToomas Soome  * it--that way lies madness.
795afc2ba1dSToomas Soome  */
796afc2ba1dSToomas Soome 
797afc2ba1dSToomas Soome struct ficlCountedString
798afc2ba1dSToomas Soome {
799afc2ba1dSToomas Soome     ficlUnsigned8 length;
800afc2ba1dSToomas Soome     char text[1];
801afc2ba1dSToomas Soome };
802afc2ba1dSToomas Soome 
803afc2ba1dSToomas Soome #define	FICL_COUNTED_STRING_GET_LENGTH(cs)	((cs).length)
804afc2ba1dSToomas Soome #define	FICL_COUNTED_STRING_GET_POINTER(cs)	((cs).text)
805afc2ba1dSToomas Soome 
806afc2ba1dSToomas Soome #define	FICL_COUNTED_STRING_MAX	(256)
807afc2ba1dSToomas Soome #define	FICL_POINTER_TO_COUNTED_STRING(p)	((ficlCountedString *)(void *)p)
808afc2ba1dSToomas Soome 
809afc2ba1dSToomas Soome struct ficlString
810afc2ba1dSToomas Soome {
811afc2ba1dSToomas Soome     ficlUnsigned length;
812afc2ba1dSToomas Soome     char *text;
813afc2ba1dSToomas Soome };
814afc2ba1dSToomas Soome 
815afc2ba1dSToomas Soome 
816afc2ba1dSToomas Soome #define	FICL_STRING_GET_LENGTH(fs)	((fs).length)
817afc2ba1dSToomas Soome #define	FICL_STRING_GET_POINTER(fs)	((fs).text)
818afc2ba1dSToomas Soome #define	FICL_STRING_SET_LENGTH(fs, l)	((fs).length = (ficlUnsigned)(l))
819afc2ba1dSToomas Soome #define	FICL_STRING_SET_POINTER(fs, p)	((fs).text = (char *)(p))
820afc2ba1dSToomas Soome #define	FICL_STRING_SET_FROM_COUNTED_STRING(string, countedstring)	\
821afc2ba1dSToomas Soome 	{(string).text = (countedstring).text;	\
822afc2ba1dSToomas Soome 	(string).length = (countedstring).length; }
823afc2ba1dSToomas Soome /*
824afc2ba1dSToomas Soome  * Init a FICL_STRING from a pointer to a zero-terminated string
825afc2ba1dSToomas Soome  */
826afc2ba1dSToomas Soome #define	FICL_STRING_SET_FROM_CSTRING(string, cstring) \
827afc2ba1dSToomas Soome 	{(string).text = (cstring); (string).length = strlen(cstring); }
828afc2ba1dSToomas Soome 
829afc2ba1dSToomas Soome /*
830afc2ba1dSToomas Soome  * Ficl uses this little structure to hold the address of
831afc2ba1dSToomas Soome  * the block of text it's working on and an index to the next
832afc2ba1dSToomas Soome  * unconsumed character in the string. Traditionally, this is
833afc2ba1dSToomas Soome  * done by a Text Input Buffer, so I've called this struct TIB.
834afc2ba1dSToomas Soome  *
835afc2ba1dSToomas Soome  * Since this structure also holds the size of the input buffer,
836afc2ba1dSToomas Soome  * and since evaluate requires that, let's put the size here.
837afc2ba1dSToomas Soome  * The size is stored as an end-pointer because that is what the
838afc2ba1dSToomas Soome  * null-terminated string aware functions find most easy to deal
839afc2ba1dSToomas Soome  * with.
840afc2ba1dSToomas Soome  * Notice, though, that nobody really uses this except evaluate,
841afc2ba1dSToomas Soome  * so it might just be moved to ficlVm instead. (sobral)
842afc2ba1dSToomas Soome  */
843afc2ba1dSToomas Soome typedef struct
844afc2ba1dSToomas Soome {
845afc2ba1dSToomas Soome     ficlInteger index;
846afc2ba1dSToomas Soome     char *end;
847afc2ba1dSToomas Soome     char *text;
848afc2ba1dSToomas Soome } ficlTIB;
849afc2ba1dSToomas Soome 
850afc2ba1dSToomas Soome /*
851afc2ba1dSToomas Soome  * Stacks get heavy use in Ficl and Forth...
852afc2ba1dSToomas Soome  * Each virtual machine implements two of them:
853afc2ba1dSToomas Soome  * one holds parameters (data), and the other holds return
854afc2ba1dSToomas Soome  * addresses and control flow information for the virtual
855afc2ba1dSToomas Soome  * machine. (Note: C's automatic stack is implicitly used,
856afc2ba1dSToomas Soome  * but not modeled because it doesn't need to be...)
857afc2ba1dSToomas Soome  * Here's an abstract type for a stack
858