home *** CD-ROM | disk | FTP | other *** search
- /* bsint.c -- main part of interpretor.
- */
-
- #include "bsdefs.h"
-
- int (*_null[])() = { 0,0 };
-
- struct line llist[NUMLINES] = {
- 0, _null, "",
- MAXLN, _null, ""
- };
-
- struct line *lastline = &llist[1];
- struct line *Thisline = &llist[0];
- int Thisp = 0;
-
- struct dictnode vlist[VLSIZ];
-
-
-
- /* gtok() -- read a token using input(). Tokens are delimited by whitespace.
- * When '\n' is found, "\n" is returned.
- * For EOF or control characters (not '\n' or '\t') 0 is returned.
- */
- char *gtok()
- {
- static char token[20];
- register char *s,c;
-
- s = &token[0];
- loop: c=input();
- if(c==' ' || c=='\t') goto loop;
- else if(c == '\n') return("\n");
- else if(c==EOF || iscntrl(c)) return(0);
- else {
- *s++ = c;
- for(c=input(); c>' ' && c<='~'; c=input())
- *s++ = c;
- unput(c);
- *s++ = '\0';
- return(token);
- }
- }
-
- /* insline(num) -- insert num into llist with insertion sort style.
- * Replaces old lines if already in list.
- */
- struct line *insline(num)
- int num;
- {
- struct line *p,*p2,*p3;
- struct dictnode *vp;
- struct dictnode *gvadr();
- char s[12];
-
- if(lastline == LASTLINE) return(0);
- for(p=lastline; p->num > num; p--)
- /* null */ ;
- if(p->num == num) {
- if(p->code != 0) { free(p->code); p->code = 0; }
- if(p->text != 0) { free(p->text); p->text = 0; }
- }
- else { /* p->num < num */
- ++p;
- p2=lastline;
- p3= ++lastline;
- while(p2 >= p) {
- p3->num = p2->num;
- p3->code = p2->code;
- p3->text = p2->text;
- p2--;
- p3--;
- }
- p->num = num;
- p->text = p->code = 0;
- }
- sprintf(s,"LN%d",num);
- vp = gvadr(s,T_LBL);
- vp->val.lval.codelist = p;
- vp->val.lval.place = 0;
- return(p);
- }
-
-
-
- /* gladr() -- get address of llist entry, given the line number.
- */
- struct line *gladr(lnum)
- unsigned lnum;
- {
- register struct line *q;
- register int num;
-
- num = lnum;
- for(q= &llist[0]; q->num!=num && q->num!=MAXLN ; q++)
- ;
- if(q->num == MAXLN) return(0);
- /* else */
- if(q->code==0 && q->text==0) return(0); /* fake line */
- /* else */
- return(q); /* found place */
- }
-
- /* gllentry() -- Given an address for a code list, return llist entry which
- * has matching code list address.
- */
- struct line *gllentry(l)
- int **l;
- {
- register int llp;
-
- for(llp=0; llist[llp].num != MAXLN; llp++)
- if(llist[llp].code == l)
- return(&llist[llp]);
-
- return(0); /* such an entry not found */
- }
-
- /* glist() -- read rest of line as a code list, return the corresponding
- * code list.
- */
- int **glist()
- {
- register char *s;
- int (*codestring[100])();
- int lp,(**l)();
- register int i;
-
- lp=0;
- for(s=gtok(); s!=0 && strcmp(s,"\n")!=0; s=gtok()) {
- for(i=0; wlist[i].name!=0; i++)
- if(strcmp(wlist[i].name,s)==0)
- break;
- if(wlist[i].name == 0) {
- fprintf(stderr,"unknown name %s\n",s);
- exit(1);
- }
- if(wlist[i].funct == 0) {
- fprintf(stderr,"glist: no function for %s at %o\n",s,&wlist[i]);
- exit(1);
- }
- codestring[lp++] = wlist[i].funct;
- lp = (*wlist[i].funct)(codestring,lp);
- }
- codestring[lp++] = 0;
- l = myalloc(lp*2+1);
- blcpy(l,codestring,lp*2);
- return(l);
- }
-
- /* rprg -- read in a bunch of lines, put them in program buffer.
- */
- rprg()
- {
- char *s;
- int ln;
- struct line *pl;
-
- for(s=gtok(); s!=0; s=gtok()) {
- if(strcmp(s,"line") == 0) {
- s=gtok();
- ln=atoi(s);
- pl=insline(ln);
- if(pl == 0) {
- fprintf(stderr,"out of room for program\n");
- exit(1);
- }
- s=myalloc(strlen(ibuf)+1);
- strcpy(s,ibuf);
- pl->text = s;
- pl->code = glist();
- }
- else {
- fprintf(stderr,"syntax error, no line number: %s\n",ibuf);
- exit(1);
- }
- }
- }
-
-
- interp(l,start)
- int (*l[])(),start;
- {
- int lp;
- for(lp=start+1; l[lp-1]!=0; lp++)
- lp = (*l[lp-1])(l,lp);
- return(lp);
- }
-
- /* runit() -- run the program in llist. arg- address of place to start at.
- *
- * to do a goto type action, set Thisline to llist entry PREVIOUS to
- * desired place. Set Thisp to desired index. To cause it to happen,
- * place a 0 in the code list where interp() will see it at the right
- * time.
- *
- * All this will cause runit() to run correctly, and automatically take
- * care of updating the line number pointers (Thisline and Thisp).
- */
- runit()
- {
- int ourthisp;
-
- ourthisp = Thisp;
- Thisp = 0;
- while(Thisline < lastline) {
- interp((Thisline->code),ourthisp);
- ++Thisline;
- ourthisp = Thisp;
- Thisp = 0;
- }
- }
-
- int dbg = 0; /* debugging flag. */
- main(argc,argv)
- int argc;
- char **argv;
- {
- int i,j;
- int (**l)();
-
- if(argc >= 2) {
- if((bsin=fopen(argv[1],"r")) == NULL) {
- fprintf(stderr,"main: could not open input file %s\n",argv[1]);
- exit(1);
- }
- }
- if(argc > 2)
- dbg = 1; /* "int file <anything>" sets debugging */
-
- /* Read the program (on file bsin) and compile it to the executable code. */
- rdlin(bsin);
- status = M_COMPILE;
- rprg();
- if(bsin != stdin)
- fclose(bsin);
- bsin = stdin; /* make sure it is stdin for execution */
- iptr = 0;
- ibuf[iptr] = 0; /* make the input buffer empty. */
-
- /* Scan through the compiled code, make sure things point to where
- * they are supposed be pointing to, etc.
- */
- status = M_FIXUP;
- Thisline = &llist[0];
- while(Thisline < lastline) {
- interp((Thisline->code),0);
- ++Thisline;
- }
-
- status = M_EXECUTE;
- dlp = 0; /* set it back to beginning of list */
- Thisline = &llist[0];
- Thisp = 0;
- runit();
- }
-