git @ Cat's Eye Technologies N-DCNC / master src / false.c
master

Tree @master (Download .tar.gz)

false.c @masterraw · history · blame

/* Introducing: Portable False!!!!

   PortableFalse is different from AmigaFalse in:
   - its Portable!!! :-)
   - full stack checking
   - strongly typed (no joke, really!)
   - debug-modi
   - real and meaningfull errormessages
   - ` inline assembly not supported
   - : and ; not supported for other than variable access.
   - "beta" (flush) and "zero-slash" (pick) from the amiga charset
     are now 'B' and 'O' resp.
   - 'D' toggles stack-watch mode on and off. format:
     [ bottom_of_stack , ... , top_of_stack | next_symbol ]
   - "-q" on command line is quiet mode: no title printing.
     (usefull for "filter"-type programs: 1> False -q filter.f <bla >burp)

   this source has been writtin in good C style:
   - no modularity whatsoever (only main())
   - only global variables
   - lots of ugly macros (replacing functions)
   - great source formatting and indentation

   still it compiles on 4-5 different ansi-C compilers. if you have trouble
   porting it to your machine, your compiler sucks. (guaranteed to be
   digested by: MaxonC++, SAS/C, DICE, GNUC++ (also on other platforms))

   todo:
   - interactive debugging?

   False, Amiga False, Portable False are all trademarks of $#%!

*/

