#include"a.h" #define Aget(T,a,i)*(T*)aget((a),i) #define Afop(T,a,x,i,...)for(W i=0;i<(a)->l;++i){T*x=aget((a),i);__VA_ARGS__;} #define Afor(T,a,x,i,...)for(W i=0;i<(a).l;++i){T x=Aget(T,&(a),i);__VA_ARGS__;} #define Nt(T,p)((T*)(p)->v) #define S0 (S){0,0} #define Sl(s)(S){SZ(s)-1,(B*)(s)} #define Sfor(s,x,i,...)W i;for(i=0;ip+(a->z*i);} _ V*aput(A*a){Q(2*a->l>a->c,a->c*=2,a->p=remk(a->p,a->c*a->z))R aget(a,a->l++);} _ C scmp(S a,S b){Q(a.l!=b.l,R b.l-a.l;)Sfor(a,c,i,Q(c!=b.p[i],R b.p[i]-a.p[i];))R 0;} _ N*nnew(S k,W z){N*n;n=mk(z+SZ(N)),n->k=k;R n;} _ N*nget(T n,S k ){ C c;WH(n,Q(0==(c=scmp(k,n->k)),R n);n=0l:n->r)R 0;} _ N*nput(T*t,S k,W z){N*o=0,*n=*t;C c;WH(n,Q(0==(c=scmp(k,n->k)),R 0)o=n,n=0l:n->r)R*(!o?t:0l:&o->r)=nnew(k,z);} _ S snxt(S s,B d){_ S x;_ W i;W b;Q(s.l,i=0,x=s);for(;i=MEMSZ||i>8),mb(i+1,h);} _ V mw(W i,W w){mh(i,w>>16),mh(i+2,w);} _ V mcpy(W dst,B*src,W l){for(W i=0;ip)WH(l&&(x=snxt(S0,'/')).l,l=nget(l,x))R(L*)(l?l->v:0);} _ B ops[OPSZ*2]="npexpbphpwprfbfhfwmbmhmwioiissdrswduovadsumudianorxrslsrsaeqltgtnojujccacc"; _ B op(B x[2]){W i=0;WH(i++='a'&&h<='f'?h-'a'+10:h>='A'&&h<='F'?h-'F'+10:h>='0'&&h<='9'?h-'0':16;} _ B ws(B x){R' '==x||'\t'==x||'\r'==x||'\n'==x;} _ V tw(S t){fprintf(stderr,"`%.*s`",t.l,t.p);} _ V tasrt(S t,C c){Q(c!=*t.p,tw(t),die(" expected %c",c))} _ B tz(S t){R t.l<4?1:t.l<6?2:t.l<10?4:(tw(t),die(" >=32 bits"),0);} _ V tto4b(S w,B*bs){W b;++w.p,--w.l;Sfor(w,a,i,Q(16>(b=htob(a)),bs[i/2]=(i%2?bs[i/2]:0)<<4|b)OR tw(w),die(" unknown char `%c`\n",a))} _ W tton(S w){W b;W r;r=0,++w.p,--w.l;Sfor(w,a,i,Q(16>(b=htob(a)),r<<=4,r|=b)OR tw(w),die(" unknown char `%c`\n",a));R r;} _ S next(S*t){B c,**p;W*l;l=&t->l,p=&t->p;*p+=*l,*l=0;WH(ws(**p),++*p);c=**p,++*l; Q(0==c,R*t)OR Q('"'==c,WH('"'!=(*p)[(*l)++],))OR Q('{'==c,WH('}'!=(*p)[(*l)++],))OR WH(!ws((*p)[*l]),++*l); R*t;} _ V finp(F); _ V builtin(S*t){FILE*f;S y,x=*t;++x.p,--x.l; BE("org",y=next(t),tasrt(y,'#'),mel=tton(*t);N(orq,orq=1,org=mel)) BE("res",y=next(t),tasrt(y,'#'),mel+=tton(*t)) BE("emb",y=next(t),tasrt(y,'"'),y.p[y.l-1]=0;WIF(f,(C*)y.p+1,"rb",mew=mel+=fread(meb+mel,1,(W)0-1,f))) BE("inc",y=next(t),tasrt(y,'"'),y.p[y.l-1]=0;WIF(f,(C*)y.p+1,"rb",finp(f))) tw(x),die(" unknown builtin");} _ V pass1(S*t){_ B o=0;S x=*t;B c;c=*x.p; Q('{'==c,/*discard*/)OR Q('"'==c,mcpy(mel,x.p+1,x.l-=2),mew=mel+=x.l)OR Q('#'==c,B bs[tz(x)];tto4b(x,bs),mcpy(mel,bs,SZ(bs)),mew=mel+=SZ(bs))OR Q(':'==c,N*l;++x.p,--x.l;N(l=nput(&root,x,SZ(L)),tw(x),die(" duplicate label"))*Nt(L,l)=(L){root,mel},root=l)OR Q('!'==c,N*m;++x.p,--x.l;N(m=nput(¯os,x,SZ(A)),tw(x),die(" duplicate macro"))aini(Nt(A,m),8,SZ(S));WH(';'!=*next(t).p,*(S*)aput(Nt(A,m))=*t))OR Q('@'==c,++x.p,--x.l,*(P*)aput(&refs)=(P){0,root,mel,x},mw(mel,0),mew=mel+=4)OR Q('^'==c,++x.p,--x.l,*(P*)aput(&refs)=(P){1,root,mel,x},mb(mel,0),mew=mel+=1)OR Q('`'==c,N*m;++x.p,--x.l;N(m=nget(macros,x),tw(x),die(" unknown macro"))Afor(S,*Nt(A,m),y,i,pass1(&y)))OR Q('-'==c,builtin(t))OR Q(';'==c,N(root,die("; at top-level"))root=((L*)root->v)->p)OR Q('~'==c,++x.p,--x.l,o|=0x40,pass1(&x))OR Q('$'==c,++x.p,--x.l,o|=0x80,pass1(&x))OR Q(2!=x.l||OPSZ==(o|=op(x.p)),tw(x),die(" unknown inst"))OR mb(mel++,o),mew=mel,o=0;} _ V pass2(V){L*l;Ws a;Bs b;Afor(P,refs,r,i,Q(l=lget(r.p,r.n), Q(0==r.r,mw(r.a,l->a))OR Q(1==r.r,a=l->a-r.a;Q(a==(b=a),mb(r.a,b))OR tw(r.n),die(" too far (%d bytes) for ^ref",a)))OR tw(r.n),die(" unknown ref"))} _ V finp(F f){B*in;W l;S t={0}; fseek(f,0,SEEK_END),l=ftell(f),fseek(f,0,SEEK_SET),in=mk(l+1),xr(f,in,1,l),in[l]=0,t.p=in; WH(0!=*next(&t).p,pass1(&t))} _ V fout(F f){pass2();xw(f,meb,1,mew-org);} I main(I ac,C**av){FILE *f; Q(3!=ac,die("usage: as INPUT.ASM OUTPUT.ROM")) aini(&refs,64,SZ(P)); WIF(f,av[1],"rb",finp(f)) WIF(f,av[2],"wb",fout(f)) printf("done: %d bytes wrote\n",mew-org); R 0;}