changeset 5369:ffd6f9ff59f3

<oren> fetch https://raw.githubusercontent.com/orenwatson/scrip7/master/scrip7.c
author HackBot
date Thu, 21 May 2015 22:11:18 +0000
parents 19f97b45593c
children f52a82ebde65
files scrip7.c
diffstat 1 files changed, 806 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scrip7.c	Thu May 21 22:11:18 2015 +0000
@@ -0,0 +1,806 @@
+#define true
+true /*
+if [ $1 = 'simple' ]
+then
+cc $0 -Wall -Wextra -lm -fwrapv -o scrip7
+else
+echo "Compiling binaries and extracting doc and test..."
+cc $0 -Wall -Wextra -lm -fwrapv -o scrip7 2>err
+cc -DNOS7MAIN $0 -c -lm -fwrapv -o scrip7.o 2>>err
+head err
+sed -n '/B[E]GINHEADER/,/E[N]DHEADER/p' $0 >scrip7.h
+cat >docs.txt <<END
+Author: Oren Watson
+Scrip7 hopefully getting stabler release 2015-05-12
+You can extract and compile the full distribution simply by running this
+file as a shell script like sh scrip7.c This produces the interpreter scrip7,
+the library scrip7.o, the documentation docs.txt.
+To include, include this file. If your platform does not support weak symbols, 
+you will also need to define NOS7MAIN when including it.
+Changes in this new version:
+Added a variable system to make things easier. the $ set instruction and
+@ get instruction are used with string src as varaible name,
+and dest as value. e.g. a='a a$3"foo a='f _.a a@3"foo _.a prints fa.
+
+Language Description:
+A scrip7 program or script consists of statements, jumps, and loop brackets.
+Jump targets are written with #, Loops are written with {} and [] 
+The {} brackets will jump  to the matching {} or [] bracket. [] brackets
+are inert labels. The quickest way to see how these are supposed to be used, 
+is to see the example code.
+Statements consist of a register letter, an optional offset, an operator,
+and either a literal, or another register and optional offset.
+There are 6 registers which store memory addresses, and whose notation 
+depends on the type of data they are being used to point to. The data types 
+in scrip7 are: 8 bit integers, 16 bit integers, 32 bit integers, 64 bit 
+integers, 32 bit floating point, 64 bit floating point, pointers, and the 
+"address" type which means accessing the address the register stores.
+The notation for registers is in the following table:
+int8 int16 int32 int64 float double pointer addr
+  a    A     i     I     u     U      o      O
+  b    B     j     J     v     V      p      P
+  c    C     k     K     w     W      q      Q
+  d    D     l     L     x     X      r      R
+  e    E     m     M     y     Y      s      S
+  f    F     n     N     z     Z      t      T
+                   g           g      g      G
+                   h           h      h      H
+A special register called _ is supported for the first register in a statement.
+It is zero when read, and does nothing when written to.
+g and h are relatively normal registers, with VARIANT type adjusting
+between double, int64, and pointer depending on the other operand.
+The offsets are added to the address of the accessed data. An offset of
+the form (1234 counts by bytes. An offset of the form )1234 counts by
+the size of the addressed data type.
+The literal syntax is as follows: 
+1234    Decimal integer.
+%34af   Hexadecimal integer. A space at the end is mandatory.
+3%ff    Repeated hex. 3%ff is equivalent to %ffffffff .
+12.34   Decimal floating point number.
+12/34   Fractional floating point number.
+1.23^4  Decimal floating point with decimal exponent.
+{...}   Delimited string or code literal.
+3"foo   Hollerith constant string. end " is not allowed or needed.
+'a      Character constant. No ' after it.
+The operators have a common semantics where usually only the first register's
+data or address (hereafter called the destination) is modified, and the
+second operand (hereafter called the source) is only read.
+If the second operand is a literal, or the first operand is the _ register,
+modifying it does nothing.
+Command List:
+END
+grep '^\( \|	\)*\(c\|br\)ase' scrip7.c | sed -e "s/.*ase '/α/; s/\\\\//; s/': \\/\\//β /; s/src/β/g; s/dest/α/g" >>docs.txt
+echo "Running test:"
+./scrip7 >out <<END
+I=260I%170I+8I*9I/2I-5_pI {checks arithmetic}
+I=7%7f I&6%e0 I|3%01 IX7%0f _xI {checks bit operations}
+I=5I^5_pII=3I^4_pI {checks exponentiation}
+u=43/8_xi {basic check for ieee float}
+U=35478/256_xI {basic check for ieee double}
+U=355/113_pU {check real number output}
+I=1J>1[J+II+JIl1000}#_pI {check basic looping}
+I=%5253545556575859{insert newline}b='
+ [_.aa>1O!P(1}# {check character output, char literals, and byte order}
+X=4.5325_pX_xXJ\X_pJJ>1_pJ 
+{check float literals and output some more and undivide}
+I=-99_pI {check negative integer literals}
+J<2J:23J:17J:27J:67J:44
+{Now a test of insertion sort}
+[O=RQ=R[IlKQ=O#I>1O!P}#KzLL>1R!P}#
+O=SP=SQ=SR=S
+_pI_pI)1_pI)2_pI)3_pI)4 {verify sort result and register offsets}
+_z0 {modifying void register and constants should do nothing}
+END
+if diff out - <<END
+436
+0f6f6f6f6e6e6e6e
+3125
+81
+40ac0000
+406152c000000000
+3.141593
+1597
+YXWVUTSR
+4.532500
+1813/400
+1813
+400
+-99
+17
+23
+27
+44
+67
+END
+then
+echo "Success"
+else
+echo "Failure"
+fi
+rm out
+fi
+exit 0
+true */
+//BEGINHEADER
+#include "stdio.h"
+#include "stdint.h"
+extern int s7logflag,s7freeflag,s7errflag,s7memsafe;
+/*Declarations for non-static*/
+void scrip7(char *code);
+/*execute string*/
+void scrip7f(FILE *code);
+/*execute whole file as a series of programs.*/
+int scrip7rc(FILE *code);
+/*execute a program, ending with .\n, returns 0 if the program was empty.*/
+void scrip7cli(FILE *code);
+/*execute a set of programs, ending with an empty program.*/
+struct va7 {int64_t c;double x;char *p;};
+extern struct scrip7state{
+	char *v[8];
+	char *data;
+	struct scrip7var *vars;
+}globa7;
+void se7var(char *name,struct va7 val);
+struct va7 ge7var(char *name);
+//ENDHEADER
+char scrap[1000];
+struct scrip7state globa7 = {{0,0,0,0,0,0,0,0},scrap,0};
+int s7logflag=0;
+int s7freeflag=0;
+int s7errflag=1;
+
+#include "stdlib.h"
+#include "string.h"
+#include "math.h"
+#include "inttypes.h"
+#include "stddef.h"
+#include "unistd.h"
+#define ei else if
+#define un(x) if(!(x))
+#define wh while
+#define loop for(;;)
+#define brase break;case
+#define brault break;default
+#define sut struct
+#define let(x,y) typeof(y) x = y
+#define new(T,y...) ({T *$$tmp=malloc(sizeof(T)); *$$tmp=(T){y}; $$tmp;})
+
+sut scrip7var{sut scrip7var*tbl[32];sut va7 val;};
+
+void se7var(char *n,sut va7 val){
+	sut scrip7var**q=&(globa7.vars);
+	loop{
+		if(!*q)*q=new(sut scrip7var,{0},{0,0,0});
+		if(!*n){(*q)->val=val;return;}
+		q=(*q)->tbl+*n%32;
+		n++;
+	}
+}
+
+sut va7 ge7var(char *n){
+	sut scrip7var**q=&(globa7.vars);
+	loop{
+		if(!*q)*q=new(sut scrip7var,{0},{0,0,0});
+		if(!*n){return (*q)->val;}
+		q=(*q)->tbl+*n%32;
+		n++;
+	}
+}
+
+static char *s7getcmd(FILE *f){
+	int n=80,l=0;
+	char *s=NULL,*q;
+	loop{
+		s=realloc(s,n);
+		q=fgets(s+l,n-l,f);
+		if(!q)return s;
+		l+=strlen(s+l);
+		if(s[l-1]=='\n')
+		if(s[l-2]=='.'){
+			s[l-2]=0;
+			return s;
+		}
+		if(l==n-1)n*=2;
+	}
+}
+
+int undiv(double x,int64_t*np,int64_t*dp){
+	double y;int i=0;
+	int64_t p=0,q=1,r=1,s=0,n;
+	do{i++;if(i>10)break;
+	n = (int64_t)((p-x*q)/(x*s-r));
+	p += n*r;q += n*s;y = (double)p/q;
+	if(y==x){*np=p;*dp=q;return i;}
+	n = (int64_t)((r-x*s)/(x*q-p));
+	r += n*p;s += n*q;y = (double)r/s;
+	}while(y!=x);
+	*np=r;*dp=s;return i;
+}
+
+static void memsetl(char *r,char *s,int len,int num){
+	memmove(r,s,len);
+	int k=1;
+	wh(k<num){
+		memcpy(r+k*len,r,len*(k*2>num?num-k:k));
+		k*=2;
+	}
+}
+
+static char *s7getinput(int fn,char b){
+	int n=80,l=0;
+	char *s=malloc(n);
+	wh(1){
+		read(fn,s+l,1);
+		if(s[l]==b)break;
+		l++;
+		if(l==n-1){
+			n*=2;
+			s=realloc(s,n);
+		}
+	}
+	s[l]=0;
+	return s;
+}
+
+#define TY_INT8 0
+#define TY_INT16 1
+#define TY_INT32 2
+#define TY_INT64 3
+#define TY_ADDR 4
+#define TY_PTR 5
+#define TY_FLOAT 6
+#define TY_DOUBLE 7
+#define TY_VARIANT 8
+static char *tpnm[]={"int8","int16","int32","int64",
+		"addr","void*","float","double","variant"};
+static int tpsz[]={1,2,4,8,1,sizeof(void*),sizeof(float),sizeof(double),8};
+static int isint[]={1,1,1,1,0,0,0,0,0};
+static int isreal[]={0,0,0,0,0,0,1,1,0};
+static int isptr[]={0,0,0,0,1,1,0,0,0};
+static int isnum[]={1,1,1,1,0,0,1,1,0};
+#define VR_AIOU 0
+#define VR_BJPV 1
+#define VR_CKQW 2
+#define VR_DLRX 3
+#define VR_EMSY 4
+#define VR_FNTZ 5
+#define VR_G 6
+#define VR_H 7
+#define VR_LIT 8
+#define VR_VOID 9
+static char *vrnm[]={"aiou","bjpv","ckqw","dlrx","emsy","fntz",
+		"g","h","constant","voidvar"};
+
+#define Log(mesg,args...) {if(s7logflag)fprintf(stderr,"%ld:"mesg"\n",g-code,##args);}wh(0)
+
+#define Die(mesg) {if(s7errflag)fprintf(stderr,"%ld:"mesg"\n",g-code);goto hell;}wh(0)
+
+static void gettype(char*g,int*d,int *dt){
+	if(*g>='a'&&*g<='f')*d=*g-'a',*dt=TY_INT8;
+	ei(*g>='A'&&*g<='F')*d=*g-'A',*dt=TY_INT16;
+	ei(*g>='i'&&*g<='n')*d=*g-'i',*dt=TY_INT32;
+	ei(*g>='I'&&*g<='N')*d=*g-'I',*dt=TY_INT64;
+	ei(*g>='o'&&*g<='t')*d=*g-'o',*dt=TY_PTR;
+	ei(*g>='O'&&*g<='T')*d=*g-'O',*dt=TY_ADDR;
+	ei(*g>='u'&&*g<='z')*d=*g-'u',*dt=TY_FLOAT;
+	ei(*g>='U'&&*g<='Z')*d=*g-'U',*dt=TY_DOUBLE;
+	ei(*g=='G')*d=VR_G,*dt=TY_ADDR;
+	ei(*g=='H')*d=VR_H,*dt=TY_ADDR;
+	ei(*g=='g')*d=VR_G,*dt=TY_VARIANT;
+	ei(*g=='h')*d=VR_H,*dt=TY_VARIANT;
+	ei(*g=='_')*d=VR_VOID,*dt=-1;
+}
+
+static void setva7(int dt,char **dp, ptrdiff_t dx, struct va7*v){
+	if(dp==0)return;
+	if(dt==TY_INT8)(*(int8_t*)(*dp+dx)) = v->c;
+	ei(dt==TY_INT16)(*(int16_t*)(*dp+dx)) = v->c;
+	ei(dt==TY_INT32)(*(int32_t*)(*dp+dx)) = v->c;
+	ei(dt==TY_INT64)(*(int64_t*)(*dp+dx)) = v->c;
+	ei(dt==TY_ADDR)(*dp) = v->p-dx;
+	ei(dt==TY_PTR)(*(void**)(*dp+dx)) = v->p;
+	ei(dt==TY_FLOAT)(*(float*)(*dp+dx)) = v->x;
+	ei(dt==TY_DOUBLE)*(double*)(*dp+dx) = v->x;
+}
+
+static void getva7(int st,char **sp, ptrdiff_t sx, struct va7 *v){
+	if(!sp){
+		v->c=0;
+		v->p=NULL;
+		v->x=0.0;
+		return;
+	}
+	if(st==TY_INT8)   v->c=*(int8_t*)(*sp+sx);
+	if(st==TY_INT16)  v->c=*(int16_t*)(*sp+sx);
+	if(st==TY_INT32)  v->c=*(int32_t*)(*sp+sx);
+	if(st==TY_INT64||st==TY_VARIANT)  v->c=*(int64_t*)(*sp+sx);
+	if(st==TY_ADDR)   v->p=(*sp+sx);
+	if(st==TY_PTR||st==TY_VARIANT)    v->p=*(void**)(*sp+sx);
+	if(st==TY_FLOAT)  v->x=*(float*)(*sp+sx);
+	if(st==TY_DOUBLE||st==TY_VARIANT) v->x=*(double*)(*sp+sx);
+	if(st<=TY_INT64){ v->p=(*sp+sx);v->x=v->c;}
+	ei(st<=TY_PTR){   v->c=(int64_t)v->p;v->x=v->c;}
+	ei(st<=TY_DOUBLE){v->c=v->x;v->p=(*sp+sx);}
+}
+
+static int64_t memlen(char *d,struct va7 *s,int t){
+	int64_t n=0;
+	struct va7 v;
+	loop{
+		char *q=d+tpsz[t]*n;
+		getva7(t,&q,0,&v);
+		if(t<TY_ADDR&&v.c==s->c)break;
+		ei(t<TY_FLOAT&&t>=TY_ADDR&&v.p==s->p)break;
+		ei(t<8&&t>=TY_FLOAT&&v.x==s->x)break;
+		n++;
+	}
+	return n;
+}
+
+#define usg uintptr_t
+
+static char *fwdjmptbl[256][2];
+static uint8_t bakjmptbl[256];
+static int pcache(char **s){
+	if(**s=='{'){
+		uint8_t k = ((usg)*s)%256;
+		if(fwdjmptbl[k][0]==*s){
+			*s = fwdjmptbl[k][1]+1;
+			return 1;
+		}else return 0;
+	}
+	if(**s=='}'){
+		uint8_t k = bakjmptbl[((usg)*s)%256];
+		if(fwdjmptbl[k][1]==*s){
+			*s = fwdjmptbl[k][0]+1;
+			return 1;
+		}else return 0;
+	}
+	return 0;
+}
+
+static char *skipp(char *s){
+	int l=0,nl=0;
+	char *ss=s;
+	if(*s=='['||*s==']')return s+1;
+	un(*s=='{'||*s=='}')return s;
+	if(pcache(&s))return s;
+	do{
+		if(*s=='['||*s=='{')nl=l+1;
+		if(*s==']'||*s=='}')nl=l-1;
+		if(nl==0){
+			usg ssh = (usg)ss%256, sh = (usg)s%256;
+			if(l>0){
+				fwdjmptbl[ssh][0]=ss;
+				fwdjmptbl[ssh][1]=s;
+				bakjmptbl[sh]=ssh;
+			}ei(l<0){
+				fwdjmptbl[sh][0]=s;
+				fwdjmptbl[sh][1]=ss;
+				bakjmptbl[ssh]=sh;
+			}
+			return ++s;
+		}
+		l=nl;
+		if(l<0)s--;
+		if(l>0)s++;
+	}wh(1);
+}
+
+static int64_t parsedec(char **gp){
+	int64_t i=0;
+	wh(**gp>='0'&&**gp<='9'){
+		i=i*10+*(*gp)++-'0';
+	}
+	return i;
+}
+
+static void parsenum(char **gp,int *stp,struct va7 *sp){
+	int64_t i=0,j;
+	double x;
+	static char *p=0;
+	int sgn=1;
+	char *g=*gp;
+	if(*g>='0'&&*g<='9'){
+		i=parsedec(&g);
+	}else if(*g=='-'){
+		sgn = -1;
+		g++;
+		i=-parsedec(&g);
+	}
+	x = i;
+	*stp = TY_INT64;
+	if(*g=='.'){
+		*stp = TY_DOUBLE;
+		g++;
+		j=0;
+		while(*g>='0'&&*g<='9'){
+			i=i*10+(*g++-'0')*sgn;
+			j++;
+		}
+		i=x=(double)i/pow(10,j);
+		if(*g=='^'){
+			g++;
+			j=parsedec(&g);
+			x*=pow(10,j);
+		}
+	}ei(*g=='/'){
+		*stp = TY_DOUBLE;
+		g++;
+		j=parsedec(&g);
+		i=x=(double)i/j;
+	}ei(*g=='%'){
+		g++;
+		j=0;
+		int l=0;
+		loop{
+			int k=(*g+30)%39;
+			if(k>=16)break;
+			j=j*16+k;
+			g++;l++;
+		}
+		int64_t t=j;
+		wh(i>0){
+			j=(j<<(l*4))+t;
+			i--;
+		}
+		i=j;
+		x=i;
+	}ei(*g=='"'){
+		p=(char*)realloc(p,i+1);
+		p[i]=0;
+		for(j=0;j<i;j++){
+			p[j]=*++g;
+		}
+		g++;
+		*stp=TY_ADDR;
+	}else{
+		x=i;
+	}
+	sp->p = p;
+	sp->c = i;
+	sp->x = x;
+	*gp = g;
+}
+
+void scrip7(char *code){
+	char **v=globa7.v;
+	int i;
+	for(i=0;i<8;i++)v[i]=globa7.data;
+	char *g=code;
+	int d,dt,s,st;
+	char op;
+	intptr_t dx,sx;
+	struct va7 dv,sv;
+	wh(*g){
+		char*j=skipp(g);
+		if(j!=g)Log("skipped parens");
+		g=j;
+		if(*g=='`'){Log("backtick is early exit");goto hell;}
+		if((*g>0&&*g<=' ')||*g=='#'){g++;continue;}
+		un((*g<='Z'&&*g>='A')||(*g<='z'&&*g>='a')||*g=='_')
+			Die("bad dest name");
+		gettype(g,&d,&dt);
+		dx=0;
+		sx=0;
+		g++;
+		wh(*g>0&&*g<=' ')g++;
+		if(*g==0)Die("unexpected zero");
+		if(*g=='('){
+			g++;
+			dx=parsedec(&g);
+		}ei(*g==')'){
+			g++;
+			dx=parsedec(&g)*tpsz[dt];
+		}
+		if(*g==0)Die("unexpected zero");
+		op=*g;
+		g++;
+		if(*g==0)Die("unexpected zero");
+		if((*g<='z'&&*g>='a')||(*g<='Z'&&*g>='A')){
+			gettype(g,&s,&st);
+			g++;
+			if(*g=='('){
+				g++;
+				sx=parsedec(&g);
+			}ei(*g==')'){
+				g++;
+				sx=parsedec(&g)*tpsz[st];
+			}
+		}ei((*g<='9'&&*g>='0')||*g=='.'||*g=='-'||*g=='%'){
+			s=8;
+			parsenum(&g,&st,&sv);
+		}ei(*g=='\''){
+			s=8;
+			st=TY_INT8;
+			g++;
+			sv.x=sv.c=*g;
+			g++;
+		}ei(*g=='{'){
+			s=8;
+			st=TY_ADDR;
+			sv.p=g+1;
+			sv.x=sv.c=0;
+			g=skipp(g)+1;
+		}else Die("bad arg");
+		if(dt==-1)dt=st;
+		Log("%s %"PRIuPTR" %s %c %s %"PRIuPTR" %s",
+			vrnm[d],dx,tpnm[dt],op,vrnm[s],sx,tpnm[st]);
+		char **sp=0;
+		if(s<8){
+			sp=v+s;
+			getva7(st,sp,sx,&sv);
+		}
+		char **dp=(d<8)?&(v[d]):0;
+		getva7(dt,dp,dx,&dv);
+		if(dt==TY_VARIANT)dt=st;
+		if(st==TY_VARIANT)st=dt;
+		if(dt==TY_VARIANT)Die("Cannot perform operation on two variants.");
+		int skip=0;
+		char *r;
+		int dvn=d;
+		int fdes;
+		int64_t n,d;
+		struct va7 nv;
+		char pbuf[100];
+		switch(op){
+		case '=': //set dest to src
+			setva7(dt,dp,dx,&sv);
+		brase 'z': //swap dest and src
+			setva7(st,sp,sx,&dv);
+			setva7(dt,dp,dx,&sv);
+		brase 'p': //print src to stream given by dest. _ is stdout
+			if(dvn!=VR_VOID&&!isint[dt])Die("dest must be a stream number, as an integer.");
+			if(dvn==VR_VOID)fdes=1;
+			else fdes=dv.c;
+			if(isint[st])sprintf(pbuf,"%"PRId64"\n",sv.c);
+			ei(isptr[st])sprintf(pbuf,"%p\n",sv.p);
+			ei(isreal[st])sprintf(pbuf,"%f\n",sv.x);
+			write(fdes,pbuf,strlen(pbuf));
+		brase 'x': //print src in hex to stream given by dest. _ is stdout
+			if(dvn!=VR_VOID&&!isint[dt])Die("dest must be a stream number, as an integer.");
+			if(dvn==VR_VOID)fdes=1;
+			else fdes=dv.c;
+			if(dt==TY_INT8)sprintf(pbuf,"%02"PRIx8"\n",(uint8_t)sv.c);
+			ei(dt==TY_INT16)
+				sprintf(pbuf,"%04"PRIx16"\n",(uint16_t)sv.c);
+			ei(dt==TY_INT32)
+				sprintf(pbuf,"%08"PRIx32"\n",(uint32_t)sv.c);
+			ei(dt==TY_INT64)sprintf(pbuf,"%016"PRIx64"\n",sv.c);
+			ei(dt<=TY_PTR)sprintf(pbuf,"%p\n",sv.p);
+			else{
+				int64_t n,d;
+				undiv(sv.x,&n,&d);
+				sprintf(pbuf,"%"PRId64"/%"PRId64"\n",n,d);
+			}
+			write(fdes,pbuf,strlen(pbuf));
+		brase 'r': //read in a line from stream given by src and put value in dest
+			if(!isint[st])Die("src must be a stream number, as an integer.");
+			r=s7getinput(sv.c,'\n');
+			if(dt<=TY_INT64)dv.c=strtol(r,0,0);
+			ei(dt==TY_FLOAT||dt==TY_DOUBLE)dv.x=strtod(r,0);
+			else dv.p = r;
+			if(!isptr[dt])free(r);
+			setva7(dt,dp,dx,&dv);
+		brase 'S': //copy N objects from src to dest, if src is an address. (N being the register N of course) otherwise, set N objects in dest to the value of src.
+			r=*dp;
+			getva7(TY_INT64,&v[5],0,&nv);
+			if(isptr[st]){
+				memmove(r,*sp,nv.c*tpsz[dt]);
+			}else{
+				memsetl(r,*sp,tpsz[st],nv.c);
+			}
+		brase 'L': //get number of objects in dest until the value of src is reached. set N to it.
+			nv.c = memlen(*dp,&sv,dt);
+			setva7(TY_INT64,v+5,0,&nv);
+		brase '\\': //undivide src into two consecutive values in dest.
+			if(!isnum[dt])Die("Undivide result must be placed in numeric type.");
+			undiv(sv.x,&n,&d);
+			dv.x=dv.c = n;
+			setva7(dt,dp,dx,&dv);
+			dv.x=dv.c = d;
+			*dp = *dp + tpsz[dt];
+			setva7(dt,dp,dx,&dv);
+			*dp = *dp - tpsz[dt];
+		brase 'R': //read N objects of dest's type into dest, from steem number src.
+			if(!isint[st])Die("Source must be a stream number, as an integer.");
+			getva7(TY_INT64,&v[5],0,&nv);
+			read(sv.c,*dp,tpsz[dt]*nv.c);
+		brase 'W': //write N objects of dest's type from dest, to stream number src..
+			if(!isint[st])Die("Source must be a stream number, as an integer.");
+			getva7(TY_INT64,&v[5],0,&nv);
+			write(sv.c,*dp,tpsz[dt]*nv.c);
+		brase '.': //put src as char, to stream indicated by dest. _ is stdout.
+			if(dvn!=VR_VOID&&!isint[dt])Die("dest must be a stream number, as an integer.");
+			if(dvn==VR_VOID)fdes=1;
+			else fdes = dv.c;
+			write(fdes,&sv.c,1);
+		brase ',': //get char into dest, from stream indicated by src.
+			if(!isint[st])Die("src must be a stream number, as an integer.");
+			{char c;
+			read(sv.c,&c,1);
+			dv.x=dv.c=c;}
+			setva7(dt,dp,dx,&dv);
+		brase '+': //add src to dest.
+			dv.c+=sv.c;
+			dv.x+=sv.x;
+			dv.p+=sv.c;
+			setva7(dt,dp,dx,&dv);
+		brase '-': //subtract src from dest.
+			dv.c-=sv.c;
+			dv.x-=sv.x;
+			dv.p-=sv.c;
+			setva7(dt,dp,dx,&dv);
+		brase '/': //divide dest by src
+			if(sv.c)dv.c/=sv.c;
+			dv.x/=sv.x;
+			if(isptr[st]||isptr[dt])Die("Can't divide pointers.");
+			setva7(dt,dp,dx,&dv);
+		brase '%': //modulo dest by src
+			dv.c%=sv.c;
+			dv.x=fmod(dv.x,sv.x);
+			if(isptr[st]||isptr[dt])Die("Can't modulo pointers.");
+			setva7(dt,dp,dx,&dv);
+		brase '*': //multiply dest by src
+			dv.c*=sv.c;
+			dv.x*=dv.x;
+			if(isptr[st]||isptr[dt])
+				Die("Can't multiply pointers.");
+			setva7(dt,dp,dx,&dv);
+		brase '|': //bitor src into dest
+			dv.c|=sv.c;
+			if(!isint[st]||!isint[dt])
+				Die("Can only bitor integers.");
+			setva7(dt,dp,dx,&dv);
+		brase '&': //bitand src with dest
+			dv.c&=sv.c;
+			if(!isint[st]||!isint[dt])
+				Die("Can only bitand integers.");
+			setva7(dt,dp,dx,&dv);
+		brase '^': //raise dest to src power
+			dv.c=pow(dv.c,sv.x);
+			dv.x=pow(dv.x,sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only exponent numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase 'c': //multiply dest by cos src
+			dv.c=dv.x=dv.x*cos(sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only cosine numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase 's': //multiply dest by sin src
+			dv.c=dv.x=dv.x*sin(sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only sine numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase '_': //multiply dest by log src
+			dv.c=dv.x=dv.x*log(sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only logarithm numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase 't': //multiply dest by tan src
+			dv.c=dv.x=dv.x*tan(sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only tangent numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase 'a': //set dest to atan(dest/src)
+			dv.c=dv.x=atan2(dv.x,sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only arctangent numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase 'e': //multiply dest by e^src
+			dv.c=dv.x=dv.x*exp(sv.x);
+			if(isptr[st]||isptr[dt])
+				Die("Can only exponent numbers.");
+			setva7(dt,dp,dx,&dv);
+		brase 'X': //xor dest with src
+			dv.c^=sv.c;
+			if(!isint[st]||!isint[dt])
+				Die("Can only bitxor integers.");
+			setva7(dt,dp,dx,&dv);
+		brase 'M': //set dest to point to src newly allocated bytes
+			if(isptr[st])
+				Die("Non number malloc size.");
+			*dp=malloc(sv.c*tpsz[dt]);
+		brase 'N': //resize allocated memory at dest to src bytes.
+			if(isptr[st])
+				Die("Non number realloc size.");
+			*dp=realloc(*dp,sv.c*tpsz[dt]);
+		brase '>': //move dest src objects forward
+			if(isptr[st])
+				Die("Non number move size.");
+			*dp=*dp+(sv.c*tpsz[dt]);
+		brase ':': //set dest to src and move dest to next object
+			setva7(dt,dp,dx,&sv);
+			*dp=*dp+tpsz[dt];
+		brase ';': // move to previous object and set dest to src
+			*dp=*dp-tpsz[dt];
+			setva7(dt,dp,dx,&sv);
+		brase '<': //move dest src objects backward
+			if(isptr[st])
+				Die("Non number move size.");
+			*dp=*dp-(sv.c*tpsz[dt]);
+		brase 'F': //free memory at dest
+			free(*dp);
+			*dp=globa7.data;
+		brase '~': //skip to # if dest != src
+			if(dt<=TY_INT64)skip=(dv.c!=sv.c);
+			ei(dt<=TY_PTR)skip=(dv.p!=sv.p);
+			else skip=(dv.x!=sv.x);
+		brase 'g': //skip to # if dest <= src
+			if(dt<=TY_INT64)skip=(dv.c<=sv.c);
+			ei(dt<=TY_PTR)skip=(dv.p<=sv.p);
+			else skip=(dv.x<=sv.x);
+		brase 'l': //skip to # if dest > src
+			if(dt<=TY_INT64)skip=(dv.c>sv.c);
+			ei(dt<=TY_PTR)skip=(dv.p>sv.p);
+			else skip=(dv.x>=sv.x);
+		brase '!': //skip to # if dest == src
+			if(dt<=TY_INT64)skip=(dv.c==sv.c);
+			ei(dt<=TY_PTR)skip=(dv.p==sv.p);
+			else skip=(dv.x==sv.x);
+		brase 'K': //save current place into dest
+			if(dt==TY_PTR||dt==TY_ADDR)dv.p=g;
+			else Die("Can only save label to a pointer.");
+		brase '@': //get variable of name src into dest
+			if(st==TY_ADDR)dv=ge7var(sv.p);
+			else Die("Variable name must be string");
+			setva7(dt,dp,dx,&dv);
+		brase '$': //set variable of name src from dest
+			if(st==TY_ADDR)se7var(sv.p,dv);
+			else Die("Variable name must be string");
+		brase 'G': //goto place saved in src
+			if(st==TY_PTR||st==TY_ADDR)g=sv.p;
+			else Die("Can only jump to a pointer.");
+		brase 'C': //call dest as a void(*)(char*) with src as parameter.
+			un(dt==TY_PTR||dt==TY_ADDR)Die("Can only call a pointer.");
+			((void(*)(char*))dv.p)(sv.p);
+		brault: Die("Bad Operator");
+		}
+		if(skip){
+			Log("condition false, skipping");
+			wh(*g&&*g!='#')g++;
+			if(*g)g++;
+		}
+	}
+	hell:
+	Log("end");
+}
+
+int scrip7rc(FILE *in){
+	char *cmd=s7getcmd(in);
+	if(*cmd==0){free(cmd);return 0;}
+	scrip7(cmd);
+	if(s7freeflag)free(cmd);
+	return 1;
+}
+
+
+void scrip7f(FILE *f){
+	wh(!feof(f))scrip7rc(f);
+}
+
+void scrip7cli(FILE *in){
+	wh(!feof(in)&&scrip7rc(in));
+}
+
+#if !defined(NOS7MAIN)
+__attribute__((weak)) int main(int argc,char **argv){
+	int i=argc,cli=1;
+	wh(i>1){
+		i--;
+		FILE *f=fopen(argv[i],"r");
+		if(!f){
+			if(strchr(argv[i],'d'))s7logflag=1;
+			if(strchr(argv[i],'f'))s7freeflag=1;
+			if(strchr(argv[i],'c'))cli=1;
+			continue;
+		}
+		cli=0;
+		scrip7f(f);
+		fclose(f);
+	}
+	if(cli)scrip7cli(stdin);
+	return 0;
+}
+#endif