#define MZ 10000
#define MS 1000
#include <stdio.h>
#define NIL 0
#define NUM 0
#define FUNC 1
#define VADR 2
#define UNDEF 3
#define l(x) ;break;case x:
#define x(num) {ernum=num;goto er;}
#define push(v,a) {if(S-2<sbeg)x(4)else{*--S=(v);*--S=(X)a;};}
#define pop(v,a) {if(S+2>se)x(5)else{if((ex=(int)a)!=(ge=(int)*S++))x(6);\
v= *S++;};}
#define pa(v,av) {if(S+2>se)x(5)else{av= *S++;v= *S++;};}
#define ru(v) {if(rp-1<rbeg)x(13)else{*--rp=(v);};}
#define ro(v) {if(rp+1>rend)x(14)else{v= *rp++;};}
#define CA(c) {ru(p);p=c;}
#define pu(x) push(x,NUM)
#define po(x) pop(x,NUM)
#define op(o) {po(b)po(d);pu((X)((int)d o (int)b));}
#define cm(o) {po(b)po(d);pu((X)(-((int)d o (int)b)));}
#define un(o) {po(b)pu((X)(o (int)b));}
#define ne (p<end)
#define W while
#define ec {W((*p!='}')&&ne)p++;p++;if(!ne)x(10);}
#define P printf
typedef char*X;typedef char**XP;X ST[MS],RST[MS],var[52],b,d,e,f,t1,t2,t3;
XP sbeg=ST+12,se=ST+MS-12,S,ts,rbeg=RST+12,rend=RST+MS-12,rp,vp;int ernum=
0,t,db=0,ex,ge,qq;FILE*fh;char src[MZ+5],a,c=0,*s,*end,*beg,*p=0,*erstr[]=
{"no args","could not open source file","source too large","data stack ov"
"erflow","data stack underflow","type conflict","stack not empty at exit "
"of program","unknown symbol","portable inline assembly not available","u"
"nbalanced '{'","unbalanced '\"'","unbalanced '['","return stack overflow"
,"return stack underflow"},*types[]={"Integer","Functional","Variabele",""
"Unitialised"};int main(int narg,char*args[]){S=se;rp=rend;t=1;for(vp=var;
vp<(var+52);){*vp++=(X)UNDEF;};if(narg>1)if(args[1][0]=='-'&&args[1][1]==
'q')t=2;if(t==1)P("Portable False Interpreter/Debugger v0.1 (c) 1993 $#%!"
"\n");if(narg<t+1)x(1);if((fh=fopen(args[t],"r"))==NIL)x(2);s=src;*s++=
'\n';W((a=fgetc(fh))!=EOF)if((src+MZ)<=s){fclose(fh);x(3)}else{*s++=a;};*s
++='\n';fclose(fh);end=s-1;beg=src+1;p=beg;W(ne){c= *p++;if(c>='0'&&c<='9'
){int num;sscanf(p-1,"%d",&num);W((*p>='0')&&(*p<='9'))p++;push((X)num,NUM
);}else if(c>='a'&&c<='z'){push((X)&var[(c-'a')*2],VADR);}else switch(c){
case' ':case '\n':case'\t':l('+')op(+)l('-')op(-)l('*')op(*)l('/')op(/)l(
'&')op(&)l('|')op(|)l('_')un(-)l('~')un(~)l('=')cm(==)l('>')cm(>)l('%')pa(
b,e)l('$')pa(b,e)push(b,e)push(b,e)l('\\')pa(b,e)pa(d,f)push(b,e)push(d,f)
l('@')pa(b,t1)pa(d,t2)pa(e,t3)push(d,t2)push(b,t1)push(e,t3)l('O')po(b)if(
S+((t=(int)b*2)+2)>se)x(5)b= *(S+t);d= *(S+t+1);push(d,b)l(':')pop(b,VADR)
pa(d,e)*((XP)b)=d;*(((XP)b)+1)=e;l(';')pop(b,VADR)push(*((XP)b),*(((XP)b)+
1));l('.')po(b)P("%d",(int)b);l(',')po(b)P("%c",(char)b);l('^')pu((X)fgetc
(stdin));l('B')fflush(stdout);fflush(stdin);l('\"')W((*p!='\"')&&ne){fputc
(*p,stdout);p++;};p++;if(!ne)x(11);l('{')ec;l('\'')pu((X)*p++);l('`')x(9);
l('D')db=!db;l('[')push((X)p,FUNC)t=1;W(t>0&&ne){a= *p++;if(a=='['){t++;}
else if(a==']'){t--;}else if(a=='{'){ec}else if(a=='\"'){W((*p!='\"')&&ne)
p++;p++;if(!ne)x(11);};};if(!ne)x(12);l(']')ro(e)if((int)e==0){ro(p)po(b)
if((int)b){ro(d)ru(d)CA(d)ru((X)1);}else{ro(d)ro(d);};}else if((int)e==1){
ro(p)ro(b)ro(d)ru(d)ru(b)CA(d)ru((X)0);}else{p=e;};l('!')pop(b,FUNC)CA(b);
l('?')pop(b,FUNC)po(d)if((int)d){CA(b);};l('#')pop(b,FUNC)pop(d,FUNC)ru(d)
ru(b);CA(d)ru((X)0);break;default:x(8);};if(db){c= *p;if(c!=' '&&c!='\n'&&
c!='\t'&&c!='{'&&c!='\"'){ts=S+20;if(ts>se)ts=se;P("[");W(ts>S){t=(int)*(
ts-2);if(t==FUNC){P("<func>");}else if(t==VADR){P("<var>");}else P("%d",(
int)*(ts-1));ts-=2;if(ts>S)P(",");};P("|'%c']\n",*p);}};};c=0;p=0;if(S!=se
)x(7);er:if(ernum){P("\nERROR: %s!\n",erstr[ernum-1]);if(c)P("WORD:  '%c'"
"\n",c);if(ernum==6)P("INFO:  Expecting %s type, while reading %s type.\n"
,types[ex],types[ge]);if(p){end=p;beg=p;W(*(beg-1)!='\n'){beg--;};W(*end!=
'\n'){end++;};t=end-beg;*end=0;if(t>0){P("LINE:  %s\n",beg);qq=p-beg+3;P(
"AT:");for(t=0;t<qq;t++){putchar(' ');};P("^\n");};};}return 0;}