#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 >s7docs.txt <<END Author: Oren Watson Scrip77 hopefully getting stabler release 2015-08-22 You can extract and compile the full distribution simply by running this file as a shell script like sh scrip77.c This produces the interpreter scrip7, the library scrip7.o, and the documentation docs.txt. To include, include scrip7.h. If your platform does not support weak symbols, you will also need to define NOS7MAIN when including it. Language Description: A scrip77 program or script consists of statements and labels. Labels are #text# between hashes. When a program is loaded, its labels' locations are stored in variables named with the text. 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" pseudo 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. Only lowercase letters are allowed. 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. escapes within string are: \@,\A thru \_ are used for character 0 to 31. also c escapes \n\t\v\a\b\e and \r can be used. 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 "^ \+brase '.*': //\|^ \+//DOCS" $0 | sed \ -e 's#.*brase '\''[\]\?#α#' -e 's#'\'': //#β #' -e 's#dest#α#' \ -e 's#src#β#' -e 's#.*\//DOCS##' >>s7docs.txt fi exit 0 */ //BEGINHEADER #include "stdio.h" #include "stdint.h" extern int s7logflag,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 knz const #define let(x,y) typeof(y) x = y knz sut va7 nu77 = {0,0,0}; knz sut va7 one77 = {1,1,"one"}; sut scrip7var{sut scrip7var*tbl[32];sut va7 val;}; sut scrip7var *news7v(){ return calloc(sizeof(sut scrip7var),0); }; void se7var(char *n,sut va7 val){ sut scrip7var**q=&(globa7.vars); loop{ if(!*q)*q=news7v(); if(!*n||*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=news7v(); 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,args...) \ {if(s7errflag)fprintf(stderr,"%ld:"mesg"\n",g-code,##args);goto hell;}wh(0) int isnu77(sut va7 v,int t){ if(isint[t])return v.c==0; if(isptr[t])return v.p==0; if(isreal[t])return v.x==0; return 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, const 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 int64_t parsedec(char **gp){ int64_t i=0; wh(**gp>='0'&&**gp<='9'){ i=i*10+*(*gp)++-'0'; } return i; } char bkslshtochr(char c){ switch(c){ case'@'...'_':return c-'@'; case'a':return'\a'; case'b':return'\b'; case'd':return'\177'; case'e':return'\033'; case'f':return'\f'; case'n':return'\n'; case'r':return'\r'; case't':return'\t'; case'v':return'\v'; default:return c; } } static void parsestr(char **gp,int *stp,struct va7 *sp){ char *s=malloc(8); int z=8,i=0; char *g=*gp; loop{ if(i==z)s=realloc(s,z*=2); g++; if(*g=='"')break; if(*g=='\\'){ g++; s[i]=bkslshtochr(*g); }else{ s[i]=*g; } i++; } s[i]=0; g++; *gp=g; *stp=TY_PTR; sp->p=s; sp->x=i; sp->c=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){ if(*g!='#'){g++;continue;} char *start=++g; while(*g&&*g!='#')g++; if(!*g)Die("zero char encountered in label"); g++; dv.p=g; dv.c=g-start-1; dv.c=dv.c; se7var(start,dv); } g=code; wh(*g){ if(*g>0&&*g<=' '){g++;continue;} if(*g=='#'){ g++; while(*g!='#')g++; g++; } if(*g=='`'){Log("backtick is early exit");goto hell;} 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; parsestr(&g,&st,&sv); }else Die("bad arg %c",*g); 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 use two variants in a command."); int skip=0; char *r; int dvn=d; int fdes; int64_t n,d; struct va7 nv; char pbuf[100]; switch(op){ brase '=': //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 filedes, an integer."); if(dvn==VR_VOID)fdes=1; else fdes=dv.c; if(isint[st])sprintf(pbuf,"%"PRId64"\n",sv.c); ei(isptr[st]){write(fdes,sv.p,strlen(sv.p));break;} 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, where //DOCS _ is used as stdout or 1. if(dvn!=VR_VOID&&!isint[dt]) Die("dest must be a fildes, 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 sprintf(pbuf,"%e\n",sv.x); write(fdes,pbuf,strlen(pbuf)); brase 'r': //read in a line from stream given by src, //DOCS and put value in dest according to dest's type if(!isint[st]) Die("src must be a fildes, 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 a ptr. //DOCS (N being the register N of course) otherwise, //DOCS 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 //DOCS 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 dest must be 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 of dest's type into dest, from fd src. if(!isint[st]) Die("src must be a fildes, as an integer."); getva7(TY_INT64,&v[5],0,&nv); read(sv.c,*dp,tpsz[dt]*nv.c); brase 'W': //write N of dest's type from dest, to fd src.. if(!isint[st]) Die("Source must be a fildes, as an integer."); getva7(TY_INT64,&v[5],0,&nv); write(sv.c,*dp,tpsz[dt]*nv.c); brase '.': //put src as char, to fd dest. _ is stdout. if(dvn!=VR_VOID&&!isint[dt]) Die("dest must be a fildes, 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 fildes, 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 'g': //set dest = 0 if dest <= src, else 1 if(dt<=TY_INT64)skip=(dv.c<=sv.c); ei(dt<=TY_PTR)skip=(dv.p<=sv.p); else skip=(dv.x<=sv.x); if(skip)setva7(dt,dp,dx,&nu77); else setva7(dt,dp,dx,&one77); brase 'l': //set dest = 0 if dest > src, else 1 if(dt<=TY_INT64)skip=(dv.c>sv.c); ei(dt<=TY_PTR)skip=(dv.p>sv.p); else skip=(dv.x>=sv.x); if(skip)setva7(dt,dp,dx,&nu77); else setva7(dt,dp,dx,&one77); brase '~': //set dest = 0 if dest == src, else 1 if(dt<=TY_INT64)skip=(dv.c==sv.c); ei(dt<=TY_PTR)skip=(dv.p==sv.p); else skip=(dv.x==sv.x); if(skip)setva7(dt,dp,dx,&nu77); else setva7(dt,dp,dx,&one77); 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,&sv); brase '$': //set variable of name src from dest if(st==TY_ADDR)se7var(sv.p,dv); else Die("Variable name must be string"); brase 'j': //goto place saved in src if(st==TY_PTR||st==TY_ADDR)g=sv.p; else Die("Can only jump to a pointer."); brase 'J': //goto place saved in variable named src if(st==TY_PTR||st==TY_ADDR)g=ge7var(sv.p).p; else Die("Can only jump to a pointer."); brase 'i': //goto place saved in src if dest is not zero if(isnu77(dv,dt))break; if(st==TY_PTR||st==TY_ADDR)g=sv.p; else Die("Can only jump to a pointer."); brase 'I': //goto place in variable src if dest is not zero if(isnu77(dv,dt))break; if(st==TY_PTR||st==TY_ADDR)g=ge7var(sv.p).p; else Die("Can only jump to a pointer."); brase 'C': //call dest as a void(*)(char*) with src as arg. un(dt==TY_PTR||dt==TY_ADDR) Die("Can only call a pointer."); ((void(*)(char*))dv.p)(sv.p); brault: Die("Bad Operator"); } } 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=1,cli=1; wh(i<argc){ FILE *f=fopen(argv[i],"r"); if(!f){ if(strchr(argv[i],'t'))s7logflag=1; if(strchr(argv[i],'c'))cli=1; if(strchr(argv[i],'d')){ i++; if(i<argc)scrip7(argv[i]); } if(strchr(argv[i],'e')){ cli=0; i++; if(i<argc)scrip7(argv[i]); } i++; continue; } cli=0; scrip7f(f); fclose(f); i++; } if(cli)scrip7cli(stdin); return 0; } #endif