Agreed. The file did not remain in that form for long.
I hope you'll also look at my later posts from May 12
which reads more nicely.
> Word alignment?
My plan was to ignore this at first. The target is my
own 8086 emulator which is missing roughly 1/3 of the
full instruction set.
> Is there some reason why putc() or putchar() i.e., send characters
> directly to an open tmpfile() file, wouldn't work in your macros?
>
No, I just hadn't consider that! That would simplify quite a bit
from the later versions.
> > Need to stitch up the link fields somehow.
>
> Of course, &image[XX], provides the address: image+XX. However, you
> only have a byte to encode a length to the next primitive. You could
> subtract two addresses. The problem is that any time you insert or
> delete bytes into any Forth word within image[], /all/ of the XX
> indexes from there onwards to the end of the dictionary, become
> incorrect and must be manually adjusted, since their values have been
> hard coded. BTDT.
>
> Now, if you called putc() or putchar() in your macros to write the
> bytes out to a file, then you could create a wrapper routine for putc()
> or putchar(), say i_putc(), which also increments a counter variable
> every time you output a character to a file. This variable would give
> you the current index position within image[]. Any time the char was
> '\0', you'd save the counter to subtract to later subtract from the
> current counter to obtain the LFA offset. Of course, that would mean
> that you'd need to use something other than '\0' for word padding the
> name field, e.g., perhaps a space.
>
Yes, that does seem like a good approach. I've gone in a different
direction with more complicated macros. But I am tempted to backtrack
and build the image with smaller functional pieces which are then
combined.
Still a work in progress, but here's the latest draft. It's now split
into several files.
$ for i in ppnarg.h asm8086.h applyx.h forth.h ; do echo ---- $i: ---- ; cat $i ; done && echo -- && cpp -P forth.h
---- ppnarg.h: ----
/*
* The PP_NARG macro evaluates to the number of arguments that have been
* passed to it.
*
* Laurent Deniau, "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007).
*/
#define PP_NARG(...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
---- asm8086.h: ----
#define LEA(to,m,r,r_m) to+0x8d,MRM(m,r,r_m)
#define MOV(to,m,r,r_m) to+0x8b,MRM(m,r,r_m)
#define ADD(to,m,r,r_m) to+0x03,MRM(m,r,r_m)
#define SUB(to,m,r,r_m) to+0x2b,MRM(m,r,r_m)
#define F -2
#define MRM(m,r,r_m) 0##m##r##r_m
#define Z 0
#define B 1
#define W 2
#define R 3
#define AX 0
#define CX 1
#define DX 2
#define BX 3
#define SP 4
#define BP 5
#define SI 6
#define DI 7
#define BX_SI 0
#define BX_DI 1
#define BP_SI 2
#define BP_DI 3
#define SI_ 4
#define DI_ 5
#define BP_ 6
#define BX_ 7
#define TEST(m,r,r_m) 0x85,MRM(m,r,r_m)
#define IMUL(m, r_m) 0xf7,MRM(m,5,r_m)
#define INC_(m, r_m) 0xff,MRM(m,0,r_m)
#define DEC_(m, r_m) 0xff,MRM(m,1,r_m)
#define JMP_(m, r_m) 0xff,MRM(m,5,r_m)
#define POP(r) 0x58+r
#define PUSH(r) 0x50+r
#define ADDAX 0x05
#define LODS 0xAD
#define JZ 0x74
---- applyx.h: ----
#include "ppnarg.h"
/* need extra level to force extra eval */
#define Paste(a,b) a ## b
#define XPASTE(a,b) Paste(a,b)
/* APPLYXn variadic X-Macro by M Joshua Ryan */
/* Free for all uses. Don't be a jerk. */
/* I got bored after typing 15 of these. */
/* You could keep going upto 64 (PPNARG's limit). */
#define APPLYX1(X, a) X(a)
#define APPLYX2(X, a,b) X(a) X(b)
#define APPLYX3(X, a,b,c) X(a) X(b) X(c)
#define APPLYX4(X, a,b,c,d) X(a) X(b) X(c) X(d)
#define APPLYX5(X, a,b,c,d,e) X(a) X(b) X(c) X(d) X(e)
#define APPLYX6(X, a,b,c,d,e,f) X(a) X(b) X(c) X(d) X(e) X(f)
#define APPLYX7(X, a,b,c,d,e,f,g) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g)
#define APPLYX8(X, a,b,c,d,e,f,g,h) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h)
#define APPLYX9(X, a,b,c,d,e,f,g,h,i) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i)
#define APPLYX10(X, a,b,c,d,e,f,g,h,i,j) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j)
#define APPLYX11(X, a,b,c,d,e,f,g,h,i,j,k) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k)
#define APPLYX12(X, a,b,c,d,e,f,g,h,i,j,k,l) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l)
#define APPLYX13(X, a,b,c,d,e,f,g,h,i,j,k,l,m) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m)
#define APPLYX14(X, a,b,c,d,e,f,g,h,i,j,k,l,m,n) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) X(n)
#define APPLYX15(X, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \
X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) X(n) X(o)
#define APPLYX_(M, ...) M(__VA_ARGS__)
#define APPLYXn(X, ...) APPLYX_(XPASTE(APPLYX, PP_NARG(__VA_ARGS__)), X, __VA_ARGS__)
---- forth.h: ----
#include "ppnarg.h"
#include "applyx.h"
#include "asm8086.h"
#define NEXT LODS, JMP_(R,AX)
#define PUSHRSP(r) LEA(,B,DI,DI_),0xfc, MOV(,Z,r,DI_)
#define POPRSP(r) MOV(F,Z,r,DI_), LEA(,B,DI,DI_),4
#define CODE(letters,...) _COUNT(LETTERS letters __VA_ARGS__)
#define WORD(letters,...) _COUNT(LETTERS letters JMP(DOCOL), __VA_ARGS__)
#define LETTERS(...) PP_NARG(__VA_ARGS__),APPLYXn(CHARIFY, __VA_ARGS__)
#define _FINIS(...) __VA_ARGS__
#define _COUNT(...) __VA_ARGS__,PP_NARG(__VA_ARGS__)
#define STRINGIFY(x) #x
#define CHARIFY(x) *STRINGIFY(x),
static inline int
forth(char *mem){
unsigned char image[] = {
0,
CODE((d,o,c,o,l), PUSHRSP(SI), ADDAX,4,0, MOV(,R,DI,AX), NEXT),
CODE((e,x,i,t), POPRSP(SI), NEXT),
CODE((l,i,t), LODS, PUSH(AX), NEXT),
CODE((d,r,o,p), POP(AX), NEXT),
CODE((s,w,a,p), POP(AX), POP(BX), PUSH(AX), PUSH(BX), NEXT),
CODE((d,u,p), MOV(,R,BP,SP), MOV(,B,AX,BP_),0, PUSH(AX), NEXT),
CODE((o,v,e,r), MOV(,R,BP,SP), MOV(,B,AX,BP_),2, PUSH(AX), NEXT),
CODE((r,o,t), POP(AX), POP(BX), POP(CX), PUSH(BX), PUSH(AX), PUSH(CX), NEXT),
CODE((-,r,o,t), POP(AX), POP(BX), POP(CX), PUSH(AX), PUSH(CX), PUSH(BX), NEXT),
CODE((2,d,r,o,p), POP(AX), POP(AX), NEXT),
CODE((2,d,u,p), MOV(,R,BP,SP), MOV(,B,AX,BP_),0, MOV(,B,BX,BP_),2, PUSH(BX), PUSH(AX), NEXT),
CODE((2,s,w,a,p), POP(AX), POP(BX), POP(CX), POP(DX),PUSH(BX),PUSH(AX),PUSH(DX),PUSH(CX),NEXT),
CODE((?,d,u,p), MOV(,R,BP,SP), MOV(,B,AX,BP_),0, TEST(R,AX,AX), JZ,1, PUSH(AX), NEXT),
CODE((1,+), MOV(,R,BP,SP), INC_(B,BP_),0, NEXT),
CODE((1,-), MOV(,R,BP,SP), DEC_(B,BP_),0, NEXT),
CODE((+), POP(AX), MOV(,R,BP,SP), ADD(F,B,AX,BP_),0, NEXT),
CODE((-), POP(AX), MOV(,R,BP,SP), SUB(F,B,AX,BP_),0, NEXT),
CODE((*), POP(AX),POP(BX), IMUL(R,BX), PUSH(AX), NEXT),
CODE((!), POP(BX), POP(AX), MOV(F,Z,AX,BX), NEXT),
CODE((@), POP(BX), MOV(,R,AX,BX), PUSH(AX), NEXT),
CODE((+,!), POP(BX), POP(AX), ADD(F,Z,AX,BX), NEXT),
CODE((-,!), POP(BX), POP(AX), SUB(F,Z,AX,BX), NEXT),
WORD((d,o,u,b,l,e), DUP, PLUS, EXIT),
};
return memcpy(mem, image, sizeof image);
}
--
static inline int
forth(char *mem){
unsigned char image[] = {
0,
5,*"d", *"o", *"c", *"o", *"l", +0x8d,0175,0xfc, +0x8b,0065, 0x05,4,0, +0x8b,0370, 0xAD, 0xff,0350,19,
4,*"e", *"x", *"i", *"t", -2 +0x8b,0065, +0x8d,0175,4, 0xAD, 0xff,0350,13,
3,*"l", *"i", *"t", 0xAD, 0x50+0, 0xAD, 0xff,0350,9,
4,*"d", *"r", *"o", *"p", 0x58+0, 0xAD, 0xff,0350,9,
4,*"s", *"w", *"a", *"p", 0x58+0, 0x58+3, 0x50+0, 0x50+3, 0xAD, 0xff,0350,12,
3,*"d", *"u", *"p", +0x8b,0354, +0x8b,0106,0, 0x50+0, 0xAD, 0xff,0350,13,
4,*"o", *"v", *"e", *"r", +0x8b,0354, +0x8b,0106,2, 0x50+0, 0xAD, 0xff,0350,14,
3,*"r", *"o", *"t", 0x58+0, 0x58+3, 0x58+1, 0x50+3, 0x50+0, 0x50+1, 0xAD, 0xff,0350,13,
4,*"-", *"r", *"o", *"t", 0x58+0, 0x58+3, 0x58+1, 0x50+0, 0x50+1, 0x50+3, 0xAD, 0xff,0350,14,
5,*"2", *"d", *"r", *"o", *"p", 0x58+0, 0x58+0, 0xAD, 0xff,0350,11,
4,*"2", *"d", *"u", *"p", +0x8b,0354, +0x8b,0106,0, +0x8b,0136,2, 0x50+3, 0x50+0, 0xAD, 0xff,0350,18,
5,*"2", *"s", *"w", *"a", *"p", 0x58+0, 0x58+3, 0x58+1, 0x58+2,0x50+3,0x50+0,0x50+2,0x50+1,0xAD, 0xff,0350,17,
4,*"?", *"d", *"u", *"p", +0x8b,0354, +0x8b,0106,0, 0x85,0300, 0x74,1, 0x50+0, 0xAD, 0xff,0350,18,
2,*"1", *"+", +0x8b,0354, 0xff,0106,0, 0xAD, 0xff,0350,11,
2,*"1", *"-", +0x8b,0354, 0xff,0116,0, 0xAD, 0xff,0350,11,
1,*"+", 0x58+0, +0x8b,0354, -2 +0x03,0106,0, 0xAD, 0xff,0350,11,
1,*"-", 0x58+0, +0x8b,0354, -2 +0x2b,0106,0, 0xAD, 0xff,0350,11,
1,*"*", 0x58+0,0x58+3, 0xf7,0353, 0x50+0, 0xAD, 0xff,0350,10,
1,*"!", 0x58+3, 0x58+0, -2 +0x8b,0003, 0xAD, 0xff,0350,9,
1,*"@", 0x58+3, +0x8b,0303, 0x50+0, 0xAD, 0xff,0350,9,
2,*"+", *"!", 0x58+3, 0x58+0, -2 +0x03,0003, 0xAD, 0xff,0350,10,
2,*"-", *"!", 0x58+3, 0x58+0, -2 +0x2b,0003, 0xAD, 0xff,0350,10,
6,*"d", *"o", *"u", *"b", *"l", *"e", JMP(DOCOL), DUP, PLUS, EXIT,11,