Imported Upstream version 21
[debian/pforth] / csrc / pf_guts.h
1 /* @(#) pf_guts.h 98/01/28 1.4 */
2 #ifndef _pf_guts_h
3 #define _pf_guts_h
4
5 /***************************************************************
6 ** Include file for PForth, a Forth based on 'C'
7 **
8 ** Author: Phil Burk
9 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, Devid Rosenboom
10 **
11 ** The pForth software code is dedicated to the public domain,
12 ** and any third party may reproduce, distribute and modify
13 ** the pForth software code or any derivative works thereof
14 ** without any compensation or license.  The pForth software
15 ** code is provided on an "as is" basis without any warranty
16 ** of any kind, including, without limitation, the implied
17 ** warranties of merchantability and fitness for a particular
18 ** purpose and their equivalents under the laws of any jurisdiction.
19 **
20 ***************************************************************/
21
22 /*
23 ** PFORTH_VERSION changes when PForth is modified and released.
24 ** See README file for version info.
25 */
26 #define PFORTH_VERSION "21"
27
28 /*
29 ** PFORTH_FILE_VERSION changes when incompatible changes are made
30 ** in the ".dic" file format.
31 **
32 ** FV3 - 950225 - Use ABS_TO_CODEREL for CodePtr. See file "pf_save.c".
33 ** FV4 - 950309 - Added NameSize and CodeSize to pfSaveForth().
34 ** FV5 - 950316 - Added Floats and reserved words.
35 ** FV6 - 961213 - Added ID_LOCAL_PLUSSTORE, ID_COLON_P, etc.
36 ** FV7 - 971203 - Added ID_FILL, (1LOCAL@),  etc., ran out of reserved, resorted.\r
37 ** FV8 - 980818 - Added Endian flag.
38 */
39 #define PF_FILE_VERSION (8)   /* Bump this whenever primitives added. */
40 #define PF_EARLIEST_FILE_VERSION (8)  /* earliest one still compatible */
41
42 /***************************************************************
43 ** Sizes and other constants
44 ***************************************************************/
45
46 #define TIB_SIZE (256)
47
48 #ifndef FALSE
49         #define FALSE (0)
50 #endif
51 #ifndef TRUE
52         #define TRUE (1)
53 #endif
54
55 #define FFALSE (0)
56 #define FTRUE (-1)
57 #define BLANK (' ')
58
59 #define FLAG_PRECEDENCE (0x80)
60 #define FLAG_IMMEDIATE  (0x40)
61 #define FLAG_SMUDGE     (0x20)
62 #define MASK_NAME_SIZE  (0x1F)
63
64 /* Debug TRACE flags */
65 #define TRACE_INNER     (0x0002)
66 #define TRACE_COMPILE   (0x0004)
67 #define TRACE_SPECIAL   (0x0008)
68
69 /* Numeric types returned by NUMBER? */
70 #define NUM_TYPE_BAD    (0)
71 #define NUM_TYPE_SINGLE (1)
72 #define NUM_TYPE_DOUBLE (2)
73 #define NUM_TYPE_FLOAT  (3)
74
75 #define CREATE_BODY_OFFSET  (3*sizeof(cell))
76
77 /***************************************************************
78 ** Primitive Token IDS
79 ** Do NOT change the order of these IDs or dictionary files will break!
80 ***************************************************************/
81 enum cforth_primitive_ids
82 {
83         ID_EXIT = 0,  /* ID_EXIT must always be zero. */
84 /* Do NOT change the order of these IDs or dictionary files will break! */
85         ID_1MINUS,
86         ID_1PLUS,
87         ID_2DUP,
88         ID_2LITERAL,
89         ID_2LITERAL_P,
90         ID_2MINUS,
91         ID_2OVER,
92         ID_2PLUS,
93         ID_2SWAP,
94         ID_2_R_FETCH,
95         ID_2_R_FROM,
96         ID_2_TO_R,
97         ID_ACCEPT,
98         ID_ALITERAL,
99         ID_ALITERAL_P,
100         ID_ALLOCATE,
101         ID_AND,
102         ID_ARSHIFT,
103         ID_BAIL,
104         ID_BODY_OFFSET,
105         ID_BRANCH,
106         ID_BYE,
107         ID_CALL_C,
108         ID_CFETCH,
109         ID_CMOVE,
110         ID_CMOVE_UP,
111         ID_COLON,
112         ID_COLON_P,
113         ID_COMPARE,
114         ID_COMP_EQUAL,
115         ID_COMP_GREATERTHAN,
116         ID_COMP_LESSTHAN,
117         ID_COMP_NOT_EQUAL,
118         ID_COMP_U_GREATERTHAN,
119         ID_COMP_U_LESSTHAN,
120         ID_COMP_ZERO_EQUAL,
121         ID_COMP_ZERO_GREATERTHAN,
122         ID_COMP_ZERO_LESSTHAN,
123         ID_COMP_ZERO_NOT_EQUAL,
124         ID_CR,
125         ID_CREATE,
126         ID_CREATE_P,
127         ID_CSTORE,
128         ID_DEFER,
129         ID_DEFER_P,
130         ID_DEPTH,
131         ID_DIVIDE,
132         ID_DOT,
133         ID_DOTS,
134         ID_DO_P,
135         ID_DROP,
136         ID_DUMP,
137         ID_DUP,
138         ID_D_MINUS,
139         ID_D_MTIMES,
140         ID_D_MUSMOD,
141         ID_D_PLUS,
142         ID_D_UMSMOD,
143         ID_D_UMTIMES,
144         ID_EMIT,
145         ID_EMIT_P,
146         ID_EOL,
147         ID_ERRORQ_P,
148         ID_EXECUTE,
149         ID_FETCH,
150         ID_FILE_CLOSE,
151         ID_FILE_CREATE,
152         ID_FILE_OPEN,
153         ID_FILE_POSITION,
154         ID_FILE_READ,
155         ID_FILE_REPOSITION,
156         ID_FILE_RO,
157         ID_FILE_RW,
158         ID_FILE_SIZE,
159         ID_FILE_WRITE,
160         ID_FILL,
161         ID_FIND,
162         ID_FINDNFA,
163         ID_FLUSHEMIT,
164         ID_FREE,
165         ID_HERE,
166         ID_NUMBERQ_P,
167         ID_I,
168         ID_INCLUDE_FILE,
169         ID_J,
170         ID_KEY,
171         ID_LEAVE_P,
172         ID_LITERAL,
173         ID_LITERAL_P,
174         ID_LOADSYS,
175         ID_LOCAL_COMPILER,
176         ID_LOCAL_ENTRY,
177         ID_LOCAL_EXIT,
178         ID_LOCAL_FETCH,
179         ID_LOCAL_FETCH_1,
180         ID_LOCAL_FETCH_2,
181         ID_LOCAL_FETCH_3,
182         ID_LOCAL_FETCH_4,
183         ID_LOCAL_FETCH_5,
184         ID_LOCAL_FETCH_6,
185         ID_LOCAL_FETCH_7,
186         ID_LOCAL_FETCH_8,
187         ID_LOCAL_PLUSSTORE,
188         ID_LOCAL_STORE,
189         ID_LOCAL_STORE_1,
190         ID_LOCAL_STORE_2,
191         ID_LOCAL_STORE_3,
192         ID_LOCAL_STORE_4,
193         ID_LOCAL_STORE_5,
194         ID_LOCAL_STORE_6,
195         ID_LOCAL_STORE_7,
196         ID_LOCAL_STORE_8,
197         ID_LOOP_P,
198         ID_LSHIFT,
199         ID_MAX,
200         ID_MIN,
201         ID_MINUS,
202         ID_NAME_TO_PREVIOUS,
203         ID_NAME_TO_TOKEN,
204         ID_NOOP,
205         ID_NUMBERQ,
206         ID_OR,
207         ID_OVER,
208         ID_PICK,
209         ID_PLUS,
210         ID_PLUSLOOP_P,
211         ID_PLUS_STORE,
212         ID_QDO_P,
213         ID_QDUP,
214         ID_QTERMINAL,
215         ID_QUIT_P,
216         ID_REFILL,
217         ID_RESIZE,
218         ID_RESTORE_INPUT,
219         ID_ROLL,
220         ID_ROT,
221         ID_RP_FETCH,
222         ID_RP_STORE,
223         ID_RSHIFT,
224         ID_R_DROP,
225         ID_R_FETCH,
226         ID_R_FROM,
227         ID_SAVE_FORTH_P,
228         ID_SAVE_INPUT,
229         ID_SCAN,
230         ID_SEMICOLON,
231         ID_SKIP,
232         ID_SOURCE,
233         ID_SOURCE_ID,
234         ID_SOURCE_ID_POP,
235         ID_SOURCE_ID_PUSH,
236         ID_SOURCE_SET,
237         ID_SP_FETCH,
238         ID_SP_STORE,
239         ID_STORE,
240         ID_SWAP,
241         ID_TEST1,
242         ID_TEST2,
243         ID_TEST3,
244         ID_TICK,
245         ID_TIMES,
246         ID_TO_R,
247         ID_TYPE,
248         ID_TYPE_P,
249         ID_VAR_BASE,
250         ID_VAR_CODE_BASE,
251         ID_VAR_CODE_LIMIT,
252         ID_VAR_CONTEXT,
253         ID_VAR_DP,
254         ID_VAR_ECHO,
255         ID_VAR_HEADERS_BASE,
256         ID_VAR_HEADERS_LIMIT,
257         ID_VAR_HEADERS_PTR,
258         ID_VAR_NUM_TIB,
259         ID_VAR_OUT,
260         ID_VAR_RETURN_CODE,
261         ID_VAR_SOURCE_ID,
262         ID_VAR_STATE,
263         ID_VAR_TO_IN,
264         ID_VAR_TRACE_FLAGS,
265         ID_VAR_TRACE_LEVEL,
266         ID_VAR_TRACE_STACK,
267         ID_VLIST,
268         ID_WORD,
269         ID_WORD_FETCH,
270         ID_WORD_STORE,
271         ID_XOR,
272         ID_ZERO_BRANCH,
273 /* If you add a word here, take away one reserved word below. */
274 #ifdef PF_SUPPORT_FP
275 /* Only reserve space if we are adding FP so that we can detect
276 ** unsupported primitives when loading dictionary.
277 */
278         ID_RESERVED01,
279         ID_RESERVED02,
280         ID_RESERVED03,
281         ID_RESERVED04,
282         ID_RESERVED05,
283         ID_RESERVED06,
284         ID_RESERVED07,
285         ID_RESERVED08,
286         ID_RESERVED09,
287         ID_RESERVED10,
288         ID_RESERVED11,
289         ID_RESERVED12,
290         ID_RESERVED13,
291         ID_RESERVED14,
292         ID_RESERVED15,
293         ID_RESERVED16,
294         ID_RESERVED17,
295         ID_RESERVED18,
296         ID_RESERVED19,
297         ID_RESERVED20,
298         ID_FP_D_TO_F,
299         ID_FP_FSTORE,
300         ID_FP_FTIMES,
301         ID_FP_FPLUS,
302         ID_FP_FMINUS,
303         ID_FP_FSLASH,
304         ID_FP_F_ZERO_LESS_THAN,
305         ID_FP_F_ZERO_EQUALS,
306         ID_FP_F_LESS_THAN,
307         ID_FP_F_TO_D,
308         ID_FP_FFETCH,
309         ID_FP_FDEPTH,
310         ID_FP_FDROP,
311         ID_FP_FDUP,
312         ID_FP_FLITERAL,
313         ID_FP_FLITERAL_P,
314         ID_FP_FLOAT_PLUS,
315         ID_FP_FLOATS,
316         ID_FP_FLOOR,
317         ID_FP_FMAX,
318         ID_FP_FMIN,
319         ID_FP_FNEGATE,
320         ID_FP_FOVER,
321         ID_FP_FROT,
322         ID_FP_FROUND,
323         ID_FP_FSWAP,
324         ID_FP_FSTAR_STAR,
325         ID_FP_FABS,
326         ID_FP_FACOS,
327         ID_FP_FACOSH,
328         ID_FP_FALOG,
329         ID_FP_FASIN,
330         ID_FP_FASINH,
331         ID_FP_FATAN,
332         ID_FP_FATAN2,
333         ID_FP_FATANH,
334         ID_FP_FCOS,
335         ID_FP_FCOSH,
336         ID_FP_FLN,
337         ID_FP_FLNP1,
338         ID_FP_FLOG,
339         ID_FP_FSIN,
340         ID_FP_FSINCOS,
341         ID_FP_FSINH,
342         ID_FP_FSQRT,
343         ID_FP_FTAN,
344         ID_FP_FTANH,
345         ID_FP_FPICK,
346 #endif
347 /* Add new IDs by replacing reserved IDs or extending FP routines. */
348 /* Do NOT change the order of these IDs or dictionary files will break! */
349         NUM_PRIMITIVES     /* This must always be LAST */
350 };
351
352
353 /***************************************************************
354 ** Structures
355 ***************************************************************/
356 #define CFTD_FLAG_GO    (0x0001)
357 /* This flag is true when ABORTing to cause the 'C' code to unravel. */
358 #define CFTD_FLAG_ABORT (0x0002)
359
360 typedef struct cfTaskData
361 {
362         cell   *td_StackPtr;       /* Primary data stack */
363         cell   *td_StackBase;
364         cell   *td_StackLimit;
365         cell   *td_ReturnPtr;      /* Return stack */
366         cell   *td_ReturnBase;
367         cell   *td_ReturnLimit;
368 #ifdef PF_SUPPORT_FP
369         PF_FLOAT  *td_FloatStackPtr;
370         PF_FLOAT  *td_FloatStackBase;
371         PF_FLOAT  *td_FloatStackLimit;
372 #endif
373         cell   *td_InsPtr;          /* Instruction pointer, "PC" */
374         cell    td_Flags;
375         FileStream   *td_InputStream;
376 /* Terminal. */
377         char    td_TIB[TIB_SIZE];   /* Buffer for terminal input. */
378         cell    td_IN;              /* Index into Source */
379         cell    td_SourceNum;       /* #TIB after REFILL */
380         char   *td_SourcePtr;       /* Pointer to TIB or other source. */
381         int32   td_LineNumber;      /* Incremented on every refill. */
382         cell    td_OUT;             /* Current output column. */
383 } cfTaskData;
384
385 typedef struct pfNode
386 {
387         struct pfNode *n_Next;
388         struct pfNode *n_Prev;
389 } pfNode;
390
391 /* Structure of header entry in dictionary. These will be stored in dictionary specific endian format*/
392 typedef struct cfNameLinks
393 {
394         cell       cfnl_PreviousName;   /* name relative address of previous */
395         ExecToken  cfnl_ExecToken;      /* Execution token for word. */
396 /* Followed by variable length name field. */
397 } cfNameLinks;
398
399 #define PF_DICF_ALLOCATED_SEGMENTS  ( 0x0001)
400 typedef struct cfDictionary
401 {
402         pfNode  dic_Node;
403         uint32  dic_Flags;
404 /* Headers contain pointers to names and dictionary. */\r
405         uint8   *dic_HeaderBaseUnaligned;\r
406         uint8   *dic_HeaderBase;
407         union
408         {
409                 cell    *Cell;
410                 uint8   *Byte;
411         } dic_HeaderPtr;
412         uint8   *dic_HeaderLimit;
413 /* Code segment contains tokenized code and data. */\r
414         uint8   *dic_CodeBaseUnaligned;\r
415         uint8   *dic_CodeBase;
416         union
417         {
418                 cell    *Cell;
419                 uint8   *Byte;
420         } dic_CodePtr;
421         uint8   *dic_CodeLimit;
422 } cfDictionary;
423
424 /* Save state of include when nesting files. */
425 typedef struct IncludeFrame
426 {
427         FileStream   *inf_FileID;
428         int32         inf_LineNumber;
429         int32         inf_SourceNum;
430         int32         inf_IN;
431         char          inf_SaveTIB[TIB_SIZE];
432 } IncludeFrame;
433
434 #define MAX_INCLUDE_DEPTH (8)
435
436 /***************************************************************
437 ** Prototypes
438 ***************************************************************/
439
440 #ifdef __cplusplus
441 extern "C" {
442 #endif
443
444 void pfExecuteToken( ExecToken XT );
445
446 #ifdef __cplusplus
447 }
448 #endif
449
450 /***************************************************************
451 ** External Globals
452 ***************************************************************/
453 extern cfTaskData   *gCurrentTask;
454 extern cfDictionary *gCurrentDictionary;
455 extern char          gScratch[TIB_SIZE];
456 extern int32         gNumPrimitives;
457
458 extern ExecToken     gLocalCompiler_XT;      /* CFA of (LOCAL) compiler. */
459
460 #define DEPTH_AT_COLON_INVALID (-100)
461 extern int32         gDepthAtColon;
462
463 /* Global variables. */
464 extern char *gVarContext;    /* Points to last name field. */
465 extern cell  gVarState;      /* 1 if compiling. */
466 extern cell  gVarBase;       /* Numeric Base. */
467 extern cell  gVarEcho;       /* Echo input from file. */
468 extern cell  gVarEchoAccept; /* Echo input from ACCEPT. */
469 extern cell  gVarTraceLevel;
470 extern cell  gVarTraceStack;
471 extern cell  gVarTraceFlags;
472 extern cell  gVarQuiet;      /* Suppress unnecessary messages, OK, etc. */
473 extern cell  gVarReturnCode; /* Returned to caller of Forth, eg. UNIX shell. */
474
475 /***************************************************************
476 ** Macros
477 ***************************************************************/
478 \r
479 /* Endian specific macros for creating target dictionaries for machines with\r
480 ** different endian-ness.\r
481 */\r
482 #if defined(PF_BIG_ENDIAN_DIC)\r
483 #define WRITE_FLOAT_DIC             WriteFloatBigEndian\r
484 #define WRITE_LONG_DIC(addr,data)   WriteLongBigEndian((uint32 *)(addr),(uint32)(data))\r
485 #define WRITE_SHORT_DIC(addr,data)  WriteShortBigEndian((uint16 *)(addr),(uint16)(data))\r
486 #define READ_FLOAT_DIC              ReadFloatBigEndian\r
487 #define READ_LONG_DIC(addr)         ReadLongBigEndian((uint32 *)(addr))\r
488 #define READ_SHORT_DIC(addr)        ReadShortBigEndian((uint16 *)(addr))\r
489 #elif defined(PF_LITTLE_ENDIAN_DIC)\r
490 #define WRITE_FLOAT_DIC             WriteFloatLittleEndian\r
491 #define WRITE_LONG_DIC(addr,data)   WriteLongLittleEndian((uint32 *)(addr),(uint32)(data))\r
492 #define WRITE_SHORT_DIC(addr,data)  WriteShortLittleEndian((uint16 *)(addr),(uint16)(data))\r
493 #define READ_FLOAT_DIC              ReadFloatLittleEndian\r
494 #define READ_LONG_DIC(addr)         ReadLongLittleEndian((uint32 *)(addr))\r
495 #define READ_SHORT_DIC(addr)        ReadShortLittleEndian((uint16 *)(addr))\r
496 #else\r
497 #define WRITE_FLOAT_DIC(addr,data)  { *((PF_FLOAT *)(addr)) = (PF_FLOAT)(data); }\r
498 #define WRITE_LONG_DIC(addr,data)   { *((int32 *)(addr)) = (int32)(data); }\r
499 #define WRITE_SHORT_DIC(addr,data)  { *((int16 *)(addr)) = (int16)(data); }\r
500 #define READ_FLOAT_DIC(addr)        ( *((PF_FLOAT *)(addr)) )\r
501 #define READ_LONG_DIC(addr)         ( *((int32 *)(addr)) )\r
502 #define READ_SHORT_DIC(addr)        ( *((int16 *)(addr)) )\r
503 #endif\r
504
505 #define HEADER_HERE (gCurrentDictionary->dic_HeaderPtr.Cell)
506 #define CODE_HERE (gCurrentDictionary->dic_CodePtr.Cell)
507 #define CODE_COMMA( N ) WRITE_LONG_DIC(CODE_HERE++,(N))
508 #define NAME_BASE (gCurrentDictionary->dic_HeaderBase)
509 #define CODE_BASE (gCurrentDictionary->dic_CodeBase)
510 #define NAME_SIZE (gCurrentDictionary->dic_HeaderLimit - gCurrentDictionary->dic_HeaderBase)
511 #define CODE_SIZE (gCurrentDictionary->dic_CodeLimit - gCurrentDictionary->dic_CodeBase)\r
512 \r
513 #define IN_CODE_DIC(addr) ( ( ((uint8 *)(addr)) >= gCurrentDictionary->dic_CodeBase)   && ( ((uint8 *)(addr)) < gCurrentDictionary->dic_CodeLimit) )\r
514 #define IN_NAME_DIC(addr) ( ( ((uint8 *)(addr)) >= gCurrentDictionary->dic_HeaderBase) && ( ((uint8 *)(addr)) < gCurrentDictionary->dic_HeaderLimit) )
515 #define IN_DICS(addr) (IN_CODE_DIC(addr) || IN_NAME_DIC(addr))\r
516 \r
517 /* Address conversion */
518 #define ABS_TO_NAMEREL( a ) ((int32)  (((uint8 *) a) - NAME_BASE ))
519 #define ABS_TO_CODEREL( a ) ((int32)  (((uint8 *) a) - CODE_BASE ))
520 #define NAMEREL_TO_ABS( a ) ((char *) (((int32) a) + NAME_BASE))
521 #define CODEREL_TO_ABS( a ) ((cell *) (((int32) a) + CODE_BASE))
522
523 /* The check for >0 is only needed for CLONE testing. !!! */
524 #define IsTokenPrimitive(xt) ((xt<gNumPrimitives) && (xt>=0))
525
526 #define SET_ABORT { gCurrentTask->td_Flags |= CFTD_FLAG_ABORT; }
527 #define CLEAR_ABORT { gCurrentTask->td_Flags &= ~CFTD_FLAG_ABORT; }
528 #define CHECK_ABORT (gCurrentTask->td_Flags & CFTD_FLAG_ABORT)
529
530 #define FREE_VAR(v) { if (v) { pfFreeMem(v); v = NULL; } }
531
532 #define DATA_STACK_DEPTH (gCurrentTask->td_StackBase - gCurrentTask->td_StackPtr)
533 #define DROP_DATA_STACK (gCurrentTask->td_StackPtr++)
534 #define POP_DATA_STACK (*gCurrentTask->td_StackPtr++)
535 #define PUSH_DATA_STACK(x) {*(--(gCurrentTask->td_StackPtr)) = (cell) x; }
536
537 /* Force Quad alignment. */
538 #define QUADUP(x) (((x)+3)&~3)
539
540 #define MIN(a,b)  ( ((a)<(b)) ? (a) : (b) )
541 #define MAX(a,b)  ( ((a)>(b)) ? (a) : (b) )
542
543
544 #ifndef TOUCH
545         #define TOUCH(argument) ((void)argument)
546 #endif
547
548 /***************************************************************
549 ** I/O related macros
550 ***************************************************************/
551
552 #define EMIT(c)  ioEmit(c)
553 #define EMIT_CR  EMIT('\n');
554
555 #define DBUG(x) /* PRT(x) */
556 #define DBUGX(x) /* DBUG(x) */
557
558 #define MSG(cs)   pfMessage(cs)
559 #define ERR(x)    MSG(x)
560
561 #define MSG_NUM_D(msg,num) { MSG(msg); ffDot((int32) num); EMIT_CR; }
562 #define MSG_NUM_H(msg,num) { MSG(msg); ffDotHex((int32) num); EMIT_CR; }
563
564 #endif  /* _pf_guts_h */
565