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