1 /* @(#) pf_guts.h 98/01/28 1.4 */
5 /***************************************************************
6 ** Include file for PForth, a Forth based on 'C'
9 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
11 ** Permission to use, copy, modify, and/or distribute this
12 ** software for any purpose with or without fee is hereby granted.
14 ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
15 ** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
16 ** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
17 ** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
18 ** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
19 ** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 ** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ***************************************************************/
26 ** PFORTH_VERSION changes when PForth is modified and released.
27 ** See README file for version info.
29 #define PFORTH_VERSION_CODE 29
30 #define PFORTH_VERSION_NAME "2.0.0"
33 ** PFORTH_FILE_VERSION changes when incompatible changes are made
34 ** in the ".dic" file format.
36 ** FV3 - 950225 - Use ABS_TO_CODEREL for CodePtr. See file "pf_save.c".
37 ** FV4 - 950309 - Added NameSize and CodeSize to pfSaveForth().
38 ** FV5 - 950316 - Added Floats and reserved words.
39 ** FV6 - 961213 - Added ID_LOCAL_PLUSSTORE, ID_COLON_P, etc.
40 ** FV7 - 971203 - Added ID_FILL, (1LOCAL@), etc., ran out of reserved, resorted.
41 ** FV8 - 980818 - Added Endian flag.
42 ** FV9 - 20100503 - Added support for 64-bit CELL.
43 ** FV10 - 20170103 - Added ID_FILE_FLUSH ID_FILE_RENAME ID_FILE_RESIZE
45 #define PF_FILE_VERSION (10) /* Bump this whenever primitives added. */
46 #define PF_EARLIEST_FILE_VERSION (9) /* earliest one still compatible */
48 /***************************************************************
49 ** Sizes and other constants
50 ***************************************************************/
52 #define TIB_SIZE (256)
65 #define FLAG_PRECEDENCE (0x80)
66 #define FLAG_IMMEDIATE (0x40)
67 #define FLAG_SMUDGE (0x20)
68 #define MASK_NAME_SIZE (0x1F)
70 /* Debug TRACE flags */
71 #define TRACE_INNER (0x0002)
72 #define TRACE_COMPILE (0x0004)
73 #define TRACE_SPECIAL (0x0008)
75 /* Numeric types returned by NUMBER? */
76 #define NUM_TYPE_BAD (0)
77 #define NUM_TYPE_SINGLE (1)
78 #define NUM_TYPE_DOUBLE (2)
79 #define NUM_TYPE_FLOAT (3)
81 #define CREATE_BODY_OFFSET (3*sizeof(cell_t))
83 /***************************************************************
84 ** Primitive Token IDS
85 ** Do NOT change the order of these IDs or dictionary files will break!
86 ***************************************************************/
87 enum cforth_primitive_ids
89 ID_EXIT = 0, /* ID_EXIT must always be zero. */
90 /* Do NOT change the order of these IDs or dictionary files will break! */
124 ID_COMP_U_GREATERTHAN,
127 ID_COMP_ZERO_GREATERTHAN,
128 ID_COMP_ZERO_LESSTHAN,
129 ID_COMP_ZERO_NOT_EQUAL,
224 ID_SOURCE_LINE_NUMBER_FETCH, /* used to be ID_RESTORE_INPUT */
234 ID_SOURCE_LINE_NUMBER_STORE, /* used to be ID_SAVE_INPUT */
262 ID_VAR_HEADERS_LIMIT,
284 /* Added to support 64 bit operation. */
289 ID_FILE_FLUSH, /* FLUSH-FILE */
290 ID_FILE_RENAME, /* (RENAME-FILE) */
291 ID_FILE_RESIZE, /* RESIZE-FILE */
292 ID_SLEEP_P, /* (SLEEP) V2.0.0 */
293 ID_VAR_BYE_CODE, /* BYE-CODE */
295 /* If you add a word here, take away one reserved word below. */
297 /* Only reserve space if we are adding FP so that we can detect
298 ** unsupported primitives when loading dictionary.
313 ID_FP_F_ZERO_LESS_THAN,
356 /* Add new IDs by replacing reserved IDs or extending FP routines. */
357 /* Do NOT change the order of these IDs or dictionary files will break! */
358 NUM_PRIMITIVES /* This must always be LAST */
363 /***************************************************************
365 ***************************************************************/
366 /* ANSI standard definitions needed by pForth */
367 #define THROW_ABORT (-1)
368 #define THROW_ABORT_QUOTE (-2)
369 #define THROW_STACK_OVERFLOW (-3)
370 #define THROW_STACK_UNDERFLOW (-4)
371 #define THROW_UNDEFINED_WORD (-13)
372 #define THROW_EXECUTING (-14)
373 #define THROW_PAIRS (-22)
374 #define THROW_FLOAT_STACK_UNDERFLOW ( -45)
375 #define THROW_QUIT (-56)
376 #define THROW_FLUSH_FILE (-68)
377 #define THROW_RESIZE_FILE (-74)
379 /* THROW codes unique to pForth */
380 #define THROW_BYE (-256) /* Exit program. */
381 #define THROW_SEMICOLON (-257) /* Error detected at ; */
382 #define THROW_DEFERRED (-258) /* Not a deferred word. Used in system.fth */
384 /***************************************************************
386 ***************************************************************/
388 typedef struct pfTaskData_s
390 cell_t *td_StackPtr; /* Primary data stack */
391 cell_t *td_StackBase;
392 cell_t *td_StackLimit;
393 cell_t *td_ReturnPtr; /* Return stack */
394 cell_t *td_ReturnBase;
395 cell_t *td_ReturnLimit;
397 PF_FLOAT *td_FloatStackPtr;
398 PF_FLOAT *td_FloatStackBase;
399 PF_FLOAT *td_FloatStackLimit;
401 cell_t *td_InsPtr; /* Instruction pointer, "PC" */
402 FileStream *td_InputStream;
404 char td_TIB[TIB_SIZE]; /* Buffer for terminal input. */
405 cell_t td_IN; /* Index into Source */
406 cell_t td_SourceNum; /* #TIB after REFILL */
407 char *td_SourcePtr; /* Pointer to TIB or other source. */
408 cell_t td_LineNumber; /* Incremented on every refill. */
409 cell_t td_OUT; /* Current output column. */
412 typedef struct pfNode
414 struct pfNode *n_Next;
415 struct pfNode *n_Prev;
418 /* Structure of header entry in dictionary. These will be stored in dictionary specific endian format*/
419 typedef struct cfNameLinks
421 cell_t cfnl_PreviousName; /* name relative address of previous */
422 ExecToken cfnl_ExecToken; /* Execution token for word. */
423 /* Followed by variable length name field. */
426 #define PF_DICF_ALLOCATED_SEGMENTS ( 0x0001)
427 typedef struct pfDictionary_s
431 /* Headers contain pointers to names and dictionary. */
433 ucell_t dic_HeaderBaseUnaligned;
435 ucell_t dic_HeaderBase;
436 ucell_t dic_HeaderPtr;
437 ucell_t dic_HeaderLimit;
438 /* Code segment contains tokenized code and data. */
439 ucell_t dic_CodeBaseUnaligned;
440 ucell_t dic_CodeBase;
446 ucell_t dic_CodeLimit;
449 /* Save state of include when nesting files. */
450 typedef struct IncludeFrame
452 FileStream *inf_FileID;
453 cell_t inf_LineNumber;
454 cell_t inf_SourceNum;
456 char inf_SaveTIB[TIB_SIZE];
459 #define MAX_INCLUDE_DEPTH (16)
461 /***************************************************************
463 ***************************************************************/
469 ThrowCode pfCatch( ExecToken XT );
475 /***************************************************************
477 ***************************************************************/
478 extern pfTaskData_t *gCurrentTask;
479 extern pfDictionary_t *gCurrentDictionary;
480 extern char gScratch[TIB_SIZE];
481 extern cell_t gNumPrimitives;
483 extern ExecToken gLocalCompiler_XT; /* CFA of (LOCAL) compiler. */
484 extern ExecToken gNumberQ_XT; /* XT of NUMBER? */
485 extern ExecToken gQuitP_XT; /* XT of (QUIT) */
486 extern ExecToken gAcceptP_XT; /* XT of ACCEPT */
488 #define DEPTH_AT_COLON_INVALID (-100)
489 extern cell_t gDepthAtColon;
491 /* Global variables. */
492 extern cell_t gVarContext; /* Points to last name field. */
493 extern cell_t gVarState; /* 1 if compiling. */
494 extern cell_t gVarBase; /* Numeric Base. */
495 extern cell_t gVarByeCode; /* BYE-CODE returned on exit */
496 extern cell_t gVarEcho; /* Echo input from file. */
497 extern cell_t gVarEchoAccept; /* Echo input from ACCEPT. */
498 extern cell_t gVarTraceLevel;
499 extern cell_t gVarTraceStack;
500 extern cell_t gVarTraceFlags;
501 extern cell_t gVarQuiet; /* Suppress unnecessary messages, OK, etc. */
502 extern cell_t gVarReturnCode; /* Returned to caller of Forth, eg. UNIX shell. */
504 extern IncludeFrame gIncludeStack[MAX_INCLUDE_DEPTH];
505 extern cell_t gIncludeIndex;
506 /***************************************************************
508 ***************************************************************/
511 /* Endian specific macros for creating target dictionaries for machines with
513 ** different endian-ness.
517 #if defined(PF_BIG_ENDIAN_DIC)
519 #define WRITE_FLOAT_DIC WriteFloatBigEndian
520 #define WRITE_CELL_DIC(addr,data) WriteCellBigEndian((uint8_t *)(addr),(ucell_t)(data))
521 #define WRITE_SHORT_DIC(addr,data) Write16BigEndian((uint8_t *)(addr),(uint16_t)(data))
522 #define READ_FLOAT_DIC ReadFloatBigEndian
523 #define READ_CELL_DIC(addr) ReadCellBigEndian((const uint8_t *)(addr))
524 #define READ_SHORT_DIC(addr) Read16BigEndian((const uint8_t *)(addr))
526 #elif defined(PF_LITTLE_ENDIAN_DIC)
528 #define WRITE_FLOAT_DIC WriteFloatLittleEndian
529 #define WRITE_CELL_DIC(addr,data) WriteCellLittleEndian((uint8_t *)(addr),(ucell_t)(data))
530 #define WRITE_SHORT_DIC(addr,data) Write16LittleEndian((uint8_t *)(addr),(uint16_t)(data))
531 #define READ_FLOAT_DIC ReadFloatLittleEndian
532 #define READ_CELL_DIC(addr) ReadCellLittleEndian((const uint8_t *)(addr))
533 #define READ_SHORT_DIC(addr) Read16LittleEndian((const uint8_t *)(addr))
537 #define WRITE_FLOAT_DIC(addr,data) { *((PF_FLOAT *)(addr)) = (PF_FLOAT)(data); }
538 #define WRITE_CELL_DIC(addr,data) { *((cell_t *)(addr)) = (cell_t)(data); }
539 #define WRITE_SHORT_DIC(addr,data) { *((int16_t *)(addr)) = (int16_t)(data); }
540 #define READ_FLOAT_DIC(addr) ( *((PF_FLOAT *)(addr)) )
541 #define READ_CELL_DIC(addr) ( *((const ucell_t *)(addr)) )
542 #define READ_SHORT_DIC(addr) ( *((const uint16_t *)(addr)) )
547 #define HEADER_HERE (gCurrentDictionary->dic_HeaderPtr.Cell)
548 #define CODE_HERE (gCurrentDictionary->dic_CodePtr.Cell)
549 #define CODE_COMMA( N ) WRITE_CELL_DIC(CODE_HERE++,(N))
550 #define NAME_BASE (gCurrentDictionary->dic_HeaderBase)
551 #define CODE_BASE (gCurrentDictionary->dic_CodeBase)
552 #define NAME_SIZE (gCurrentDictionary->dic_HeaderLimit - gCurrentDictionary->dic_HeaderBase)
553 #define CODE_SIZE (gCurrentDictionary->dic_CodeLimit - gCurrentDictionary->dic_CodeBase)
555 #define IN_CODE_DIC(addr) ( ( ((uint8_t *)(addr)) >= gCurrentDictionary->dic_CodeBase) && ( ((uint8_t *)(addr)) < gCurrentDictionary->dic_CodeLimit) )
557 #define IN_NAME_DIC(addr) ( ( ((uint8_t *)(addr)) >= gCurrentDictionary->dic_HeaderBase) && ( ((uint8_t *)(addr)) < gCurrentDictionary->dic_HeaderLimit) )
558 #define IN_DICS(addr) (IN_CODE_DIC(addr) || IN_NAME_DIC(addr))
560 /* Address conversion */
561 #define ABS_TO_NAMEREL( a ) ((cell_t) (((ucell_t) a) - NAME_BASE ))
562 #define ABS_TO_CODEREL( a ) ((cell_t) (((ucell_t) a) - CODE_BASE ))
563 #define NAMEREL_TO_ABS( a ) ((ucell_t) (((cell_t) a) + NAME_BASE))
564 #define CODEREL_TO_ABS( a ) ((ucell_t) (((cell_t) a) + CODE_BASE))
566 /* The check for >0 is only needed for CLONE testing. !!! */
567 #define IsTokenPrimitive(xt) ((xt<gNumPrimitives) && (xt>=0))
569 #define FREE_VAR(v) { if (v) { pfFreeMem((void *)(v)); v = 0; } }
571 #define DATA_STACK_DEPTH (gCurrentTask->td_StackBase - gCurrentTask->td_StackPtr)
572 #define DROP_DATA_STACK (gCurrentTask->td_StackPtr++)
573 #define POP_DATA_STACK (*gCurrentTask->td_StackPtr++)
574 #define PUSH_DATA_STACK(x) {*(--(gCurrentTask->td_StackPtr)) = (cell_t) x; }
576 /* Force Quad alignment. */
577 #define QUADUP(x) (((x)+3)&~3)
580 #define MIN(a,b) ( ((a)<(b)) ? (a) : (b) )
583 #define MAX(a,b) ( ((a)>(b)) ? (a) : (b) )
587 #define TOUCH(argument) ((void)argument)
590 /***************************************************************
591 ** I/O related macros
592 ***************************************************************/
594 #define EMIT(c) ioEmit(c)
595 #define EMIT_CR EMIT('\n');
597 #define MSG(cs) pfMessage(cs)
598 #define ERR(x) MSG(x)
600 #define DBUG(x) /* PRT(x) */
601 #define DBUGX(x) /* DBUG(x) */
603 #define MSG_NUM_D(msg,num) { MSG(msg); ffDot((cell_t) num); EMIT_CR; }
604 #define MSG_NUM_H(msg,num) { MSG(msg); ffDotHex((cell_t) num); EMIT_CR; }
606 #define DBUG_NUM_D(msg,num) { pfDebugMessage(msg); pfDebugPrintDecimalNumber((cell_t) num); pfDebugMessage("\n"); }
608 #endif /* _pf_guts_h */