[mod.sources] A BASIC interpretor

sources-request@genrad.UUCP (07/30/85)

Mod.sources:  Volume 2, Issue 22
Submitted by: ukma!david (David Herron)

About a month ago I posted a response saying that I had a BASIC
interpretor I'd written (that it wasn't a working interpretor)
and that I'd post it if anybody wanted to debug it.  Well, something
in the offer must have sounded tempting since I got about 30 replies
all saying yes.  So here it is.

Let me give a little bit of the history first.  About 3 years ago
I was taking a course entitled something like "Minicomputer Management".
Which, it was basically a smoke screen behind which to introduce students
to the wonderful world on Unix.  (On 2 PDP-11/23's (not 23+) running
Version 7 (now 2.9BSD)).  Two weeks before the end of class we were
assigned to write a BASIC interpretor.  Nobody else finished it
but me, but it took me a year and a half to get a working version.
(I spent a lot of that time playing with different ideas for parsing).

I had it working.  But it was in two parts.  A parser which turned
the BASIC programs into a stack based intermediate language, and
the interpretor for the intermediate language.  There was no immediate
type in program and run it capability.  You had to run ed, write the
file, save it, convert it, THEN run it.  I really wanted to have
the two parts in one piece, so I started improving it.

Unfortunately, about half way through improving the program I got
hired for my current job.  (One of those student slave labor deals).
And I never finished it.  I don't know the status of the code I am 
sending.  It may be code from the first iteration, or it may be 
from the current (now a year old) iteration.

There are three directories under here, as follows:

	bs2	This has sources which will make the two part
		translator/interpretor I described above.  But I
		don't know if the files will compile into a runnable
		program or not.
	bstest	Some basic programs and the output produced by the
		translator.  It should help you in understanding
		what the intermediate code should look like.
	newbs	This is where I was working on the new interpretor.
		I was trying to make bsgram.y produce EITHER
		the ascii intermediate file, or an incore version
		that could be run immediately.  I may also have
		been trying to clean up the grammar some.

The intermediate language is intended to be much like FORTH.  It is not
a full FORTH of course, butis much simplified.  I picked this route
partly as a path of least resistance, and partly to try out an
idea.   (I had a good description of how to build a FORTH, if you are
interested look for the article in 1981 or 1982 of the IEEE Computer
magazine).  Around that time I had an inspiration on a better way to
implement languages.  I had recieved a strong lesson in the amount of
work that was needed to implement a language on a new piece of
hardware.  My idea is similar to the P-code method of implementing
Pascal. Design a machine-independant intermediate language which is
simple yet provides facilities needed by a language interpretor.  You
would save a lot of time in porting languages to new hardware this way,
especially if the intermediate language was easy to interpret.  I
already knew that RPN was easy to interpret having worked with one
previously.   And I could show myself that it was easy to convert an
expression tree to an RPN expression.  So this looked good.

The idealistic form of this interpretor is simply an array of pointers
to procedures which are called in order.  In actuality arguments to the
routines are interspersed with the pointers.   The comments in the code
try to make this clear.  This is (currently) the only documentation,
and in some cases the code and the comments may not agree.  Remember
that this is a work in progress that was never completed.  (But now
that I'm thinking about it again, I see so many better ways of doing
things,  I  may just give it another go.)

A quick word about efficiency and I'll get off this subject.  My
standard quickie benchmark is the nearest equivalent to:


		 10 FOR I = 1 TO 10000 
		 20 NEXT I


I ran this on both a TRS-80 Color Computer (it was handy) with floating
point arithmetic, and my interpretor running on a LSI-11/23 with
integer arithmetic.   They both took about 15  seconds to run this.
As a first attempt I am pleased to have showed so well against seasoned
professionals.  On the other hand, considering the differences in data
types, and CPU speeds, should have given a two to three times
difference.   (In the favor of the LSI-11).  There is one GLARING thing
I should do when (if) I do this over.   I should not have the
interpretor doing procedure calls for each instruction, but should have
the main loop be a large switch statement.  This was an early design
decision that I now regret.  I went with using the procedure calls
because it seemed that I would end up with a less monolithic system.

sources-request@genrad.UUCP (07/30/85)

Mod.sources:  Volume 2, Issue 23
Submitted by: ukma!david (David Herron, NPR)


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	newbs/act.c
#	newbs/action.c
#	newbs/action.c.new
#	newbs/bsint.c
#	newbs/errors.c
#	newbs/mkrbop.c
#	newbs/operat.c.new
# This archive created: Tue Jul 30 13:02:14 1985
export PATH; PATH=/bin:$PATH
if test ! -d 'newbs'
then
	echo shar: creating directory "'newbs'"
	mkdir 'newbs'
fi
echo shar: extracting "'newbs/act.c'" '(14296 characters)'
if test -f 'newbs/act.c'
then
	echo shar: will not over-write existing file "'newbs/act.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/act.c'
/* action.c -- "action" routines for interpretor.  These are the base-level
 *	routines, pointed to by the code-list.
 */

#include "bsdefs.h"

int status = 0;

/* M_COMPILE:
 *	x print x   --to--   x,_print,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	output: "string\n"
 */
_print(l,p)
int (*l[])(),p;
{
    union value s1;
    switch(status&XMODE) {
	case M_EXECUTE:
	    s1 = pop();
	    printf("%s",s1.sval);
	    if(s1.sval != 0) free(s1.sval);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default:
	    STerror("print");
    }
}

/* M_COMPILE:
 *	x rlabel name goto x     --to--    x,rlabel,lval,_goto,0,x
 *	(the 0 is for the benefit of interp())
 * M_FIXUP: nothing.
 * any other mode:
 *	stack: lval,x    --to--    x
 *	other: Thisline = lval.lval.codelist;
 *	       Thisp = lval.lval.place;
 */
_goto(l,p) int (*l[])(),p;
{
    union value lval;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE: l[p] = 0;
#endif
	case M_FIXUP: return(++p);
	default:
	    lval = pop();
	    if(lval.lval.codelist == 0) ULerror(l,p);
	    Thisline = lval.lval.codelist;
	    Thisline--;
	    Thisp = lval.lval.place;
if(dbg) printf("_goto:EXEC:to:llent:%o:pl:%d:num:%u\n",lval.lval.codelist,
	lval.lval.place,lval.lval.codelist->num);
	    return(p);
    }
}

/* M_COMPILE:
 *	x dlabel name x    --to--    x,_dlabel,&vlist entry,x
 * M_FIXUP:
 *	Make vlist entry for "name" point to current place.
 */
_dlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;
    char *s;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    s=gtok();
	    vp=gvadr(s,T_LBL);
	    l[p++] = vp;
	    return(p);
#endif
	case M_FIXUP:
	    vp=l[p++];
	    vp->val.lval.codelist = (int **)gllentry(l);
	    vp->val.lval.place = p;
	    return(p);
	default: return(++p);
    }
}

/* M_COMPILE:
 *	x rlabel name x    --to--     x,rlabel,&vlist entry,x
 * any other mode:
 *	push(vp->val)    (i.e.  pointer to location of label)
 */
_rlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;
    char *s;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    s=gtok();
	    vp=gvadr(s,T_LBL);
	    l[p++] = vp;
	    return(p);
#endif
	case M_FIXUP: return(++p);
	default:
	    vp = l[p++];
if(dbg) printf("_rlabel:M_EXECUTE:name:%s:llent:%o:place:%d\n",vp->name,
	vp->val.lval.codelist,vp->val.lval.place);
	    push(vp->val);
	    return(p);
    }
}

/* M_COMPILE:
 *	x rlabel name goto x    --to--    x,_rlabel,lval,_gosub,0,x
 *
 * M_EXECUTE:
 *	stack: lval,x   --to--   x
 *	other: saves current place (on stack) and jumps to lval.
 */
_gosub(l,p) int(*l[])(),p;
{
    union value here,there;
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP:
	    l[p++] = 0;
	    return(p);
	case M_EXECUTE:
	    there = pop();
	    here.lval.codelist = gllentry(l);
	    here.lval.place = p+1;
if(dbg) printf("_gosub:EXEC:here.l:%o:here.pl:%d:there.l:%o:there.pl:%d\n",
	here.lval.codelist,here.lval.place,there.lval.codelist,there.lval.place);
	    push(here);
	    Thisline = there.lval.codelist;
	    Thisline--;
	    Thisp = there.lval.place;
	    return(p);
	default: STerror("gosub");
    }
}

_return(l,p) int(*l[])(),p;
{
    union value loc;
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP:
	    l[p++] = 0;
	    return(p);
	case M_EXECUTE:
	    loc = pop();
	    Thisp = loc.lval.place;
	    Thisline = loc.lval.codelist;
	    Thisline--;
	    return(p);
	default:
	    STerror("return");
    }
}

/* Routines control entering and leaving of loops.
 *
 *	enter -- makes a mark that we have entered a loop, and also records
 *		 branch points for "continue" and "leave".
 *	exitlp -- undoes the mark made by enter.
 *	contin -- branches to "continue" point.
 *	leave -- branches to "leave" point.
 *
 * The following stack structure is used to record these loop markers.
 */

struct loopstack {
	struct label contlb,leavlb;
};

struct loopstack lpstk[20];
int lpstkp = -1;	/* -1 when stack is empty.
			 * always points to CURRENT loop marker.
			 */

/* M_COMPILE:
 *	x rlabel contlb rlabel leavlb enter x
 *--to--
 *	x,_rlabel,contlb,_rlabel,_leavlb,_enter,x
 *
 * M_EXECUTE:
 *	loopstack: x    --to--   <contlb,leavlb>,x
 */
_enter(l,p) int (*l[])(),p;
{
    union value loc;

    if((status&XMODE) == M_EXECUTE) {
	lpstkp++;
	loc = pop();
if(dbg) printf("_enter:EXEC:lpsp:%d:leav.list:%o:leav.pl:%d",lpstkp,
	loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].leavlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].leavlb.place = loc.lval.place;
	loc = pop();
if(dbg) printf(":cont.list:%o:cont.pl:%d\n",loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].contlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].contlb.place = loc.lval.place;
    }
    return(p);
}

/* M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x    --to--   x
 *	other: ensures that lpstkp doesnt get less that -1;
 */
_exitlp(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_EXECUTE)
	if(lpstkp >= 0)
	    lpstkp--;
	else
	    lpstkp = -1;
if(dbg) printf("_exitlp:M_%d:lpstkp:%d\n",status,lpstkp);
    return(p);
}

/* M_COMPILE:
 *	x leave x   --to--   x,_leave,0,x
 *	(the 0 is for the benefit of interp())
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: branches to leavlb.  exitlp takes care of cleaning up stack.
 */
_leave(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    if(lpstkp == -1) /* not inside a loop, ergo cannot leave a loop */
		LVerror(l,p);
	    Thisline = lpstk[lpstkp].leavlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].leavlb.place;
	    return(p);
	default: STerror("leave");
    }
}

/* M_COMPILE:
 *	x contin x    --to--    x,_contin,0,x
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: jumps to contlb.
 */
_contin(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    if(lpstkp == -1) /* cannot continue a loop we're not in */
		CNerror(l,p);
	    Thisline = lpstk[lpstkp].contlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].contlb.place;
	    return(p);
	default: STerror("contin");
    }
}



/* M_COMPILE:
 *	x rlabel name if x    --to--   x,_rlabel,vp,if,0,x
 *	(the 0 is for the benefit for interp()).
 * M_EXECUTE:
 *	stack: loc,bool,x     --to--   x
 *	p: if bool, p=p else p=loc->place
 */
_if(l,p)
int (*l[])(),p;
{
    union value bv,lv;

    switch(status&XMODE) {
	case M_EXECUTE:
	    lv = pop();
	    bv = pop();
if(dbg) printf("_if:M_EXECUTE:lv.pl:%d:p:%d:bv.iv:%D\n",lv.lval.place,
	p,bv.ival);
	    if(bv.ival == (long)0) { /* jump to else part. */
		Thisline = lv.lval.codelist;
		Thisline--;
		Thisp = lv.lval.place;
	    }
	    else p++;	/* skip the 0 so we get to the then part */
	    return(p);
	case M_FIXUP:
	case M_COMPILE: l[p++] = 0; return(p);
	default: STerror("if");
    }
}

/* M_COMPILE:
 *	var name <from>expr <to>expr <step>expr <flag>con 0 dlabel FORx rlabel FORx+1 for
 *--to--
 *	_var,vp,<from>,<to>,<step>,<flag>,0,_dlabel,lblp,_rlabel,lblp2,_for
 *
 * M_EXECUTE:
 *	stack: xitpt,vizd,step,to,from,vp,x
 *	other: if exit conditions are correct, jump to exit point.
 *		vizd is used to hold the data type for vp.  Data types
 *		are always non-zero so the test for the first visit to
 *		the loop is to see if vizd is 0.
 */
_for(l,p) int(*l[])(),p;
{
    union value xitpt,vizd,from,to,step,place;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    xitpt = pop();	vizd = pop();
	    step = pop();	to = pop();
	    from = pop();
if(dbg) printf("_for:EXEC:xit.l:%o:xit.pl:%d:viz.iv:%D:step.iv:%D:to.iv:%D:from.iv:%D:",
	xitpt.lval.codelist,xitpt.lval.place,(long)vizd.ival,(long)step.ival,(long)to.ival,(long)from.ival);
	    if(vizd.ival == 0) { /* first visit to loop */
		place = pop();
if(dbg) printf("first time:var:%s:",place.vpval->name);
		vizd.ival = place.vpval->type_of_value&T_TMASK; /* != 0 */
		place.plval = getplace(place.vpval);
		*(place.plval) = from;	/* since first time, set starting val */
if(dbg) printf("var.pl:%o:var.val:%D:",place.plval,(long)place.plval->ival);
		if(vizd.ival==T_INT && step.ival==0)
			if(to.ival < from.ival)
				step.ival = -1;
			else
				step.ival = 1;
		else if(vizd.ival==T_DBL && step.rval==0)
			if(to.rval < from.rval)
				step.rval = -1;
			else
				step.rval = 1;
	    }
	    else place = pop();
if(dbg) printf("var.place:%o:",place.plval);

	    /* The stack frame is now correctly popped off.
	     * Next, we check if the loop is finished.
	     */

	    if(vizd.ival == T_INT)
		if(step.ival<0 && place.plval->ival<to.ival) goto loop_done;
		else if(step.ival>0 && place.plval->ival>to.ival) goto loop_done;
	    else /* vizd.ival == T_DBL */
		if(step.rval<0 && place.plval->rval<to.rval) goto loop_done;
		else if(step.rval>0 && place.plval->rval>to.rval) goto loop_done;

	    /* Loop is not done yet, push back stack frame. */

if(dbg) printf("loop not done, push everything back\n");
	    push(place);	push(from);	push(to);
	    push(step);		push(vizd);	push(xitpt);
	    return(p);

	/* Come here when the loop is finished. */
loop_done:
if(dbg) printf("loop done, jump to xitpt\n");
	    Thisline = xitpt.lval.codelist;
	    Thisline--;
	    Thisp = xitpt.lval.place;
	    return(p);
	default: STerror("for");
    }
}

/* M_COMPILE:
 *	var name next rlabel FORx go@ dlabel FORx+1
 *--to--
 *	_var,vp,_next,_rlabel,lblp,_go_at,dlabel,lblp2
 *
 * M_EXECUTE:
 *	stack: same as M_EXECUTE in _for.
 *	other: adds step to (control var)->val.
 */
_next(l,p) int(*l[])(),p;
{
    union value vp,xitpt,vizd,step,to,from,place;

    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: return(p);
	case M_EXECUTE:
	    vp = pop();
if(dbg) printf("_next():EXEC:var:%s",vp.vpval->name);
	    vp.plval = getplace(vp.vpval);
if(dbg) printf(":vp.pl:%o:",vp.plval);
	    xitpt = pop();	vizd = pop();	step = pop();
	    to = pop();		from = pop();	place = pop();
if(dbg) printf("pl.pl:%o:from.iv:%D:to.iv:%D:step.iv:%D:viz.iv:%D:",
	place.plval,(long)from.ival,(long)to.ival,(long)step.ival,(long)vizd.ival);
if(dbg) printf("xit.list:%o:xit.pl:%d:xit.num:%u\n",xitpt.lval.codelist,
	xitpt.lval.place,xitpt.lval.codelist->num);
	    if(place.plval != vp.plval) FNerror(l,p);
	    if(vizd.ival == T_INT)
		place.plval->ival += step.ival;
	    else
		place.plval->rval += step.rval;
	    push(place);	push(from);	push(to);	
	    push(step);		push(vizd);	push(xitpt);
	    return(p);
	default: STerror("next");
    }
}

/* variables needed for M_READ. */

struct line *dlist[DLSIZ];
int dlp = 0;
int dlindx = 2;		/* skips <_data,0> */
int dtype;		/* type of last operation. */


/* M_COMPILE:
 *	x data x     --to--    x,_data,0,x     (0 is for interp())
 * M_FIXUP:
 *	allocates a spot in dlist, stores pointer to llist entry for
 *	this line at that spot.
 * M_EXECUTE:
 *	Returns, with p pointing at the zero, making interp() return.
 */
_data(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = 0;
	    return(p);
#endif
	case M_FIXUP:
	    dlist[dlp++] = gllentry(l);
	    p++;
	case M_EXECUTE: return(p);
	default:
	    STerror("data");
    }
}

/* M_COMPILE:  x dsep x   --to--   x,_dsep,0,x
 */
_dsep(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP:
	    l[p++] = 0;
	case M_READ:
	case M_EXECUTE: return(p);
	default: STerror("dsep");
    }
}

/* routines for changing the interpretors state. */

struct statstk {	/* for saving old states */
	int stkp;
	int stat;
} sstk[30];
int sstktop = 0;

/* M_COMPILE:
 *	x pushstate <state> x    --to--    x,pushstate,<state>,x
 * M_FIXUP:
 *	skip <state>
 * any other state:
 *	save old state and stack pointer.
 *	set state to <state>.
 */
_pushstate(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
#endif
	case M_FIXUP: return(++p);
	default:
	    sstk[sstktop].stkp = stackp;
	    sstk[sstktop].stat = status;
	    sstktop++;
	    status = l[p++];
	    return(p);
    }
}
_popstate(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: return(p);
	default:
	    sstktop--;
	    stackp = sstk[sstktop].stkp;
	    status = sstk[sstktop].stat&XMODE;
	    return(p);
    }
}


/* stack maintanence routines.
 */


/* M_COMPILE:
 *	x spop x    --to--    x,_spop,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	other: frees storage used by string (if any).
 */
_spop(l,p) int(*l[])(),p;
{
    union value s;

    switch(status&XMODE) {
	case M_EXECUTE:
	    s=pop();
	    if(s.sval != 0) free(s.sval);
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: return(p);
	default:
	    STerror("spop");
    }
}

/* M_COMPILE:
 *	x pop x    --to--    x,_pop,x
 * M_EXECUTE:
 *	stack: int,x    --to--   x
 */
_pop(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_EXECUTE: pop(); return(p);
	default:
	    STerror("pop");
    }
}

_stop(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_EXECUTE: exit(1);
	default:
	    STerror("stop");
    }
}
_end(l,p) int (*l[])(),p; { return(_stop(l,p)); }


/* operator list for the intermediate language. */
struct wlnode wlist[] = {
	"itoa",_itoa,	"print",_print,	"goto",_goto,	"if",_if,  "rtoa",_rtoa,
	"itor",_itor,	"rtoi",_rtoi,	"gosub",_gosub,  "return",_return,
	"scon",_scon,	"icon",_icon,	"i+",_iadd,	"-",_isub,
	"rcon",_rcon,	"r+",_radd,	"r-",_rsub,
	"i*",_imult,	"i/",_idiv,	"i%",_imod,	",",_comma,
	"r*",_rmult,	"r/",_rdiv,	";",_scolon,
	"i==",_ieq,	"s==",_seq,	"r==",_req,
	"i<>",_ineq,	"r<>",_rneq,	"s<>",_sneq,
	"i<=",_ileq,	"s<=",_sleq,	"r<=",_rleq,
	"i<",_ilt,	"s<",_slt,	"r<",_rlt,
	"i>=",_igeq,	"s>=",_sgeq,	"r>=",_rgeq,
	"i>",_igt,	"s>",_sgt,	"r>",_rgt,
	"or",_or,	"and",_and,	"val",_val,	"not",_not,
	"pop",_pop,	"spop",_spop,
	"stop",_stop,	"end",_end,	"var",_var,	"store",_store,
	"for",_for,	"next",_next,
	"dlabel",_dlabel,	"rlabel",_rlabel,
	"contin",_contin,  "leave",_leave,  "enter",_enter,  "exitlp",_exitlp,
	"data",_data,	"dsep",_dsep,
	"pushstate",_pushstate,		"popstate",_popstate,
    0,0
};

SHAR_EOF
if test 14296 -ne "`wc -c < 'newbs/act.c'`"
then
	echo shar: error transmitting "'newbs/act.c'" '(should have been 14296 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/action.c'" '(12253 characters)'
if test -f 'newbs/action.c'
then
	echo shar: will not over-write existing file "'newbs/action.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/action.c'
/* action.c -- "action" routines for interpretor.  These are the base-level
 *	routines, pointed to by the code-list.
 */

#include "bsdefs.h"

int status = 0;

/* M_COMPILE:
 *	x print x   --to--   x,_print,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	output: "string\n"
 */
_print(l,p)
int (*l[])(),p;
{
    union value s1;
    if((status&XMODE) == M_EXECUTE) {
	    s1 = pop();
	    printf("%s",s1.sval);
	    if(s1.sval != 0) free(s1.sval);
    }
    return(p);
}

/* M_COMPILE:
 *	x rlabel name goto x     --to--    x,rlabel,lval,_goto,0,x
 *	(the 0 is for the benefit of interp())
 * M_FIXUP: nothing.
 * any other mode:
 *	stack: lval,x    --to--    x
 *	other: Thisline = lval.lval.codelist;
 *	       Thisp = lval.lval.place;
 */
_goto(l,p) int (*l[])(),p;
{
    union value lval;

    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    lval = pop();
	    if(lval.lval.codelist == 0) ULerror(l,p);
	    Thisline = lval.lval.codelist;
	    Thisline--;
	    Thisp = lval.lval.place;
if(dbg) printf("_goto:EXEC:to:llent:%o:pl:%d:num:%u\n",lval.lval.codelist,
	lval.lval.place,lval.lval.codelist->num);
	    return(p);
    }
    return(p);
}

/* M_COMPILE:
 *	x dlabel name x    --to--    x,_dlabel,&vlist entry,x
 * M_FIXUP:
 *	Make vlist entry for "name" point to current place.
 */
_dlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;

    if((status&XMODE) == M_FIXUP) {
	    vp=l[p++];
	    vp->val.lval.codelist = (int **)gllentry(l);
	    vp->val.lval.place = p;
	    return(p);
    }
    p++; return(p);	/* skip over the vp in any other mode */
}

/* M_COMPILE:
 *	x rlabel name x    --to--     x,rlabel,&vlist entry,x
 * any other mode:
 *	push(vp->val)    (i.e.  pointer to location of label)
 */
_rlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;

    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    vp = l[p++];
if(dbg) printf("_rlabel:M_EXECUTE:name:%s:llent:%o:place:%d\n",vp->name,
	vp->val.lval.codelist,vp->val.lval.place);
	    push(vp->val);
    }
	    return(p);
}

/* M_COMPILE:
 *	x rlabel name gosub x    --to--    x,_rlabel,lval,_gosub,0,x
 *
 * M_EXECUTE:
 *	stack: lval,x   --to--   x
 *	other: saves current place (on stack) and jumps to lval.
 */
_gosub(l,p) int(*l[])(),p;
{
    union value here,there;
    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    there = pop();
	    here.lval.codelist = gllentry(l);
	    here.lval.place = p+1;
if(dbg) printf("_gosub:EXEC:here.l:%o:here.pl:%d:there.l:%o:there.pl:%d\n",
	here.lval.codelist,here.lval.place,there.lval.codelist,there.lval.place);
	    push(here);
	    Thisline = there.lval.codelist;
	    Thisline--;
	    Thisp = there.lval.place;
    }
	    return(p);
}

_return(l,p) int(*l[])(),p;
{
    union value loc;
    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    loc = pop();
	    Thisp = loc.lval.place;
	    Thisline = loc.lval.codelist;
	    Thisline--;
    }
	    return(p);
}

/* Routines control entering and leaving of loops.
 *
 *	enter -- makes a mark that we have entered a loop, and also records
 *		 branch points for "continue" and "leave".
 *	exitlp -- undoes the mark made by enter.
 *	contin -- branches to "continue" point.
 *	leave -- branches to "leave" point.
 *
 * The following stack structure is used to record these loop markers.
 */

struct loopstack {
	struct label contlb,leavlb;
};

struct loopstack lpstk[20];
int lpstkp = -1;	/* -1 when stack is empty.
			 * always points to CURRENT loop marker.
			 */

/* M_COMPILE:
 *	x rlabel contlb rlabel leavlb enter x
 *--to--
 *	x,_rlabel,contlb,_rlabel,_leavlb,_enter,x
 *
 * M_EXECUTE:
 *	loopstack: x    --to--   <contlb,leavlb>,x
 */
_enter(l,p) int (*l[])(),p;
{
    union value loc;

    if((status&XMODE) == M_EXECUTE) {
	lpstkp++;
	loc = pop();
if(dbg) printf("_enter:EXEC:lpsp:%d:leav.list:%o:leav.pl:%d",lpstkp,
	loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].leavlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].leavlb.place = loc.lval.place;
	loc = pop();
if(dbg) printf(":cont.list:%o:cont.pl:%d\n",loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].contlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].contlb.place = loc.lval.place;
    }
    return(p);
}

/* M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x    --to--   x
 *	other: ensures that lpstkp doesnt get less that -1;
 */
_exitlp(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_EXECUTE)
	if(lpstkp >= 0)
	    lpstkp--;
	else
	    lpstkp = -1;
if(dbg) printf("_exitlp:M_%d:lpstkp:%d\n",status,lpstkp);
    return(p);
}

/* M_COMPILE:
 *	x leave x   --to--   x,_leave,0,x
 *	(the 0 is for the benefit of interp())
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: branches to leavlb.  exitlp takes care of cleaning up stack.
 */
_leave(l,p) int(*l[])(),p;
{
    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    if(lpstkp == -1) /* not inside a loop, ergo cannot leave a loop */
		LVerror(l,p);
	    Thisline = lpstk[lpstkp].leavlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].leavlb.place;
    }
	    return(p);
}

/* M_COMPILE:
 *	x contin x    --to--    x,_contin,0,x
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: jumps to contlb.
 */
_contin(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    if(lpstkp == -1) /* cannot continue a loop we're not in */
		CNerror(l,p);
	    Thisline = lpstk[lpstkp].contlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].contlb.place;
    }
	    return(p);
}



/* M_COMPILE:
 *	x rlabel name if x    --to--   x,_rlabel,vp,if,0,x
 *	(the 0 is for the benefit for interp()).
 * M_EXECUTE:
 *	stack: loc,bool,x     --to--   x
 *	p: if bool, p=p else p=loc->place
 */
_if(l,p)
int (*l[])(),p;
{
    union value bv,lv;

    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    lv = pop();
	    bv = pop();
if(dbg) printf("_if:M_EXECUTE:lv.pl:%d:p:%d:bv.iv:%D\n",lv.lval.place,
	p,bv.ival);
	    if(bv.ival == (long)0) { /* jump to else part. */
		Thisline = lv.lval.codelist;
		Thisline--;
		Thisp = lv.lval.place;
	    }
	    else p++;	/* skip the 0 so we get to the then part */
    }
	    return(p);
}

/* M_COMPILE:
 *	var name <from>expr <to>expr <step>expr <flag>con 0 dlabel FORx rlabel FORx+1 for
 *--to--
 *	_var,vp,<from>,<to>,<step>,<flag>,0,_dlabel,lblp,_rlabel,lblp2,_for
 *
 * M_EXECUTE:
 *	stack: xitpt,vizd,step,to,from,vp,x
 *	other: if exit conditions are correct, jump to exit point.
 *		vizd is used to hold the data type for vp.  Data types
 *		are always non-zero so the test for the first visit to
 *		the loop is to see if vizd is 0.
 */
_for(l,p) int(*l[])(),p;
{
    union value xitpt,vizd,from,to,step,place;

    if((status&XMODE) == M_FIXUP) return(++p);
    if((status&XMODE) == M_EXECUTE) {
	    xitpt = pop();	vizd = pop();
	    step = pop();	to = pop();
	    from = pop();
if(dbg) printf("_for:EXEC:xit.l:%o:xit.pl:%d:viz.iv:%D:step.iv:%D:to.iv:%D:from.iv:%D:",
	xitpt.lval.codelist,xitpt.lval.place,(long)vizd.ival,(long)step.ival,(long)to.ival,(long)from.ival);
	    if(vizd.ival == 0) { /* first visit to loop */
		place = pop();
if(dbg) printf("first time:var:%s:",place.vpval->name);
		vizd.ival = place.vpval->type_of_value&T_TMASK; /* != 0 */
		place.plval = getplace(place.vpval);
		*(place.plval) = from;	/* since first time, set starting val */
		if(vizd.ival == T_INT) { /* if it is an INT, convert to/from/step to INT also */
			to.ival = (long)to.rval;
			from.ival = (long)from.rval;
			step.ival = (long)step.rval;
		}
if(dbg) printf("var.pl:%o:var.val:%D:",place.plval,(long)place.plval->ival);
		if(vizd.ival==T_INT && step.ival==0)
			if(to.ival < from.ival)
				step.ival = -1;
			else
				step.ival = 1;
		else if(vizd.ival==T_DBL && step.rval==0)
			if(to.rval < from.rval)
				step.rval = -1;
			else
				step.rval = 1;
	    }
	    else place = pop();
if(dbg) printf("var.place:%o:",place.plval);

	    /* The stack frame is now correctly popped off.
	     * Next, we check if the loop is finished.
	     */

	    if(vizd.ival == T_INT)
		if(step.ival<0 && place.plval->ival<to.ival) goto loop_done;
		else if(step.ival>0 && place.plval->ival>to.ival) goto loop_done;
	    else /* vizd.ival == T_DBL */
		if(step.rval<0 && place.plval->rval<to.rval) goto loop_done;
		else if(step.rval>0 && place.plval->rval>to.rval) goto loop_done;

	    /* Loop is not done yet, push back stack frame. */

if(dbg) printf("loop not done, push everything back\n");
	    push(place);	push(from);	push(to);
	    push(step);		push(vizd);	push(xitpt);
	    return(++p);	/* skip over the 0 */

	/* Come here when the loop is finished. */
loop_done:
if(dbg) printf("loop done, jump to xitpt\n");
	    Thisline = xitpt.lval.codelist;
	    Thisline--;
	    Thisp = xitpt.lval.place;
	    return(p);	/* hit the 0 */
    }
return(p);
}

/* M_COMPILE:
 *	var name next rlabel FORx goto dlabel FORx+1
 *--to--
 *	_var,vp,_next,_rlabel,lblp,_goto,dlabel,lblp2
 *
 * M_EXECUTE:
 *	stack: same as M_EXECUTE in _for.
 *	other: adds step to (control var)->val.
 */
_next(l,p) int(*l[])(),p;
{
    union value vp,xitpt,vizd,step,to,from,place;

    if((status&XMODE) == M_EXECUTE) {
	    vp = pop();
if(dbg) printf("_next():EXEC:var:%s",vp.vpval->name);
	    vp.plval = getplace(vp.vpval);
if(dbg) printf(":vp.pl:%o:",vp.plval);
	    xitpt = pop();	vizd = pop();	step = pop();
	    to = pop();		from = pop();	place = pop();
if(dbg) printf("pl.pl:%o:from.iv:%D:to.iv:%D:step.iv:%D:viz.iv:%D:",
	place.plval,(long)from.ival,(long)to.ival,(long)step.ival,(long)vizd.ival);
if(dbg) printf("xit.list:%o:xit.pl:%d:xit.num:%u\n",xitpt.lval.codelist,
	xitpt.lval.place,xitpt.lval.codelist->num);
	    if(place.plval != vp.plval) FNerror(l,p);
	    if(vizd.ival == T_INT)
		place.plval->ival += step.ival;
	    else
		place.plval->rval += step.rval;
	    push(place);	push(from);	push(to);	
	    push(step);		push(vizd);	push(xitpt);
	    return(p);
    }
return(p);
}

/* variables needed for M_READ. */

struct line *dlist[DLSIZ];
int dlp = 0;
int dlindx = 2;		/* skips <_data,0> */
int dtype;		/* type of last operation. */


/* M_COMPILE:
 *	x data x     --to--    x,_data,0,x     (0 is for interp())
 * M_FIXUP:
 *	allocates a spot in dlist, stores pointer to llist entry for
 *	this line at that spot.
 * M_EXECUTE:
 *	Returns, with p pointing at the zero, making interp() return.
 */
_data(l,p) int(*l[])(),p;
{
    if((status&XMODE) == M_FIXUP) {
	    dlist[dlp++] = gllentry(l);
	    p++;
    }
    return(p);
}

/* M_COMPILE:  x dsep x   --to--   x,_dsep,0,x
 */
_dsep(l,p) int(*l[])(),p;
{
    if((status&XMODE) == M_FIXUP) ++p;
    return(p);
}

/* routines for changing the interpretors state. */

struct statstk {	/* for saving old states */
	int stkp;
	int stat;
} sstk[30];
int sstktop = 0;

/* M_COMPILE:
 *	x pushstate <state> x    --to--    x,pushstate,<state>,x
 * M_FIXUP:
 *	skip <state>
 * any other state:
 *	save old state and stack pointer.
 *	set state to <state>.
 */
_pushstate(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_FIXUP) return(++p);
	    sstk[sstktop].stkp = stackp;
	    sstk[sstktop].stat = status;
	    sstktop++;
	    status = l[p++];
	    return(p);
}
_popstate(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_FIXUP) return(p); /* want to stay in this mode */
	    sstktop--;
	    stackp = sstk[sstktop].stkp;
	    status = sstk[sstktop].stat&XMODE;
	    return(p);
}


/* stack maintanence routines.
 */


/* M_COMPILE:
 *	x spop x    --to--    x,_spop,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	other: frees storage used by string (if any).
 */
_spop(l,p) int(*l[])(),p;
{
    union value s;

    if((status&XMODE) == M_EXECUTE) {
	    s=pop();
	    if(s.sval != 0) free(s.sval);
    }
    return(p);
}

/* M_COMPILE:
 *	x pop x    --to--    x,_pop,x
 * M_EXECUTE:
 *	stack: int,x    --to--   x
 */
_pop(l,p) int(*l[])(),p;
{
    if((status&XMODE) == M_EXECUTE) pop();
    return(p);
}

_stop(l,p) int(*l[])(),p;
{
    if((status&XMODE) == M_EXECUTE) exit(1);
    return(p);
}
_end(l,p) int (*l[])(),p; { return(_stop(l,p)); }


SHAR_EOF
if test 12253 -ne "`wc -c < 'newbs/action.c'`"
then
	echo shar: error transmitting "'newbs/action.c'" '(should have been 12253 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/action.c.new'" '(14386 characters)'
if test -f 'newbs/action.c.new'
then
	echo shar: will not over-write existing file "'newbs/action.c.new'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/action.c.new'
/* action.c -- "action" routines for interpretor.  These are the base-level
 *	routines, pointed to by the code-list.
 */

#include "bsdefs.h"

int status = 0;

/* M_COMPILE:
 *	x print x   --to--   x,_print,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	output: "string\n"
 */
_print(l,p)
int (*l[])(),p;
{
    union value s1;
    switch(status&XMODE) {
	case M_EXECUTE:
	    s1 = pop();
	    printf("%s",s1.sval);
	    if(s1.sval != 0) free(s1.sval);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default:
	    STerror("print");
    }
}

/* M_COMPILE:
 *	x rlabel name goto x     --to--    x,rlabel,lval,_goto,0,x
 *	(the 0 is for the benefit of interp())
 * M_FIXUP: nothing.
 * any other mode:
 *	stack: lval,x    --to--    x
 *	other: Thisline = lval.lval.codelist;
 *	       Thisp = lval.lval.place;
 */
_goto(l,p) int (*l[])(),p;
{
    union value lval;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE: l[p] = 0;
#endif
	case M_FIXUP: return(++p);
	default:
	    lval = pop();
	    if(lval.lval.codelist == 0) ULerror(l,p);
	    Thisline = lval.lval.codelist;
	    Thisline--;
	    Thisp = lval.lval.place;
if(dbg) printf("_goto:EXEC:to:llent:%o:pl:%d:num:%u\n",lval.lval.codelist,
	lval.lval.place,lval.lval.codelist->num);
	    return(p);
    }
}

/* M_COMPILE:
 *	x dlabel name x    --to--    x,_dlabel,&vlist entry,x
 * M_FIXUP:
 *	Make vlist entry for "name" point to current place.
 */
_dlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;
    char *s;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    s=gtok();
	    vp=gvadr(s,T_LBL);
	    l[p++] = vp;
	    return(p);
#endif
	case M_FIXUP:
	    vp=l[p++];
	    vp->val.lval.codelist = (int **)gllentry(l);
	    vp->val.lval.place = p;
	    return(p);
	default: return(++p);
    }
}

/* M_COMPILE:
 *	x rlabel name x    --to--     x,rlabel,&vlist entry,x
 * any other mode:
 *	push(vp->val)    (i.e.  pointer to location of label)
 */
_rlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;
    char *s;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    s=gtok();
	    vp=gvadr(s,T_LBL);
	    l[p++] = vp;
	    return(p);
#endif
	case M_FIXUP: return(++p);
	default:
	    vp = l[p++];
if(dbg) printf("_rlabel:M_EXECUTE:name:%s:llent:%o:place:%d\n",vp->name,
	vp->val.lval.codelist,vp->val.lval.place);
	    push(vp->val);
	    return(p);
    }
}

/* M_COMPILE:
 *	x rlabel name goto x    --to--    x,_rlabel,lval,_gosub,0,x
 *
 * M_EXECUTE:
 *	stack: lval,x   --to--   x
 *	other: saves current place (on stack) and jumps to lval.
 */
_gosub(l,p) int(*l[])(),p;
{
    union value here,there;
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP:
	    l[p++] = 0;
	    return(p);
	case M_EXECUTE:
	    there = pop();
	    here.lval.codelist = gllentry(l);
	    here.lval.place = p+1;
if(dbg) printf("_gosub:EXEC:here.l:%o:here.pl:%d:there.l:%o:there.pl:%d\n",
      here.lval.codelist,here.lval.place,there.lval.codelist,there.lval.place);
	    push(here);
	    Thisline = there.lval.codelist;
	    Thisline--;
	    Thisp = there.lval.place;
	    return(p);
	default: STerror("gosub");
    }
}

_return(l,p) int(*l[])(),p;
{
    union value loc;
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP:
	    l[p++] = 0;
	    return(p);
	case M_EXECUTE:
	    loc = pop();
	    Thisp = loc.lval.place;
	    Thisline = loc.lval.codelist;
	    Thisline--;
	    return(p);
	default:
	    STerror("return");
    }
}

/* Routines control entering and leaving of loops.
 *
 *	enter -- makes a mark that we have entered a loop, and also records
 *		 branch points for "continue" and "leave".
 *	exitlp -- undoes the mark made by enter.
 *	contin -- branches to "continue" point.
 *	leave -- branches to "leave" point.
 *
 * The following stack structure is used to record these loop markers.
 */

struct loopstack {
	struct label contlb,leavlb;
};

struct loopstack lpstk[20];
int lpstkp = -1;	/* -1 when stack is empty.
			 * always points to CURRENT loop marker.
			 */

/* M_COMPILE:
 *	x rlabel contlb rlabel leavlb enter x
 *--to--
 *	x,_rlabel,contlb,_rlabel,_leavlb,_enter,x
 *
 * M_EXECUTE:
 *	loopstack: x    --to--   <contlb,leavlb>,x
 */
_enter(l,p) int (*l[])(),p;
{
    union value loc;

    if((status&XMODE) == M_EXECUTE) {
	lpstkp++;
	loc = pop();
if(dbg) printf("_enter:EXEC:lpsp:%d:leav.list:%o:leav.pl:%d",lpstkp,
	loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].leavlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].leavlb.place = loc.lval.place;
	loc = pop();
if(dbg) printf(":cont.list:%o:cont.pl:%d\n",loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].contlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].contlb.place = loc.lval.place;
    }
    return(p);
}

/* M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x    --to--   x
 *	other: ensures that lpstkp doesnt get less that -1;
 */
_exitlp(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_EXECUTE)
	if(lpstkp >= 0)
	    lpstkp--;
	else
	    lpstkp = -1;
if(dbg) printf("_exitlp:M_%d:lpstkp:%d\n",status,lpstkp);
    return(p);
}

/* M_COMPILE:
 *	x leave x   --to--   x,_leave,0,x
 *	(the 0 is for the benefit of interp())
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: branches to leavlb.  exitlp takes care of cleaning up stack.
 */
_leave(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    if(lpstkp == -1) /* not inside a loop, ergo cannot leave a loop */
		LVerror(l,p);
	    Thisline = lpstk[lpstkp].leavlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].leavlb.place;
	    return(p);
	default: STerror("leave");
    }
}

/* M_COMPILE:
 *	x contin x    --to--    x,_contin,0,x
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: jumps to contlb.
 */
_contin(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    if(lpstkp == -1) /* cannot continue a loop we're not in */
		CNerror(l,p);
	    Thisline = lpstk[lpstkp].contlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].contlb.place;
	    return(p);
	default: STerror("contin");
    }
}



/* M_COMPILE:
 *	x rlabel name if x    --to--   x,_rlabel,vp,if,0,x
 *	(the 0 is for the benefit for interp()).
 * M_EXECUTE:
 *	stack: loc,bool,x     --to--   x
 *	p: if bool, p=p else p=loc->place
 */
_if(l,p)
int (*l[])(),p;
{
    union value bv,lv;

    switch(status&XMODE) {
	case M_EXECUTE:
	    lv = pop();
	    bv = pop();
if(dbg) printf("_if:M_EXECUTE:lv.pl:%d:p:%d:bv.iv:%D\n",lv.lval.place,
	p,bv.ival);
	    if(bv.ival == (long)0) { /* jump to else part. */
		Thisline = lv.lval.codelist;
		Thisline--;
		Thisp = lv.lval.place;
	    }
	    else p++;	/* skip the 0 so we get to the then part */
	    return(p);
	case M_FIXUP:
	case M_COMPILE: l[p++] = 0; return(p);
	default: STerror("if");
    }
}

/* M_COMPILE:
 *	var name <from>expr <to>expr <step>expr <flag>con 0 dlabel FORx rlabel FORx+1 for
 *--to--
 *	_var,vp,<from>,<to>,<step>,<flag>,0,_dlabel,lblp,_rlabel,lblp2,_for
 *
 * M_EXECUTE:
 *	stack: xitpt,vizd,step,to,from,vp,x
 *	other: if exit conditions are correct, jump to exit point.
 *		vizd is used to hold the data type for vp.  Data types
 *		are always non-zero so the test for the first visit to
 *		the loop is to see if vizd is 0.
 */
_for(l,p) int(*l[])(),p;
{
    union value xitpt,vizd,from,to,step,place;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    xitpt = pop();
	    vizd = pop();
	    step = pop();
 	    to = pop();
	    from = pop();
if(dbg)
printf("_for:EXEC:xit.l:%o:xit.pl:%d:viz.iv:%D:step.iv:%D:to.iv:%D:from.iv:%D:",
xitpt.lval.codelist,xitpt.lval.place,(long)vizd.ival,(long)step.ival,
(long)to.ival,(long)from.ival);
	    if(vizd.ival == 0) { /* first visit to loop */
		place = pop();
if(dbg) printf("first time:var:%s:",place.vpval->name);
		vizd.ival = place.vpval->type_of_value&T_TMASK; /* != 0 */
		place.plval = getplace(place.vpval);
		*(place.plval) = from;	/* since first time, set starting val */
if(dbg) printf("var.pl:%o:var.val:%D:",place.plval,(long)place.plval->ival);
		if(vizd.ival==T_INT && step.ival==0)
			if(to.ival < from.ival)
				step.ival = -1;
			else
				step.ival = 1;
		else if(vizd.ival==T_DBL && step.rval==0)
			if(to.rval < from.rval)
				step.rval = -1;
			else
				step.rval = 1;
	    }
	    else 
		place = pop();
if(dbg) printf("var.place:%o:",place.plval);

	    /* The stack frame is now correctly popped off.
	     * Next, we check if the loop is finished.
	     */

	    if(vizd.ival == T_INT)
		if(step.ival<0 && place.plval->ival<to.ival) 
			goto loop_done;
		else if(step.ival>0 && place.plval->ival>to.ival) 
			goto loop_done;
	    else /* vizd.ival == T_DBL */
		if(step.rval<0 && place.plval->rval<to.rval) 
			goto loop_done;
		else if(step.rval>0 && place.plval->rval>to.rval) 
			goto loop_done;

	    /* Loop is not done yet, push back stack frame. */

if(dbg) printf("loop not done, push everything back\n");
	    push(place);
	    push(from);
	    push(to);
	    push(step);
    	    push(vizd);
	    push(xitpt);
	    return(p);

	default: STerror("for");
    }


	 /* Come here when the loop is finished. */

loop_done:
if(dbg) printf("loop done, jump to xitpt\n");
    Thisline = xitpt.lval.codelist;
    Thisline--;
    Thisp = xitpt.lval.place;
    return(p);
}

/* M_COMPILE:
 *	var name next rlabel FORx go@ dlabel FORx+1
 *--to--
 *	_var,vp,_next,_rlabel,lblp,_go_at,dlabel,lblp2
 *
 * M_EXECUTE:
 *	stack: same as M_EXECUTE in _for.
 *	other: adds step to (control var)->val.
 */
_next(l,p) int(*l[])(),p;
{
    union value vp,xitpt,vizd,step,to,from,place;

    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: return(p);
	case M_EXECUTE:
	    vp = pop();
if(dbg) printf("_next():EXEC:var:%s",vp.vpval->name);
	    vp.plval = getplace(vp.vpval);
if(dbg) printf(":vp.pl:%o:",vp.plval);
	    xitpt = pop();
	    vizd = pop();
	    step = pop();
	    to = pop();
	    from = pop();
	    place = pop();
if(dbg) printf("pl.pl:%o:from.iv:%D:to.iv:%D:step.iv:%D:viz.iv:%D:",
place.plval,(long)from.ival,(long)to.ival,(long)step.ival,(long)vizd.ival);
if(dbg) printf("xit.list:%o:xit.pl:%d:xit.num:%u\n",xitpt.lval.codelist,
xitpt.lval.place,xitpt.lval.codelist->num);
	    if(place.plval != vp.plval) 
		FNerror(l,p);
	    if(vizd.ival == T_INT)
		place.plval->ival += step.ival;
	    else
		place.plval->rval += step.rval;
	    push(place);
	    push(from);
	    push(to);	
	    push(step);
	    push(vizd);	
	    push(xitpt);
	    return(p);
	default: STerror("next");
    }
}

/* variables needed for M_READ. */

struct line *dlist[DLSIZ];
int dlp = 0;
int dlindx = 2;		/* skips <_data,0> */
int dtype;		/* type of last operation. */


/* M_COMPILE:
 *	x data x     --to--    x,_data,0,x     (0 is for interp())
 * M_FIXUP:
 *	allocates a spot in dlist, stores pointer to llist entry for
 *	this line at that spot.
 * M_EXECUTE:
 *	Returns, with p pointing at the zero, making interp() return.
 */
_data(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = 0;
	    return(p);
#endif
	case M_FIXUP:
	    dlist[dlp++] = gllentry(l);
	    p++;
	case M_EXECUTE: return(p);
	default:
	    STerror("data");
    }
}

/* M_COMPILE:  x dsep x   --to--   x,_dsep,0,x
 */
_dsep(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP:
	    l[p++] = 0;
	case M_READ:
	case M_EXECUTE: return(p);
	default: STerror("dsep");
    }
}

/* routines for changing the interpretors state. */

struct statstk {	/* for saving old states */
	int stkp;
	int stat;
} sstk[30];
int sstktop = 0;

/* M_COMPILE:
 *	x pushstate <state> x    --to--    x,pushstate,<state>,x
 * M_FIXUP:
 *	skip <state>
 * any other state:
 *	save old state and stack pointer.
 *	set state to <state>.
 */
_pushstate(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
#endif
	case M_FIXUP: return(++p);
	default:
	    sstk[sstktop].stkp = stackp;
	    sstk[sstktop].stat = status;
	    sstktop++;
	    status = l[p++];
	    return(p);
    }
}
_popstate(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: return(p);
	default:
	    sstktop--;
	    stackp = sstk[sstktop].stkp;
	    status = sstk[sstktop].stat&XMODE;
	    return(p);
    }
}


/* stack maintanence routines.
 */


/* M_COMPILE:
 *	x spop x    --to--    x,_spop,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	other: frees storage used by string (if any).
 */
_spop(l,p) int(*l[])(),p;
{
    union value s;

    switch(status&XMODE) {
	case M_EXECUTE:
	    s=pop();
	    if(s.sval != 0) free(s.sval);
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: return(p);
	default:
	    STerror("spop");
    }
}

/* M_COMPILE:
 *	x pop x    --to--    x,_pop,x
 * M_EXECUTE:
 *	stack: int,x    --to--   x
 */
_pop(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_EXECUTE: pop(); return(p);
	default:
	    STerror("pop");
    }
}

_stop(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_EXECUTE: exit(1);
	default:
	    STerror("stop");
    }
}
_end(l,p) int (*l[])(),p; { return(_stop(l,p)); }


/* operator list for the intermediate language. */
struct wlnode wlist[] = {
	"itoa",_itoa,	"print",_print,	"goto",_goto,	"if",_if,
	"rtoa",_rtoa,	"itor",_itor,	"rtoi",_rtoi,
	"gosub",_gosub, "return",_return,
	"icon",_icon,	"i+",_iadd,	"-",_isub,
	"rcon",_rcon,	"r+",_radd,	"r-",_rsub,
	"r*",_rmult,	"r/",_rdiv,
	"i*",_imult,	"i/",_idiv,	"i%",_imod,
	"scon",_scon,	",",_comma,	";",_scolon,
	"i==",_ieq,	"s==",_seq,	"r==",_req,
	"i<>",_ineq,	"r<>",_rneq,	"s<>",_sneq,
	"i<=",_ileq,	"s<=",_sleq,	"r<=",_rleq,
	"i<",_ilt,	"s<",_slt,	"r<",_rlt,
	"i>=",_igeq,	"s>=",_sgeq,	"r>=",_rgeq,
	"i>",_igt,	"s>",_sgt,	"r>",_rgt,
	"or",_or,	"and",_and,	"not",_not,
	"val",_val,	"var",_var,	"store",_store,
	"pop",_pop,	"spop",_spop,
	"pushstate",_pushstate,"popstate",_popstate,
	"stop",_stop,	"end",_end,
	"for",_for,	"next",_next,
	"dlabel",_dlabel,"rlabel",_rlabel,
	"contin",_contin,"leave",_leave,"enter",_enter,"exitlp",_exitlp,
	"data",_data,	"dsep",_dsep,
    0,0
};

SHAR_EOF
if test 14386 -ne "`wc -c < 'newbs/action.c.new'`"
then
	echo shar: error transmitting "'newbs/action.c.new'" '(should have been 14386 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/bsint.c'" '(5406 characters)'
if test -f 'newbs/bsint.c'
then
	echo shar: will not over-write existing file "'newbs/bsint.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/bsint.c'
/* 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();
}
SHAR_EOF
if test 5406 -ne "`wc -c < 'newbs/bsint.c'`"
then
	echo shar: error transmitting "'newbs/bsint.c'" '(should have been 5406 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/errors.c'" '(1583 characters)'
if test -f 'newbs/errors.c'
then
	echo shar: will not over-write existing file "'newbs/errors.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/errors.c'
/* errors.c -- error message routines for int.
 */

#include "bsdefs.h"


/* ULerror() -- unknown line (cannot find wanted line)
 */
ULerror(l,p) int(*l[])(),p;
{
    fprintf(stderr,"Unknown line %d\n",*(l[p]));
    exit(1);
}

/* STerror() -- wrong value for status variable
 */
XSTerror(f) char *f;
{
    fprintf(stderr,"%s: illegal status %o\n",f,status);
    exit(1);
}
/* FNerror() -- For Next error
 */
XFNerror(l,p)
int (*l[])(),p;
{
    struct dictnode *nv;
    struct line *ll;

    ll = gllentry(l);
    nv = l[p-2];
    fprintf(stderr,"Next %s, For (something else), at line %u\n",
	nv->name,ll->num);
    exit(1);
}

ODerror(l,p)
int (*l[])(),p;
{
    struct line *ll;
    char *s;
    ll = gllentry(l);
    s = ((struct dictnode *)l[p])->name;
    fprintf(stderr,"Out of Data in line %u at var %s\b",ll->num,s);
    exit(1);
}

BDerror(l,p)
int (*l[])(),p;
{
    struct line *ll;
    char *s;
    ll = gllentry(l);
    s = ((struct dictnode *)l[p])->name;
    fprintf(stderr,"Bad Data type in line %u at var %s\n",ll->num,s);
    exit(1);
}

VTerror(l,p)
int (*l[])(),p;
{
    struct dictnode *vp;
    vp = (struct dictnode *)l[p];
    fprintf(stderr,"Invalid data type %d for var %s\n",vp->type_of_value,vp->name);
    exit(1);
}

LVerror(l,p) int(*l[])(),p;
{
    struct line *ll;
    ll = gllentry(l);
    fprintf(stderr,"Tried to leave while not in a loop, at line %u\n",ll->num);
    exit(1);
}

CNerror(l,p) int(*l[])(),p;
{
    struct line *ll;
    ll = gllentry(l);
    fprintf(stderr,"Tried to continue while not in a loop, at line %u\n",ll->num);
    exit(1);
}
SHAR_EOF
if test 1583 -ne "`wc -c < 'newbs/errors.c'`"
then
	echo shar: error transmitting "'newbs/errors.c'" '(should have been 1583 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/mkrbop.c'" '(734 characters)'
if test -f 'newbs/mkrbop.c'
then
	echo shar: will not over-write existing file "'newbs/mkrbop.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/mkrbop.c'
/* mkrbop.c -- make operator functions for bs.  (real-boolean functions.)
*
*	USAGE: op name oper
*
* where:	name: name of function generated.
*		oper: operator for operation.
*/
#include <stdio.h>

main(argc,argv)
char **argv;
int argc;
{
char *name,*oper;

if(argc != 3) {
	fprintf(stderr,"arg count\n");
	exit(1);
}
name = argv[1]; oper = argv[2];

printf("_%s(l,p)\n",name);
printf("int (*l[])(),p;\n");
printf("{\n");
printf("    union value rg1,rg2,result;\n");
printf("\n");
printf("    if((status&XMODE) == M_EXECUTE) {\n");
printf("	rg2 = pop();\n");
printf("	rg1 = pop();\n");
printf("	result.ival = rg1.rval %s rg2.rval;\n",oper);
printf("	push(result);\n");
printf("    }\n");
printf("    return(p);\n");
printf("}\n");
}
SHAR_EOF
if test 734 -ne "`wc -c < 'newbs/mkrbop.c'`"
then
	echo shar: error transmitting "'newbs/mkrbop.c'" '(should have been 734 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/operat.c.new'" '(9302 characters)'
if test -f 'newbs/operat.c.new'
then
	echo shar: will not over-write existing file "'newbs/operat.c.new'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/operat.c.new'
/* operat.c -- operations, as opposed to actions.  FOR is an action,
 *	'+' is an operation.
 *
 * More operators can be found in the machine generated file "operat2.c".
 */

#include "bsdefs.h"


/*	BINARY OPERATORS	*/

/* Common description for the binary ops.
 *  also applies to all ops in operat2.c
 *
 * M_COMPILE:
 *	x op x   --to--   x,_op,x
 * M_EXECUTE:
 *	stack: ar2,ar1,x   --to--   (ar1 op ar2),x
 */


_comma(l,p) int (*l[])(),p;
{
    union value s1,s2,s3;
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: return(p);
	case M_READ: dtype = T_CHR;
	case M_EXECUTE:
	    s1 = pop();
	    s2 = pop();
	    s3.sval = myalloc(strlen(s1.sval)+strlen(s2.sval)+3);
	    strcpy(s3.sval,s2.sval);
	    strcat(s3.sval,"\t");
	    strcat(s3.sval,s1.sval);
	    if(s1.sval != 0) free(s1.sval);
	    if(s2.sval != 0) free(s2.sval);
	    push(s3);
	    return(p);
	default: STerror("comma");
    }
}
_scolon(l,p) int(*l[])(),p;
{
    union value s1,s2,s3;
    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
#endif
	case M_FIXUP: return(p);
	case M_READ: dtype = T_CHR;
	case M_EXECUTE:
	    s1 = pop();
	    s2 = pop();
	    s3.sval = myalloc(strlen(s1.sval)+strlen(s2.sval)+2);
	    strcpy(s3.sval,s2.sval);
	    strcat(s3.sval,s1.sval);
	    push(s3);
	    if(s1.sval != 0) free(s1.sval);
	    if(s2.sval != 0) free(s2.sval);
	    return(p);
	default:
	    STerror("scolon");
    }
}
/* last of binary operators */

/* M_COMPILE:
 *	x not x    --to--    x,_not,x
 * M_EXECUTE:
 *	stack: bool,x    --to--     !(bool),x
 */
_not(l,p) int (*l[])(),p;
{
    union value val;

    if((status&XMODE) == M_EXECUTE) {
	val = pop();
	val.ival = ! val.ival;
	push(val);
    }
    return(p);
}

/* M_COMPILE:
 *	x itoa x   --to--   x,_itoa,x
 * M_EXECUTE:
 *	stack: int,x   --to--   string,x
 */
_itoa(l,p)
int (*l[])(),p;
{
    union value val;
    char s2[30];

    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_READ:
	    dtype = T_CHR;
	case M_EXECUTE:
	    val=pop();
	    sprintf(s2,"%D",val.ival);	/* optimize later */
if(dbg) printf("_icon():M_EXECUTE:ival:%D to sval:%s\n",val.ival,s2);
	    val.sval=myalloc(strlen(s2)+1);
	    strcpy(val.sval,s2);
	    push(val);
	    return(p);
	default:
	    STerror("itoa");
    }
}
_rtoa(l,p)
int (*l[])(),p;
{
    union value val;
    char s2[30];

    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_READ: dtype = T_CHR;
	case M_EXECUTE:
	    val = pop();
	    sprintf(s2,"%g",val.rval);
if(dbg) printf("_rtoa():M_EXECUTE:rval:%g to sval:%s\n",val.rval,s2);
	    val.sval = myalloc(strlen(s2)+1);
	    strcpy(val.sval,s2);
	    push(val);
	    return(p);
	default: STerror("rtoa");
    }
}
_itor(l,p)
int (*l[])(),p;
{
    union value v1,v2;

    switch(status&XMODE) {
	case M_READ: dtype = T_DBL;
	case M_EXECUTE:
	    v1 = pop();
	    v2.rval = (double)v1.ival;
	    push(v2);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default: STerror("itor");
    }
}
_rtoi(l,p)
int (*l[])(),p;
{
    union value v1,v2;

    switch(status&XMODE) {
	case M_READ: dtype = T_INT;
	case M_EXECUTE:
	    v1 = pop();
	    v2.ival = (int)v1.rval;
	    push(v2);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default: STerror("rtoi");
    }
}

/* M_COMPILE:
 *	x scon "quoted string" x   --to--   x,_scon,*string,x
 * M_EXECUTE:
 *	stack: x   --to--   string,x
 *	other: pushes a COPY of the string, not the original.
 */
_scon(l,p)
int (*l[])(),p;
{
    char *s,c;
    union value val;
    int i;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = scon_in();
	    return(p);
#endif
	case M_READ:
	    dtype = T_CHR;
	case M_EXECUTE:
	    s = l[p++];
	    val.sval = myalloc(strlen(s)+1);
	    strcpy(val.sval,s);
	    push(val);
if(dbg) printf("_scon():M_EXECUTE:sval:%s\n",val.sval);
	    return(p);
	case M_FIXUP: p++; return(p);
	default: STerror("scon");
    }
}

/* M_COMPILE:
 *	x icon int x   --to--   x,_icon,int,x
 * M_EXECUTE:
 *	stack: x   --to--   int,x
 */
_icon(l,p)
int (*l[])(),p;
{
    union value val;
    union loni v;
    int i;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    v.l_in_loni = atol(int_in());
	    for(i=0; i<(sizeof(long)/sizeof(int)); i++)
		l[p++] = v.i_in_loni[i];
	    return(p);
#endif
	case M_READ: dtype = T_INT;
	case M_EXECUTE:
	    for(i=0; i<(sizeof(long)/sizeof(int)); i++)
		v.i_in_loni[i] = l[p++];
	    val.ival = v.l_in_loni;
	    push(val);
if(dbg) printf("_icon():M_EXECUTE:ival:%D\n",val.ival);
	    return(p);
	case M_FIXUP:
	    p += (sizeof(long)/sizeof(int));
	    return(p);
	default: STerror("icon");
    }
}
_rcon(l,p)
int (*l[])(),p;
{
    union doni v;
    int i;
    union value val;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    v.d_in_doni = atof(real_in());
	    for(i=0; i<(sizeof(double)/sizeof(int)); i++)
		l[p++] = v.i_in_doni[i];
	    return(p);
#endif
	case M_FIXUP:
	    p += (sizeof(double)/sizeof(int));
	    return(p);
	case M_READ: dtype = T_DBL;
	case M_EXECUTE:
	    for(i=0; i<(sizeof(double)/sizeof(int)); i++)
		v.i_in_doni[i] = l[p++];
	    val.rval = v.d_in_doni;
	    push(val);
	    return(p);
	default: STerror("rcon");
    }
}

/* M_COMPILE:
 *	x val type x   --to--   x,_val,type,x
 * M_EXECUTE:
 *	stack:	place,x   --to--   value,x
 *	other: for strings, pushes a copy of the string.
 */
_val(l,p) int(*l[])(),p;
{
    union value place,val;
    int ty;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
#endif
	case M_READ:
	    dtype = l[p];
	case M_EXECUTE:
	    ty = l[p];
	    place = pop();
if(dbg) printf("_val():M_EXECUTE:var:%s",place.vpval->name);
	    place.plval = getplace(place.vpval);
	    if(ty==T_CHR && place.plval->sval!=0) {
		val.sval = myalloc(strlen(place.plval->sval)+1);
		strcpy(val.sval,place.plval->sval);
		push(val);
	    }
	    else push(*place.plval);
if(dbg) printf(":ival:%D:rval:%g:sval:%s\n",ty==T_INT?place.plval->ival:(long)0,
	ty==T_DBL?place.plval->rval:(double)0,ty==T_CHR?place.plval->sval:0);
	case M_FIXUP: p++; return(p);
	default: STerror("val");
    }
}

/* M_COMPILE:
 *	x store typ x   --to--    x,_store,type,x
 * M_EXECUTE:
 *	stack: value,location,x   --to--   value,x
 *		(stores value at location).
 */
_store(l,p) int(*l[])(),p;
{
    union value place,val;
    int ty;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
#endif
	case M_READ:
	    dtype = l[p];
	case M_EXECUTE:
	    val = pop();
	    place = pop();
	    ty = l[p];
if(dbg) printf("_store():M_EXECUTE:var:%s:ival:%D:rval:%g:sval:%s\n",
	place.vpval->name,ty==T_INT?val.ival:(long)0,ty==T_DBL?val.rval:(double)0,ty==T_CHR?val.sval:0);
	    place.plval = getplace(place.vpval);
	    if(ty==T_CHR && place.plval->sval!=0) free(place.plval->sval);
	    (*place.plval) = val;
	    push(val);
	case M_FIXUP:
	    p++;
	    return(p);
	default: STerror("store");
    }
}

/* M_COMPILE:
 *	x var typ name x   --to--    x,_var,&vlist entry,x
 * M_EXECUTE:
 *	stack: x   --to--   &vlist entry,x
 * M_INPUT:
 *	(&vlist entry)->val is set to input value.
 * M_READ:
 *	Moves the data list pointers to the next data item.  If no next
 *	data item, calls ODerror.
 *	Does a "gosub" to the data item, to get its value on the stack.
 *	Does T_INT to T_CHR conversion if necessary.
 *	Pops value into vp->val.
 */
_var(l,p) int(*l[])(),p; /* same proc for any variable type */
{
    char *s;
    struct dictnode *vp;
    struct line *thislist;
    union value place,val;
    int ty,qual;

    switch(status&XMODE) {
#ifdef INT
	case M_COMPILE:
	    ty = atoi(int_in());
	    s = gtok();
	    l[p++] = gvadr(s,ty);
	    return(p);
#endif
	case M_EXECUTE:
	    val.vpval = l[p++];
if(dbg) printf("_var():M_EXECUTE:var:(%d)%s\n",val.vpval->type_of_value,
	val.vpval->name);
	    push(val);
	    return(p);
	case M_INPUT:
	    vp = l[p++];
	    place.plval = getplace(vp);
	    ty = (vp->type_of_value) & T_TMASK;
	    if(ty == T_INT)
		place.plval->ival = atol(int_in());
	    else if(ty == T_DBL)
		place.plval->rval = atof(real_in());
	    else 
		place.plval->sval = scon_in();
if(dbg) printf("_var():M_INPUT:var:(%d)%s:ival:%D:rval:%g:sval:%s\n",
vp->type_of_value,vp->name,ty==T_INT?place.plval->ival:(long)0,
ty==T_DBL?place.plval->rval:(double)0,ty==T_CHR?place.plval->sval:0);
	    return(p);
	case M_READ:
nxdl:	    if(dlist[dlp] == 0) ODerror(l,p);	/* ran off end of dlist */
	    thislist = dlist[dlp];
	    if((thislist->code)[dlindx] == 0) {
		dlp++;
		dlindx = 2;	/* skips <_data,0> */
		goto nxdl;
	    }

	    status = M_EXECUTE;
	    dlindx = interp(thislist->code,dlindx);
	    status = M_READ;

	    val = pop();
	    vp = l[p];
	    place.plval = getplace(vp);
	    qual = vp->type_of_value&T_TMASK;
	    if(qual == T_INT)
		place.plval->ival = val.ival;
	    else if(qual == T_DBL)
		place.plval->rval = val.rval;
	    else if(qual == T_CHR) {
		if(dtype == T_INT) {
			push(val); _itoa(l,p); val = pop();
		}
		else if(dtype == T_DBL) {
			push(val); _rtoa(l,p); val = pop();
		}
		if(place.plval->sval != 0) free(place.plval->sval);
		place.plval->sval = myalloc(strlen(val.sval)+1);
		strcpy(place.plval->sval,val.sval);
	    }
	    else VTerror(l,p);
	case M_FIXUP:
	    p++;
	    return(p);
	default: STerror("var");
    }
}
SHAR_EOF
if test 9302 -ne "`wc -c < 'newbs/operat.c.new'`"
then
	echo shar: error transmitting "'newbs/operat.c.new'" '(should have been 9302 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

sources-request@genrad.UUCP (07/31/85)

Mod.sources:  Volume 2, Issue 24
Submitted by: ukma!david (David Herron)


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	newbs/bsdefs.c
#	newbs/bsdefs.h
#	newbs/bsgram.y
#	newbs/bslash.c
#	newbs/bslib.c
#	newbs/getplace.c
#	newbs/gvadr.c
#	newbs/makefile
#	newbs/makefile.old
#	newbs/mkop.c
#	newbs/mkop.sh
#	newbs/mksop.c
#	newbs/num_ins.c
#	newbs/op2.c
#	newbs/operat.c
#	newbs/scon_in.c
# This archive created: Tue Jul 30 13:02:34 1985
export PATH; PATH=/bin:$PATH
if test ! -d 'newbs'
then
	echo shar: creating directory "'newbs'"
	mkdir 'newbs'
fi
echo shar: extracting "'newbs/bsdefs.c'" '(1128 characters)'
if test -f 'newbs/bsdefs.c'
then
	echo shar: will not over-write existing file "'newbs/bsdefs.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/bsdefs.c'
/* bsdefs.c -- Actual definitions of all the variables.
 *
 * bsdefs.h only has the "extern's" of the things declared in here.
 */

#include "bsdefs.h"


/* Initial stuff for line number table.
 *
 * The line number table is a singly-linked list.  The head is "firstline",
 * and the tail is "lastline".  The proper way to check for the end of the
 * list is to compare it to LASTLINE.  Lastline points to itself in case
 * I forget and code something differently (it also neatly ties up the end
 * of the list).
 */

#define LASTLINE	(struct line *)(&lastline)

struct line lastline = { &lastline,0077777,"",_nulline };
struct line firstline = { &lastline,0,"",_nulline };
struct line *curline = LASTLINE;


/* Initial stuff for data statements.
 *
 * "dlist[]" holds pointers to lines that have data on them.  It is initialized
 * in M_FIXUP.  "dlp" used to allocate entries from dlist[], it points to the
 * first free entry.  "dlindx" points within the current data line to the next
 * data item.
 * "dtype" indicates the data type for the last data item.
 */

struct line *dlist[DLSIZ];
int dlp = 0,dlindx = 0, dtype = 0;

SHAR_EOF
if test 1128 -ne "`wc -c < 'newbs/bsdefs.c'`"
then
	echo shar: error transmitting "'newbs/bsdefs.c'" '(should have been 1128 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/bsdefs.h'" '(4648 characters)'
if test -f 'newbs/bsdefs.h'
then
	echo shar: will not over-write existing file "'newbs/bsdefs.h'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/bsdefs.h'
/* bsdefs.h -- definition file for bs.
 */

#include <stdio.h>
#include <ctype.h>

/* 'Machine' status */
extern int status;
#define M_COMPILE	(1<<0)
#define M_EXECUTE	(1<<1)
#define M_INPUT		(1<<2)
#define M_FIXUP		(1<<3)
#define M_READ		(1<<4)

#define XMODE	(M_COMPILE|M_EXECUTE|M_INPUT|M_FIXUP|M_READ)


/* line table. */
#define LASTLINE	(struct line *)(&lastline)

struct line {
    struct line *nextline;	/* next entry in list. */
    int lnum;			/* its' number */
    int (*list)();		/* its' definition */
    char *text;			/* the original definition */
};

extern struct line firstline,lastline,*curline;


/* Variable types */
#define Q_NRM	0	/* nice, ordinary variable */
#define Q_ARY	1	/* array */
#define Q_BF	2	/* builtin-function */
#define Q_UFL	3	/* long user function */
#define Q_UFS	4	/* short user function */

			/* in type part, a zero value is an undefined type. */
#define T_INT	(1<<6)
#define T_CHR	(2<<6)
#define T_DBL	(3<<6)
#define T_LBL	(4<<6)

#define T_QMASK		037		/* lower 5 bits for type qualifier */
#define T_TMASK		(T_INT|T_CHR|T_DBL|T_LBL)

/* variable table */
#define VLSIZ	150

struct label {
    char *name;			/* what do we call it by. */
    int (*where)();		/* and where does it live */
};
/* For arrays, storage of them is defined as follows:
 *
 *   1st item: number of dimensions in array <NDIMS>.
 *   next <NDIMS> items: size of each dimension.
 *   rest of items: the actual values.
 *
 * Until we can support varrying sized arrays this is the setup:
 *
 *   1,10,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
 *
 * for a total size of 13 items.
 */
union value {
    long ival;		/* T_INT */
    double rval;	/* T_DBL */
    char *sval;		/* T_CHR */
    struct label lval;  /* T_LBL */
    struct line *locval; /* for pushing line# list entries */
    union value *arval; /* any+Q_ARY */
    struct dictnode *vpval; /* for use when pushing variable pointers */
    union value *plval; /* for use when pushing pointers to a value */
};

struct dictnode {	/* format of vlist entry */
    struct dictnode *father,*daughter;	/* doubly-linked list. */
    char *name;		/* name of entry. */
    int type_of_value;	/* its type. */
    union value val;	/* and its value */
};

extern struct dictnode *dicthead,*dictail,*curvp;

/* '_' Function table */
extern
	_print(),  	_goto(),	_if(),		_else(),
	_for(),		_next(),	_read(),	_data(),
	_dsep(),	_spop(),	_pop(),		_stop(),
	_end(),		_dlabel(),	_rlabel(),	_contin(),
	_leave(),	_enter(),	_exitlp(),	_iadd(),
	_isub(),	_imult(),	_idiv(),	_imod(),
	_comma(),	_radd(),	_rsub(),	_rmult(),
	_rdiv(),	_scolon(),	_gosub(),	_return(),
	_not(),		_ieq(),		_req(),		_seq(),
	_ineq(),	_rneq(),	_sneq(),	_ileq(),
	_rleq(),	_sleq(),	_ilt(),		_rlt(),
	_slt(),		_igeq(),	_rgeq(),	_sgeq(),
	_igt(),		_rgt(),		_sgt(),		_or(),
	_and(),		_itoa(),	_rtoa(),	_itor(),
	_rtoi(),	_pushstate(),	_popstate(),	_scon(),
	_rcon(),	_icon(),	_val(),		_store(),
	_var();

/*
 * Data table.
 * Array of pointers into llist.
 * Each is a line which has data.
 */
#define DLSIZ	100
extern struct line *dlist[]; /* actual table, number of elems. is DLSIZ */
extern int dlp;		/* index into dlist for current line of data */
extern int dlindx;	/* index into current line for current data item. */
extern int dtype;	/* in M_READ, operators set this to the type of 
			 * their operation.  When the expression is done
			 * executing, this variable will indicate its type.
			 */

/* error routines */
extern int ULerror();
extern int STerror();
extern int FNerror();
extern int ODerror();
extern int BDerror();
extern int VTerror();


/*
 * unions for storing data types in the code list 
 *
 * Used to convert from a double (for instance) into "int" sized chunks
 * for the purpose of manipulating instances of them in code lists.
 */


union doni {
    double d_in_doni;
    int i_in_doni[sizeof(double)/sizeof(int)];
};
union loni {
    long l_in_loni;
    int i_in_loni[sizeof(long)/sizeof(int)];
};
union voni {
    union value v_in_voni;
    int i_in_voni[sizeof(union value)/sizeof(int)];
};


/* miscellaneous definitions. */

#define STKSIZ	500
extern union value stack[];
extern int stackp;
extern int push();
extern union value pop();

#define CSTKSIZ	5
#define BFSIZ	200	/* input buffer */
extern char pbbuf[];	/* unput() buffer */
extern char ibuf[];
extern int iptr,pbptr;
extern char input();
extern rdlin(),unput();

extern blcpy();

extern char bslash();
extern char *scon_in();
extern int num_in();

extern char *myalloc();
extern union value *getplace();
extern struct line *gllentry();

extern FILE *bsin;

extern int dbg;		/* debugging flag. */
extern long atol();
extern double atof();
SHAR_EOF
if test 4648 -ne "`wc -c < 'newbs/bsdefs.h'`"
then
	echo shar: error transmitting "'newbs/bsdefs.h'" '(should have been 4648 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/bsgram.y'" '(8891 characters)'
if test -f 'newbs/bsgram.y'
then
	echo shar: will not over-write existing file "'newbs/bsgram.y'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/bsgram.y'
	/* bsgram.y -- grammer specification for bs.
	 */
%{
#include "bsdefs.h"

char *p;		/* the generic pointer */
int i;			/* the generic counter */
int (*l[300])();	/* array to generate the code list into. */
int lp;			/* pointer to current spot in l[] */

struct stk {
    int stack[40];
    int stkp;
};

struct stk ifstk,whstk,forstk,repstk,lpstk;
int gomax=0, ifmax=0, whmax=0, formax=0, repmax=0, lpmax=0;

extern char *yytext;
extern char *bsyysval;
extern int yyleng;
%}

%term EQUAL	NEQ	LE	LT	GE	WHILE
%term GT	OR	AND	NOT	RET	REPEAT
%term IF	THEN	ELSE	GOTO	GOSUB	UNTIL
%term STOP	END	INTEGER	REAL	SCONST	ELIHW
%term LET	SWORD	PRINT	INPUT	DATA	CFOR
%term FOR	TO	STEP	READ	WRITE	NEXT
%term DEFINE	LFUN	SFUN	FDEF	SYMBOL	DIM
%term VALUE	IWORD	RWORD	ROFC	LOOP	EXITIF
%term ITOR	RTOI	ITOA	RTOA	LEAVE	CONTINUE
%term POOL

%left ',' ';'
%right '='
%nonassoc OR AND
%nonassoc LE LT GE GT EQUAL NEQ
%left '+' '-'
%left '*' '/' '%'
%left UNARY
%left '('


%start lines

%%

lines		: /* empty */
		| lines line
		;

line		: lnum stat '\n'
			{ printf("\n"); }
		| '\n'
		;

lnum		: INTEGER
			{ bundle(2,_line,atoi($1); }
		;

stat		: LET let_xpr
		| let_xpr
		| PRINT pe
			{ bundle(1,_print); }
		| GOTO INTEGER
			{
				sprintf(s,"LN%s",$2);
				bundle(4,_rlabel,gvadr(s,T_LBL),_goto,0);
			}
		| GOSUB INTEGER
			{
				sprintf(s,"LN%s",$2);
				bundle(4,_rlabel,gvadr(s,T_LBL),_gosub,0); 
			}
		| LEAVE
			{ bundle(2,_leave,0); }
		| CONTINUE
			{ bundle(2,_contin,0); }
		| RET
			{ bundle(1,_return); }
		| IF bexpr
			{
				lpush(&ifstk,ifmax);
				sprintf(s,"IF%d",ifmax);
				bundle(4,_rlabel,gvadr(s,T_LBL),_if,0);
				ifmax += 2;
			}
		  THEN stat
			{
				i = ltop(&ifstk);
				sprintf(s,"IF%d",i+1);
				bundle(4,_rlabel,gvadr(s,T_LBL),_goto,0);
			}
		  if_else
		| INPUT 
			{ bundle(2,_pushstate,M_INPUT); }
		  var_lst
			{ bundle(1,_popstate); }
		| STOP
			{ bundle(1,_stop); }
		| END
			{ bundle(1,_end); }
		| FOR nvar '=' rexpr TO rexpr for_step
			{
				lpush(&forstk,formax);
				sprintf(s,"FOR%d",formax+2);
				bundle(2,_rlabel,gvadr(s,T_LBL));
				sprintf(s,"FOR%d",formax+1);
				bundle(3,_rlabel,gvadr(s,T_LBL),_enter);
				sprintf(s,"FOR%d",formax+1);
				bundle(5,_icon,(long)0,_rlabel,gvadr(s,T_LBL));
				sprintf(s,"FOR%d",formax);
				bundle(4,_dlabel,gvadr(s,T_LBL),_for,0);
				formax += 3;
			}
		| NEXT
			{
				i = ltop(&forstk);
				sprintf(s,"FOR%d",i+2);
				bundle(2,_dlabel,gvadr(s,T_LBL));
			}
		  nvar
			{
				i = lpop(&forstk);
				sprintf(s,"FOR%d",i);
				bundle(5,_next,_rlabel,gvadr(s,T_LBL),_goto,0);
				sprintf(s,"FOR%d",i+1);
				bundle(3,_dlabel,gvadr(s,T_LBL),_exitlp);
			}
		| READ 
			{ bundle(2,_pushstate,M_READ); }
		  var_lst
			{ bundle(1,_popstate); }
		| DATA 
			{ bundle(2,_data,0); }
		   data_lst
		| LOOP
			{
				lpush(&lpstk,lpmax);
				sprintf(s,"LP%d",lpmax+2);
				bundle(2,_rlabel,gvadr(s,T_LBL));
				sprintf(s,"LP%d",lpmax+1);
				bundle(3,_rlabel,gvadr(s,T_LBL),_enter);
				sprintf(s,"LP%d",lpmax);
				bundle(2,_dlabel,gvadr(s,T_LBL));
				lpmax += 3;
			}
		| EXITIF bexpr
			{
				i = ltop(&lpstk);
				sprintf(s,"LP%d",i+1);
				bundle(5,_not,_rlabel,gvadr(s,T_LBL),_if,0);
			}
		| POOL
			{
				i = lpop(&lpstk);
				sprintf(s,"LP%d",i+2);
				bundle(2,_dlabel,gvadr(s,T_LBL));
				sprintf(s,"LP%d",i);
				bundle(4,_rlabel,gvadr(s,T_LBL),_goto,0);
				sprintf(s,"LP%d",i+1);
				bundle(3,_dlabel,gvadr(s,T_LBL),_exitlp);
			}
		| WHILE
			{
				lpush(&whstk,whmax);
				sprintf(s,"WH%d",whmax+2);
				bundle(2,_rlabel,gvadr(s,T_LBL));
				sprintf(s,"WH%d",whmax+1);
				bundle(3,_rlabel,gvadr(s,T_LBL),_enter);
				sprintf(s,"WH%d",whmax);
				bundle(2,_rlabel,gvadr(s,T_LBL));
				whmax += 3;
			}
		  bexpr
			{
				i = ltop(&whstk);
				sprintf(s,"WH%d",i+1);
				bundle(4,_rlabel,gvadr(s,T+LBL),_if,0);
			}
		| ELIHW
			{
				i = lpop(&whstk);
				sprintf(s,"WH%d",i+2);
				bundle(2,_dlabel,gvadr(s,T_LBL));
				sprintf(s,"WH%d",i)
				bundle(4,_rlabel,gvadr(s,T_LBL),_goto,0);
				sprintf(s,"WH%d",i+1);
				bundle(3,_dlabel,gvadr(s,T_LBL),_exitlp);
			}
		| REPEAT
			{
				lpush(&repstk,repmax);
				sprintf(s,"REP%d",repmax+1);
				bundle(2,_rlabel,gvadr(s,T_LBL));
				sprintf(s,"REP%d",repmax+2);
				bundle(3,_rlabel,gvadr(s,T_LBL),_enter);
				sprintf(s,"REP%d",repmax);
				bundle(2,_dlabel,gvadr(s,T_LBL));
				repmax += 3;
			}
		| UNTIL
			{
				i = ltop(&repstk);
				sprintf(s,"REP%d",i+1);
				bundle(2,_dlabel,gvadr(s,T_LBL));
			}
		  bexpr
			{
				i = lpop(&repstk);
				sprintf(s,"REP%d",i);
				bundle(5,_not,_rlabel,gvadr(s,T_LBL),_if,0);
				sprintf(s,"REP%d",i+2);
				bundle(3,_dlabel,gvadr(s,T_LBL),_exitlp);
			}
		;

nvar		: ivar
		| rvar
		;

let_xpr		: ivar '=' rexpr
			{ bundle(4,_rtoi,_store,T_DBL,_pop); }
		| rvar '=' rexpr
			{ bundle(3,_store,T_DBL,_pop); }
		| svar '=' sexpr
			{ bundle(3,_store,T_CHR,spop); }
		;

data_lst	: rexpr
			{ bundle(2,_dsep,0); }
		| sexpr
			{ bundle(1,_dsep); }
		| data_lst ',' rexpr
			{ bundle(1,_dsep); }
		| data_lst ',' sexpr
			{ bundle(1,_dsep); }
		;

ind_lst		: rexpr
		| ind_lst ',' rexpr
		;

for_step	: /* empty */
			{ bundle(3,_icon,(long)0); }
		| STEP rexpr
		;

if_else		: /* empty */
			{
				i = lpop(&ifstk);
				sprintf(s,"IF%d",i);
				bundle(2,_dlabel,gvadr(s,T_LBL));
				sprintf(s,"IF%d",i+1);
				bundle(2,_dlabel,gvadr(s,T_LBL));
			}
		| ELSE 
			{
				i = ltop(&ifstk);
				sprintf(s,"IF%d",i);
				bundle(2,_dlabel,gvadr(s,T_LBL));
			}
		  stat
			{
				i = lpop(&ifstk);
				sprintf(s,"IF%d",i+1);
				bundle(2,_dlabel,gvadr(s,T_LBL));
			}
		;


pe		: sexpr ','
			{ bundle(3,_scon,"",_comma); }
		| sexpr ';'
		| sexpr
			{ bundle(3,_scon,"\\n",_scolon); }
		| /* empty */
			{ bundle(2,_scon,"\\n"); }
		;


var_lst		: ivar
		| rvar
		| svar
		| var_lst ',' var_lst
		;

sexpr		: SCONST
			{ p=myalloc(yyleng); strcpy(p,$1); bundle(2,_scon,p); }
		| svar
			{ bundle(2,_val,T_CHR); }
		| rexpr
			{ bundle(1,_rtoa); }
		| svar '=' sexpr
			{ bundle(2,_store,T_CHR); }
		| sexpr ';' sexpr
			{ bundle(1,_scolon); }
		| sexpr '+' sexpr
			{ bundle(1,_scolon); }
		| sexpr ',' sexpr
			{ bundle(1,_comma); }
		| '(' sexpr ')'
		;
sbe		: sexpr EQUAL sexpr
			{ bundle(1,_seq); }
		| sexpr NEQ sexpr
			{ bundle(1,_sneq); }
		| sexpr LE sexpr
			{ bundle(1,_sleq); }
		| sexpr LT sexpr
			{ bundle(1,_slt); }
		| sexpr GE sexpr
			{ bundle(1,_sgeq); }
		| sexpr GT sexpr
			{ bundle(1,_sgt); }
		;

ivar		: IWORD
			{ bundle(2,_var,gvadr($1,T_INT)); }
		| IWORD '(' 
			{ bundle(2,_pushstate,M_EXECUTE); }
		  ind_lst ')'
			{ bundle(3,_popstate,_var,gvadr($1,T_INT+Q_ARY)); }
		;
rvar		: RWORD
			{ bundle(2,_var,gvadr($1,T_DBL)); }
		| RWORD '(' 
			{ bundle(2,_pushstate,M_EXECUTE); }
		  ind_lst ')'
			{ bundle(3,_popstate,_var,gvadr($1,T_DBL+Q_ARY)); }
		;

svar		: SWORD
			{ bundle(2,_var,gvadr($1,T_CHR)); }
		| SWORD '(' 
			{ bundle(2,_pushstate,M_EXECUTE); }
		  ind_lst ')'
			{ bundle(3,_popstate,_var,gvadr($1,T_CHR+Q_ARY)); }
		;



rexpr		: rvar
			{ bundle(2,_val,T_DBL); }
		| REAL
			{ bundle(5,_rcon,(double)atof($1)); }
		| INTEGER
			{ bundle(5,_rcon,(double)atof($1)); }
		| ivar
			{ bundle(3,_val,T_INT,_itor); }
		| rvar '=' rexpr
			{ bundle(2,_store,T_DBL); }
		| '(' rexpr ')'
		| rexpr '+' rexpr
			{ bundle(1,_radd); }
		| rexpr '-' rexpr
			{ bundle(1,_rsub); }
		| rexpr '*' rexpr
			{ bundle(1,_rmult); }
		| rexpr '/' rexpr
			{ bundle(1,_rdiv); }
		| '+' rexpr	%prec UNARY
		| '-' rexpr	%prec UNARY
			{ bundle(6,_rcon,(double)(-1),_rmult); }
		;

rbe		: rexpr EQUAL rexpr
			{ bundle(1,_req); }
		| rexpr NEQ rexpr
			{ bundle(1,_rneq); }
		| rexpr LE rexpr
			{ bundle(1,_rleq); }
		| rexpr LT rexpr
			{ bundle(1,_rlt); }
		| rexpr GE rexpr
			{ bundle(1,_rgeq); }
		| rexpr GT rexpr
			{ bundle(1,_rgt); }
		;
bexpr		: sbe
		| rbe
		| NOT bexpr	%prec UNARY
			{ bundle(1,_not); }
		| bexpr OR bexpr
			{ bundle(1,_or); }
		| bexpr AND bexpr
			{ bundle(1,_and); }
		| '(' bexpr ')'
		;
%%

main()
{
    rdlin(bsin);
    return(yyparse());
}

yyerror(s)
char *s;
{
    fprintf(stderr,"%s\n",s);
}

lpush(stack,val) struct stk *stack; int val;
{
    stack->stack[stack->stkp++] = val; 
}

int ltop(stack) struct stk *stack;
{ 
    return(stack->stack[stack->stkp-1]); 
}

int lpop(stack) struct stk *stack;
{ 
    return(stack->stack[--stack->stkp]); 
}

/* bundle() -- append argument list to l[].  Idea tooken from bc.y.
 *
 * Usage:  bundle(cnt,arg,arg,...,arg)
 *
 * The "arg"'s can be anything.  "cnt" is a count of the number of integers
 * it would take to hold all the args.
 *
 * e.g.  bundle(4,(double)a); is the correct count for a.
 *
 *	******* NOTE *******
 *
 * This routine is machine dependant.  It depends on the way arguments are
 * passed on the stack on the PDP-11 machines.  It may not work elsewhere.
 */
bundle(a)
int a;
{
    register int *p;
    register int sz;

    p = &a;
    sz = *p++;
    while(sz-- > 0) 
	l[lp++] = *p++;
}
SHAR_EOF
if test 8891 -ne "`wc -c < 'newbs/bsgram.y'`"
then
	echo shar: error transmitting "'newbs/bsgram.y'" '(should have been 8891 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/bslash.c'" '(567 characters)'
if test -f 'newbs/bslash.c'
then
	echo shar: will not over-write existing file "'newbs/bslash.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/bslash.c'
/* bslash() -- have seen '\', use input() to say what is actually wanted.
 */
char bslash()
{
    char text[8];
    register char *s,c;
    int v;

    c=input();
    if(c == 'n') c='\n';
    else if(c == 't') c='\t';
    else if(c == 'b') c='\b';
    else if(c == 'r') c='\r';
    else if(c == 'f') c='\f';
    else if(c>='0' && c<='7') { /* octal digit string */
	s = &text[0];
	*s++ = c;
	c=input();
	while(c>='0' && c<='7') {
		*s++ = c;
		c=input();
	}
	*s++ = '\0';
	sscanf(text,"%o",&v);
	c = (char) v;
    }
    else if(c=='\n') rdlin(bsin);
    return(c);
}
SHAR_EOF
if test 567 -ne "`wc -c < 'newbs/bslash.c'`"
then
	echo shar: error transmitting "'newbs/bslash.c'" '(should have been 567 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/bslib.c'" '(1553 characters)'
if test -f 'newbs/bslib.c'
then
	echo shar: will not over-write existing file "'newbs/bslib.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/bslib.c'
/* bslib.c -- subroutine library, routines useful anywhere.
 */

#include "bsdefs.h"

XFILE *bsin = stdin;

/* blcpy -- copies a block of memory (l bytes) from s to d.
 */
blcpy(d,s,l)
char *d,*s;
int l;
{
    for(; l >= 0; (l--)) *(d++) = *(s++);
}

/* Input routines.  These routines buffer input a line at a time into
 * ibuf.  Unputted input goes to pbbuf, and gets read before things in
 * ibuf, if anything in pbbuf.
 */

char pbbuf[CSTKSIZ],ibuf[BFSIZ];

int iptr = -1;
int pbptr = -1;

char input()
{
    if(pbptr > -1)
	return(pbbuf[pbptr--]);
    else {
	if(ibuf[iptr] == '\0') rdlin(bsin);
	if(ibuf[iptr]!='\0' && !feof(bsin))
	    return(ibuf[iptr++]);
	else
	    return(0);
    }
}

rdlin(f) FILE *f;
{
    char c;

    iptr = 0;
    for(c=fgetc(f); c!='\n' && c!=EOF; c=fgetc(f)) ibuf[iptr++] = c;
    ibuf[iptr++] = c;
    ibuf[iptr++] = '\0';
    iptr = 0;
}

unput(c) char c;
{ pbbuf[++pbptr] = c; }

/* myalloc() -- allocate, checking for out of memory.
 */
char *myalloc(nb)
int nb;
{
    char *rval;
    rval = malloc(nb);
/*
    printf("myalloc:tos:%o,rv:%o,nb:%d,e:%o\n",&rval,rval,nb,sbrk(0));
*/
    if(rval == 0) {
	fprintf(stderr,"myalloc: out of memory\n");
	exit(1);
    }
    return(rval);
}



/* Stack routines.  Very simple. */

union value stack[STKSIZ];
int stackp = -1;

push(i) union value i;
{
    stack[++stackp] = i;
}

union value pop()
{
    return(stack[stackp--]);
}

/* Mark stack.  Also very simple. */
int mstack[5];
int mstkp = -1;
mpush()
{ mstack[++mstkp] = stackp; }
mpop()
{ stackp = mstack[mstkp--]; }
SHAR_EOF
if test 1553 -ne "`wc -c < 'newbs/bslib.c'`"
then
	echo shar: error transmitting "'newbs/bslib.c'" '(should have been 1553 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/getplace.c'" '(488 characters)'
if test -f 'newbs/getplace.c'
then
	echo shar: will not over-write existing file "'newbs/getplace.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/getplace.c'
/* getplace() -- get a pointer to place of value for vlist entry on top of stack
 *	For arrays, getplace() expects the indexes to be on the stack as well.
 *	The parser should properly arrange for this to happen.
 */
union value *getplace(dp)
struct dictnode *dp;
{
    int qual;
    union value ind,*place;

    qual = dp->type_of_value&T_QMASK;
    if(qual == Q_ARY) {
	ind = pop();
	mpop();
	place = & dp->val.arval[ind.ival+2];
    }
    else
	place = & dp->val;
    return(place);
}
SHAR_EOF
if test 488 -ne "`wc -c < 'newbs/getplace.c'`"
then
	echo shar: error transmitting "'newbs/getplace.c'" '(should have been 488 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/gvadr.c'" '(911 characters)'
if test -f 'newbs/gvadr.c'
then
	echo shar: will not over-write existing file "'newbs/gvadr.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/gvadr.c'
/* gvadr() -- Get variable address from vlist, with type checking.
 *	This routine allows numerous copies of same name as long as
 *	all copies have different types.  Probably doesnt matter since
 *	the parser does the type checking.
 */
struct dictnode *gvadr(s,ty)
char *s;
int ty;
{
    register int i;
    register int qual; /* type qualifier */

    /* Inefficient */
    for(i=0; vlist[i].name!=0 && i<VLSIZ; i++)
	if(vlist[i].type_of_value==ty && strcmp(s,vlist[i].name)==0)
		/* match found */
			break;
    if(i >= VLSIZ) {
	fprintf(stderr,"gvadr: out of room in variable list for %s\n",s);
	exit(1);
    }
    /* not on list, enter it */
    if(vlist[i].name == 0) {
	vlist[i].name = myalloc(strlen(s)+1);
	strcpy(vlist[i].name,s);
	vlist[i].val.rval = 0;
	vlist[i].type_of_value = ty;
	if(ty&T_QMASK == Q_ARY)
	    vlist[i].val.arval = myalloc(13*sizeof(union value));
    }
    return(&vlist[i]);
}
SHAR_EOF
if test 911 -ne "`wc -c < 'newbs/gvadr.c'`"
then
	echo shar: error transmitting "'newbs/gvadr.c'" '(should have been 911 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/makefile'" '(193 characters)'
if test -f 'newbs/makefile'
then
	echo shar: will not over-write existing file "'newbs/makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/makefile'
operat2.o: mkop.sh op rop sop
	mkop.sh >operat2.c
	cc -c operat2.c
	rm operat2.c
	: done operat2.o
op: mkop.c
	cc mkop.c -o op
rop: mkrbop.c
	cc mkrbop.c -o rop
sop: mksop.c
	cc mksop.c -o sop
SHAR_EOF
if test 193 -ne "`wc -c < 'newbs/makefile'`"
then
	echo shar: error transmitting "'newbs/makefile'" '(should have been 193 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/makefile.old'" '(661 characters)'
if test -f 'newbs/makefile.old'
then
	echo shar: will not over-write existing file "'newbs/makefile.old'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/makefile.old'
OFILES = lex.o bsint.o action.o operat.o bslib.o errors.o
PRSO= bsgram.o lex.o bslib.o
INTO= bsint.o action.o operat2.o operat.o bslib.o errors.o

prs: ${PRSO}
	cc -s ${PRSO} -o prs
bsgram.o: bsgram.c bsdefs.h
	cc -c bsgram.c
bsgram.c: bsgram.y
	yacc -d bsgram.y
	mv y.tab.c bsgram.c
	mv y.tab.h bstokens.h

int: ${INTO}
	cc ${INTO} -o int

${OFILES}: bsdefs.h

operat2.o: mkop.sh op rop sop
	mkop.sh >operat2.c
	cc -c operat2.c
	rm operat2.c
	: done operat2.o
op: mkop.c
	cc mkop.c -o op
rop: mkrbop.c
	cc mkrbop.c -o rop
sop: mksop.c
	cc mksop.c -o sop

pr:
	pr bsgram.y lex.c bsdefs.h bslib.c bsint.c action.c operat.c mkop.c mkrbop.c mksop.c errors.c | lpr
SHAR_EOF
if test 661 -ne "`wc -c < 'newbs/makefile.old'`"
then
	echo shar: error transmitting "'newbs/makefile.old'" '(should have been 661 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/mkop.c'" '(1030 characters)'
if test -f 'newbs/mkop.c'
then
	echo shar: will not over-write existing file "'newbs/mkop.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/mkop.c'
/* mkop.c -- make operator function for bs.
*
*	USAGE: op name type oper tag
*
* where:	name: name of function generated.
*		type: data type of operation.
*		oper: operator for operation.
*		tag: structure tag name.
*
* This will only work with T_INT and T_DBL operators, T_CHR operations
* do not boil down to a simple operation.
*/
#include <stdio.h>

main(argc,argv)
char **argv;
int argc;
{
char *name,*type,*oper,*tag;

if(argc != 5) {
	fprintf(stderr,"arg count\n");
	exit(1);
}
name = argv[1]; type = argv[2]; oper = argv[3]; tag = argv[4];

printf("_%s(l,p)\n",name);
printf("int (*l[])(),p;\n");
printf("{\n");
printf("    union value rg1,rg2,result;\n");
printf("\n");
printf("    if((status&XMODE)==M_READ){ dtype=T_%s; goto EXEC;}\n",type);
printf("    if((status&XMODE) == M_EXECUTE) {\n");
printf("EXEC:\n");
printf("	rg2 = pop();\n");
printf("	rg1 = pop();\n");
printf("	result.%s = rg1.%s %s rg2.%s;\n",tag,tag,oper,tag);
printf("	push(result);\n");
printf("    }\n");
printf("    return(p);\n");
printf("}\n");
}
SHAR_EOF
if test 1030 -ne "`wc -c < 'newbs/mkop.c'`"
then
	echo shar: error transmitting "'newbs/mkop.c'" '(should have been 1030 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/mkop.sh'" '(482 characters)'
if test -f 'newbs/mkop.sh'
then
	echo shar: will not over-write existing file "'newbs/mkop.sh'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/mkop.sh'
echo "/* operat2.c -- more operators for bs.  the ones that are all alike."
echo " */"
echo ""
echo "#include \"bsdefs.h\""
echo ""
op "radd" "DBL" "+" "rval" 
op "rsub" "DBL" "-" "rval" 
op "rmult" "DBL" "*" "rval" 
op "rdiv" "DBL" "/" "rval" 
rop "req" "=="
sop "seq" "=="
rop "rneq" "!="
sop "sneq" "!="
rop "rleq" "<="
sop "sleq" "<="
rop "rlt" "<"
sop "slt" "<"
rop "rgeq" ">="
sop "sgeq" ">="
rop "rgt" ">"
sop "sgt" ">"
op "or" "INT" "||" "ival" 
op "and" "INT" "&&" "ival" 
SHAR_EOF
if test 482 -ne "`wc -c < 'newbs/mkop.sh'`"
then
	echo shar: error transmitting "'newbs/mkop.sh'" '(should have been 482 characters)'
fi
chmod +x 'newbs/mkop.sh'
fi # end of overwriting check
echo shar: extracting "'newbs/mksop.c'" '(725 characters)'
if test -f 'newbs/mksop.c'
then
	echo shar: will not over-write existing file "'newbs/mksop.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/mksop.c'
/* mksop.c -- make string comparator functions for bs.
*
*	USAGE: op name oper
*
* where:	name: name of function generated.
*		oper: operator for operation.
*/
#include <stdio.h>

main(argc,argv)
char **argv;
int argc;
{
char *name,*oper;

if(argc != 3) {
	fprintf(stderr,"arg count\n");
	exit(1);
}
name = argv[1]; oper = argv[2];

printf("_%s(l,p)\n",name);
printf("int (*l[])(),p;\n");
printf("{\n");
printf("    union value rg1,rg2,result;\n");
printf("\n");
printf("    if((status&XMODE) == M_EXECUTE) {\n");
printf("	rg2 = pop();\n");
printf("	rg1 = pop();\n");
printf("	result.sval = strcmp(rg1.sval,rg2.sval) %s 0;\n",oper);
printf("	push(result);\n");
printf("    }\n");
printf("    return(p);\n");
printf("}\n");
}
SHAR_EOF
if test 725 -ne "`wc -c < 'newbs/mksop.c'`"
then
	echo shar: error transmitting "'newbs/mksop.c'" '(should have been 725 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/num_ins.c'" '(3393 characters)'
if test -f 'newbs/num_ins.c'
then
	echo shar: will not over-write existing file "'newbs/num_ins.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/num_ins.c'
/* int_in() -- tokenizer routine for inputting a number.
 * int_in() returns a pointer to a static data area.  This area gets 
 * overwritten with each call to int_in so use the data before calling
 * int_in() again.
 */
char * int_in()
{
    register char c,*s;
    static char text[20];

    s = &text[0];

/* beginning state, skip junk until either '-' or ['0'-'9'] comes along */

l1: c=input();
    if(c>='0' && c<='9') goto l3;
    else if(c == '-') goto l2;
    else {
	if(c=='\n' || c=='\0') rdlin(bsin);
	goto l1;
    }

/* skipped junk, seen '-', gather it and make sure next char is a digit */

l2: *s++ = c;
    c=input();
    if(c==' ' || c=='\t') goto l2; /* allow white between sign and digit */
    else if(c>='0' && c<='9') goto l3;
    else { /* seen something not allowed. */
	s = &text[0];
	printf("\n\007??");
	goto l1; /* restart machine */
    }

/* skipped junk, seen a digit, gather until a non-digit appears */

l3: *s++ = c;
    c=input();
    if(c>='0' && c<='9') goto l3;
    else {
	/* have reached successful conclusion to machine. */
	unput(c);
	*s++ = '\0';
	return(text);
    }
}

/* real_in() -- read in a floating point number using input().
 *
 * real_in() returns a pointer to a static data area.  This data area
 * gets overwritten with each call to real_in(), so use it quickly.
 */
char *real_in()
{
    register char *s,c;
    static char bf[30];

    s = &bf[0];

/* starting state.  loops back until something interesting seen */

state1:	c=input();
	if(c == '-') goto state3;
	else if(c>='0' && c<='9') goto state2;
	else if(c == '.') goto state4;
	else {
		if(c == '\0') return(0);
		/* else */
		if(c == '\n') rdlin(bsin);
		goto state1;
	}

/* seen ([sign] dig). loop back for digs, looking for (.|e|E) */

state2: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state2;
	else if(c=='e' || c=='E') goto state6;
	else if(c == '.') goto state4;
	else goto state9;	/* done */

/* seen (sign).  looking for (dig). ignore whitespace. */

state3: *s++ = c;
state3_a: c=input();
	if(c==' ' || c=='\t') goto state3_a;
	else if(c>='0' && c<='9') goto state2;
	else if(c == '.') goto state4;
	else goto state10;	/* error, had a sign so we have to have digs. */

/* seen ([sign] digs '.').  looking for digs.  done on anything else */

state4: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state5;
	else goto state9;	/* done */

/* seen ([sign] digs '.' dig).  looking for (dig|e|E). done on anything else */

state5:	*s++ = c;
	c=input();
	if(c=='e' || c=='E') goto state6;
	else if(c>='0' && c<='9') goto state5;
	else goto state9;

/* seen ([sign] digs '.' digs (e|E)). looking for sign or digs, else error. */

state6: *s++ = c;
	c=input();
	if(c=='+' || c=='-') goto state7;
	else if(c>='0' && c<='9') goto state8;
	else goto state10;	/* error */

/* seen ([sign] digs '.' digs (e|E) sign). looking for digs, else error. */

state7: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state8;
	else goto state10;	/* error */

/* seen ([sign] digs '.' digs (e|E) [sign] dig). looking for digs. */

state8: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state8;
	else goto state9;	/* done */

/* seen a complete number.  machine successfully completed.  whew! */

state9: unput(c);	/* might want that later */
	*s++ = '\0';
	return(bf);

/* Uh oh.  An error.  Print an error and restart. */

state10: printf("\n\007??");
	s = &bf[0];
	goto state1;
}
SHAR_EOF
if test 3393 -ne "`wc -c < 'newbs/num_ins.c'`"
then
	echo shar: error transmitting "'newbs/num_ins.c'" '(should have been 3393 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/op2.c'" '(4171 characters)'
if test -f 'newbs/op2.c'
then
	echo shar: will not over-write existing file "'newbs/op2.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/op2.c'
/* operat2.c -- more operators for bs.  the ones that are all alike.
 */

#include "bsdefs.h"

_radd(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE)==M_READ){ dtype=T_DBL; goto EXEC;}
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	rg2 = pop();
	rg1 = pop();
	result.rval = rg1.rval + rg2.rval;
	push(result);
    }
    return(p);
}
_rsub(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE)==M_READ){ dtype=T_DBL; goto EXEC;}
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	rg2 = pop();
	rg1 = pop();
	result.rval = rg1.rval - rg2.rval;
	push(result);
    }
    return(p);
}
_rmult(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE)==M_READ){ dtype=T_DBL; goto EXEC;}
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	rg2 = pop();
	rg1 = pop();
	result.rval = rg1.rval * rg2.rval;
	push(result);
    }
    return(p);
}
_rdiv(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE)==M_READ){ dtype=T_DBL; goto EXEC;}
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	rg2 = pop();
	rg1 = pop();
	result.rval = rg1.rval / rg2.rval;
	push(result);
    }
    return(p);
}
_req(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.rval == rg2.rval;
	push(result);
    }
    return(p);
}
_seq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.sval = strcmp(rg1.sval,rg2.sval) == 0;
	push(result);
    }
    return(p);
}
_rneq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.rval != rg2.rval;
	push(result);
    }
    return(p);
}
_sneq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.sval = strcmp(rg1.sval,rg2.sval) != 0;
	push(result);
    }
    return(p);
}
_rleq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.rval <= rg2.rval;
	push(result);
    }
    return(p);
}
_sleq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.sval = strcmp(rg1.sval,rg2.sval) <= 0;
	push(result);
    }
    return(p);
}
_rlt(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.rval < rg2.rval;
	push(result);
    }
    return(p);
}
_slt(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.sval = strcmp(rg1.sval,rg2.sval) < 0;
	push(result);
    }
    return(p);
}
_rgeq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.rval >= rg2.rval;
	push(result);
    }
    return(p);
}
_sgeq(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.sval = strcmp(rg1.sval,rg2.sval) >= 0;
	push(result);
    }
    return(p);
}
_rgt(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.rval > rg2.rval;
	push(result);
    }
    return(p);
}
_sgt(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE) == M_EXECUTE) {
	rg2 = pop();
	rg1 = pop();
	result.sval = strcmp(rg1.sval,rg2.sval) > 0;
	push(result);
    }
    return(p);
}
_or(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE)==M_READ){ dtype=T_INT; goto EXEC;}
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.ival || rg2.ival;
	push(result);
    }
    return(p);
}
_and(l,p)
int (*l[])(),p;
{
    union value rg1,rg2,result;

    if((status&XMODE)==M_READ){ dtype=T_INT; goto EXEC;}
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	rg2 = pop();
	rg1 = pop();
	result.ival = rg1.ival && rg2.ival;
	push(result);
    }
    return(p);
}
SHAR_EOF
if test 4171 -ne "`wc -c < 'newbs/op2.c'`"
then
	echo shar: error transmitting "'newbs/op2.c'" '(should have been 4171 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/operat.c'" '(8663 characters)'
if test -f 'newbs/operat.c'
then
	echo shar: will not over-write existing file "'newbs/operat.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/operat.c'
/* operat.c -- operations, as opposed to actions.  FOR is an action,
 *	'+' is an operation.
 *
 * More operators can be found in the machine generated file "operat2.c".
 */

#include "bsdefs.h"


/*	BINARY OPERATORS	*/

/* Common description for the binary ops.
 *  also applies to all ops in operat2.c
 *
 * M_COMPILE:
 *	x op x   --to--   x,_op,x
 * M_EXECUTE:
 *	stack: ar2,ar1,x   --to--   (ar1 op ar2),x
 */


_comma(l,p) int (*l[])(),p;
{
    union value s1,s2,s3;
    if((status&XMODE) == M_FIXUP) return(p);
    if((status&XMODE) == M_READ) { dtype = T_CHR; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    s1 = pop();
	    s2 = pop();
	    s3.sval = myalloc(strlen(s1.sval)+strlen(s2.sval)+3);
	    strcpy(s3.sval,s2.sval);
	    strcat(s3.sval,"\t");
	    strcat(s3.sval,s1.sval);
	    if(s1.sval != 0) free(s1.sval);
	    if(s2.sval != 0) free(s2.sval);
	    push(s3);
    }
	    return(p);
}
_scolon(l,p) int(*l[])(),p;
{
    union value s1,s2,s3;
    if((status&XMODE) == M_READ) { dtype = T_CHR; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    s1 = pop();
	    s2 = pop();
	    s3.sval = myalloc(strlen(s1.sval)+strlen(s2.sval)+2);
	    strcpy(s3.sval,s2.sval);
	    strcat(s3.sval,s1.sval);
	    push(s3);
	    if(s1.sval != 0) free(s1.sval);
	    if(s2.sval != 0) free(s2.sval);
    }
    return(p);
}
/* last of binary operators */

/* ---And now for something completely different: a Unary Operator.
 *
 * M_COMPILE:
 *	x not x    --to--    x,_not,x
 * M_EXECUTE:
 *	stack: bool,x    --to--     !(bool),x
 */
_not(l,p) int (*l[])(),p;
{
    union value val;

    if((status&XMODE) == M_EXECUTE) {
	val = pop();
	val.ival = ! val.ival;
	push(val);
    }
    return(p);
}

/* M_COMPILE:
 *	x itoa x   --to--   x,_itoa,x
 * M_EXECUTE:
 *	stack: int,x   --to--   string,x
 */
_itoa(l,p)
int (*l[])(),p;
{
    union value val;
    char s2[30];

    if((status&XMODE) == M_READ) { dtype = T_CHR; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    val=pop();
	    sprintf(s2,"%D",val.ival);	/* optimize later */
if(dbg) printf("_icon():M_EXECUTE:ival:%D to sval:%s\n",val.ival,s2);
	    val.sval=myalloc(strlen(s2)+1);
	    strcpy(val.sval,s2);
	    push(val);
    }
    return(p);
}
_rtoa(l,p)
int (*l[])(),p;
{
    union value val;
    char s2[30];

    if((status&XMODE) == M_READ) { dtype = T_CHR; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    val = pop();
	    sprintf(s2,"%g",val.rval);
if(dbg) printf("_rtoa():M_EXECUTE:rval:%g to sval:%s\n",val.rval,s2);
	    val.sval = myalloc(strlen(s2)+1);
	    strcpy(val.sval,s2);
	    push(val);
    }
    return(p);
}
_itor(l,p)
int (*l[])(),p;
{
    union value v1,v2;

    if((status&XMODE) == M_READ) { dtype = T_DBL; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    v1 = pop();
	    v2.rval = (double)v1.ival;
	    push(v2);
    }
    return(p);
}
_rtoi(l,p)
int (*l[])(),p;
{
    union value v1,v2;

    if((status&XMODE) == M_READ) { dtype = T_INT; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    v1 = pop();
	    v2.ival = (int)v1.rval;
	    push(v2);
    }
    return(p);
}

/* M_COMPILE:
 *	x scon "quoted string" x   --to--   x,_scon,&string,x
 * M_EXECUTE:
 *	stack: x   --to--   string,x
 *	other: pushes a COPY of the string, not the original.
 */
_scon(l,p)
int (*l[])(),p;
{
    char *s,c;
    union value val;
    int i;

    if((status&XMODE) == M_FIXUP) ++p;
    if((status&XMODE) == M_READ) { dtype = T_CHR; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    s = l[p++];
	    val.sval = myalloc(strlen(s)+1);
	    strcpy(val.sval,s);
	    push(val);
if(dbg) printf("_scon():M_EXECUTE:sval:%s\n",val.sval);
    }
    return(p);
}

/* M_COMPILE:
 *	x icon int x   --to--   x,_icon,int,x
 * M_EXECUTE:
 *	stack: x   --to--   int,x
 */
_icon(l,p)
int (*l[])(),p;
{
    union value val;
    union loni v;
    int i;

    if((status&XMODE) == M_FIXUP) return(p+(sizeof(long)/sizeof(int)));
    if((status&XMODE) == M_READ) { dtype = T_INT; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    for(i=0; i<(sizeof(long)/sizeof(int)); i++)
		v.i_in_loni[i] = l[p++];
	    val.ival = v.l_in_loni;
	    push(val);
if(dbg) printf("_icon():M_EXECUTE:ival:%D\n",val.ival);
    }
    return(p);
}
_rcon(l,p)
int (*l[])(),p;
{
    union doni v;
    int i;
    union value val;

    if((status&XMODE) == M_FIXUP) return(p+(sizeof(double)/sizeof(int)));
    if((status&XMODE) == M_READ) { dtype = T_DBL; goto EXEC; }
    if((status&XMODE) = M_EXECUTE) {
EXEC:
	    for(i=0; i<(sizeof(double)/sizeof(int)); i++)
		v.i_in_doni[i] = l[p++];
	    val.rval = v.d_in_doni;
	    push(val);
    }
    return(p);
}

/* M_COMPILE:
 *	x val type x   --to--   x,_val,type,x
 * M_EXECUTE:
 *	stack:	place,x   --to--   value,x
 *	other: for strings, pushes a copy of the string.
 */
_val(l,p) int(*l[])(),p;
{
    union value place,val;
    int ty;

    if((status&XMODE) == M_READ) { dtype = l[p]; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    ty = l[p];
	    place = pop();
if(dbg) printf("_val():M_EXECUTE:var:%s",place.vpval->name);
	    place.plval = getplace(place.vpval);
	    if(ty==T_CHR && place.plval->sval!=0) {
		val.sval = myalloc(strlen(place.plval->sval)+1);
		strcpy(val.sval,place.plval->sval);
		push(val);
	    }
	    else push(*place.plval);
if(dbg) printf(":ival:%D:rval:%g:sval:%s\n",ty==T_INT?place.plval->ival:(long)0,
	ty==T_DBL?place.plval->rval:(double)0,ty==T_CHR?place.plval->sval:0);
    }
    return(p+1);
}

/* M_COMPILE:
 *	x store typ x   --to--    x,_store,type,x
 * M_EXECUTE:
 *	stack: value,location,x   --to--   value,x
 *		(stores value at location).
 */
_store(l,p) int(*l[])(),p;
{
    union value place,val;
    int ty;

    if((status&XMODE) == M_READ) { dtype = l[p]; goto EXEC; }
    if((status&XMODE) == M_EXECUTE) {
EXEC:
	    val = pop();
	    place = pop();
	    ty = l[p];
if(dbg) printf("_store():M_EXECUTE:var:%s:ival:%D:rval:%g:sval:%s\n",
	place.vpval->name,ty==T_INT?val.ival:(long)0,ty==T_DBL?val.rval:(double)0,ty==T_CHR?val.sval:0);
	    place.plval = getplace(place.vpval);
	    if(ty==T_CHR && place.plval->sval!=0) free(place.plval->sval);
	    (*place.plval) = val;
	    push(val);
    }
    return(p+1);
}

/* M_COMPILE:
 *	x var typ name x   --to--    x,_var,&vlist entry,x
 * M_EXECUTE:
 *	stack: x   --to--   &vlist entry,x
 * M_INPUT:
 *	(&vlist entry)->val is set to input value.
 * M_READ:
 *	Moves the data list pointers to the next data item.  If no next
 *	data item, calls ODerror.
 *	Does a "gosub" to the data item, to get its value on the stack.
 *	Does T_INT to T_CHR conversion if necessary.
 *	Pops value into vp->val.
 */
_var(l,p) int(*l[])(),p; /* same proc for any variable type */
{
    char *s;
    struct dictnode *vp;
    struct line *thislist;
    union value place,val;
    int ty,qual;

    if((status&XMODE) == M_EXECUTE) {
	    val.vpval = l[p++];
if(dbg) printf("_var():M_EXECUTE:var:(%d)%s\n",val.vpval->type_of_value,
	val.vpval->name);
	    push(val);
	    return(p);
    }
    if((status&XMODE) == M_INPUT) {
	    vp = l[p++];
	    place.plval = getplace(vp);
	    ty = (vp->type_of_value) & T_TMASK;
	    if(ty == T_INT)
		place.plval->ival = atol(int_in());
	    else if(ty == T_DBL)
		place.plval->rval = atof(real_in());
	    else /* ty == T_CHR */
		place.plval->sval = scon_in();
if(dbg) printf("_var():M_INPUT:var:(%d)%s:ival:%D:rval:%g:sval:%s\n",
vp->type_of_value,vp->name,ty==T_INT?place.plval->ival:(long)0,
ty==T_DBL?place.plval->rval:(double)0,ty==T_CHR?place.plval->sval:0);
	    return(p);
    }
    if((status&XMODE) == M_READ) {
nxdl:	    if(dlist[dlp] == 0) ODerror(l,p);	/* ran off end of dlist */
	    thislist = dlist[dlp];
	    if((thislist->code)[dlindx] == 0) {
		dlp++;
		dlindx = 2;	/* skips <_data,0> */
		goto nxdl;
	    }

	    status = M_EXECUTE;
	    dlindx = interp(thislist->code,dlindx);
	    status = M_READ;

	    val = pop();
	    vp = l[p];
	    place.plval = getplace(vp);
	    qual = vp->type_of_value&T_TMASK;
	    if(qual == T_INT) {
		if(dtype == T_DBL) {
			push(val); _rtoi(l,p); val = pop();
		}
		place.plval->ival = val.ival;
	    }
	    else if(qual == T_DBL) {
		if(dtype == T_INT) {
			push(val); _itor(l,p); val = pop();
		}
		place.plval->rval = val.rval;
	    }
	    else if(qual == T_CHR) {
		if(dtype == T_INT) {
			push(val); _itoa(l,p); val = pop();
		}
		else if(dtype == T_DBL) {
			push(val); _rtoa(l,p); val = pop();
		}
		if(place.plval->sval != 0) free(place.plval->sval);
		place.plval->sval = myalloc(strlen(val.sval)+1);
		strcpy(place.plval->sval,val.sval);
	    }
	    else VTerror(l,p);
    return(p+1);
    }
    return(p+1);
}
SHAR_EOF
if test 8663 -ne "`wc -c < 'newbs/operat.c'`"
then
	echo shar: error transmitting "'newbs/operat.c'" '(should have been 8663 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'newbs/scon_in.c'" '(1454 characters)'
if test -f 'newbs/scon_in.c'
then
	echo shar: will not over-write existing file "'newbs/scon_in.c'"
else
sed 's/^X//' << \SHAR_EOF > 'newbs/scon_in.c'
/* scon_in() -- read in a string constant using input.
 *	Format of an scon is either a quoted string, or a sequence
 *	of characters ended with a seperator (' ', '\t' or '\n' or ',').
 *
 *	In either mode, you can get funny characters into the string by
 *	"quoting" them with a '\'.
 *
 * scon_in() uses myalloc() to create space to store the string in.
 */
char *scon_in()
{
    register char c,*s;
    static char text [80];

    s = &text[0];

/* beginning state, skip seperators until something interesting comes along */

l1: c=input();
    if(c == '"') goto l2;
    else if(c=='\n' || c=='\0') {
	rdlin(bsin);
	goto l1;
    }
    else if(c==' ' || c=='\t' || c==',') goto l1;
    else goto l3;

/* have skipped unwanted material, seen a '"', read in a quoted string */

l2: c=input();
    if(c == '\n') {
	fprintf(stderr,"scon_in: unterminated string\n");
	exit(1);
    }
    else if(c == '\\') { *s++ = bslash(bsin); goto l2; }
    else if(c == '"')
	if((c=input()) == '"') {
	    *s++ = '"';
	    goto l2;
	}
	else goto done;
    else { *s++ = c; goto l2; }

/* skipped unwanted, seen something interesting, not '"', gather until sep */

l3: *s++ = c;
    c=input();
    if(c == '\\') { c = bslash(bsin); goto l3; }
    else if(c==' ' || c=='\t' || c==',' || c=='\n') goto done;
    else goto l3;

/* final state (if machine finished ok.) */

done: unput(c);
    *s++ = '\0';
    s=myalloc(strlen(text)+1);
    strcpy(s,text);
    return(s);
}
SHAR_EOF
if test 1454 -ne "`wc -c < 'newbs/scon_in.c'`"
then
	echo shar: error transmitting "'newbs/scon_in.c'" '(should have been 1454 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

sources-request@genrad.UUCP (07/31/85)

Mod.sources:  Volume 2, Issue 25
Submitted by: ukma!david (David Herron)


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	bs2/action.c
#	bs2/bsdefs.h
#	bs2/bsgram.y
#	bs2/bsgram.y.orig
#	bs2/bsint.c
#	bs2/bslib.c
#	bs2/errors.c
#	bs2/operat.c
# This archive created: Tue Jul 30 13:03:04 1985
export PATH; PATH=/bin:$PATH
if test ! -d 'bs2'
then
	echo shar: creating directory "'bs2'"
	mkdir 'bs2'
fi
echo shar: extracting "'bs2/action.c'" '(14073 characters)'
if test -f 'bs2/action.c'
then
	echo shar: will not over-write existing file "'bs2/action.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/action.c'
/* action.c -- "action" routines for interpretor.  These are the base-level
 *	routines, pointed to by the code-list.
 */

#include "bsdefs.h"

int status = 0;

/* M_COMPILE:
 *	x print x   --to--   x,_print,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	output: "string\n"
 */
_print(l,p)
int (*l[])(),p;
{
    union value s1;
    switch(status&XMODE) {
	case M_EXECUTE:
	    s1 = pop();
	    printf("%s",s1.sval);
	    if(s1.sval != 0) free(s1.sval);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default:
	    STerror("print");
    }
}

/* M_COMPILE:
 *	x rlabel name goto x     --to--    x,rlabel,lval,_goto,0,x
 *	(the 0 is for the benefit of interp())
 * M_FIXUP: nothing.
 * any other mode:
 *	stack: lval,x    --to--    x
 *	other: Thisline = lval.lval.codelist;
 *	       Thisp = lval.lval.place;
 */
_goto(l,p) int (*l[])(),p;
{
    union value lval;

    switch(status&XMODE) {
	case M_COMPILE: l[p] = 0;
	case M_FIXUP: return(++p);
	default:
	    lval = pop();
	    if(lval.lval.codelist == 0) ULerror(l,p);
	    Thisline = lval.lval.codelist;
	    Thisline--;
	    Thisp = lval.lval.place;
if(dbg) printf("_goto:EXEC:to:llent:%o:pl:%d:num:%u\n",lval.lval.codelist,
	lval.lval.place,lval.lval.codelist->num);
	    return(p);
    }
}

/* M_COMPILE:
 *	x dlabel name x    --to--    x,_dlabel,&vlist entry,x
 * M_FIXUP:
 *	Make vlist entry for "name" point to current place.
 */
_dlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;
    char *s;

    switch(status&XMODE) {
	case M_COMPILE:
	    s=gtok();
	    vp=gvadr(s,T_LBL);
	    l[p++] = vp;
	    return(p);
	case M_FIXUP:
	    vp=l[p++];
	    vp->val.lval.codelist = (int **)gllentry(l);
	    vp->val.lval.place = p;
	    return(p);
	default: return(++p);
    }
}

/* M_COMPILE:
 *	x rlabel name x    --to--     x,rlabel,&vlist entry,x
 * any other mode:
 *	push(vp->val)    (i.e.  pointer to location of label)
 */
_rlabel(l,p) int (*l[])(),p;
{
    struct dictnode *vp;
    char *s;

    switch(status&XMODE) {
	case M_COMPILE:
	    s=gtok();
	    vp=gvadr(s,T_LBL);
	    l[p++] = vp;
	    return(p);
	case M_FIXUP: return(++p);
	default:
	    vp = l[p++];
if(dbg) printf("_rlabel:M_EXECUTE:name:%s:llent:%o:place:%d\n",vp->name,
	vp->val.lval.codelist,vp->val.lval.place);
	    push(vp->val);
	    return(p);
    }
}

/* M_COMPILE:
 *	x rlabel name goto x    --to--    x,_rlabel,lval,_gosub,0,x
 *
 * M_EXECUTE:
 *	stack: lval,x   --to--   x
 *	other: saves current place (on stack) and jumps to lval.
 */
_gosub(l,p) int(*l[])(),p;
{
    union value here,there;
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP:
	    l[p++] = 0;
	    return(p);
	case M_EXECUTE:
	    there = pop();
	    here.lval.codelist = gllentry(l);
	    here.lval.place = p+1;
if(dbg) printf("_gosub:EXEC:here.l:%o:here.pl:%d:there.l:%o:there.pl:%d\n",
	here.lval.codelist,here.lval.place,there.lval.codelist,there.lval.place);
	    push(here);
	    Thisline = there.lval.codelist;
	    Thisline--;
	    Thisp = there.lval.place;
	    return(p);
	default: STerror("gosub");
    }
}

_return(l,p) int(*l[])(),p;
{
    union value loc;
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP:
	    l[p++] = 0;
	    return(p);
	case M_EXECUTE:
	    loc = pop();
	    Thisp = loc.lval.place;
	    Thisline = loc.lval.codelist;
	    Thisline--;
	    return(p);
	default:
	    STerror("return");
    }
}

/* Routines control entering and leaving of loops.
 *
 *	enter -- makes a mark that we have entered a loop, and also records
 *		 branch points for "continue" and "leave".
 *	exitlp -- undoes the mark made by enter.
 *	contin -- branches to "continue" point.
 *	leave -- branches to "leave" point.
 *
 * The following stack structure is used to record these loop markers.
 */

struct loopstack {
	struct label contlb,leavlb;
};

struct loopstack lpstk[20];
int lpstkp = -1;	/* -1 when stack is empty.
			 * always points to CURRENT loop marker.
			 */

/* M_COMPILE:
 *	x rlabel contlb rlabel leavlb enter x
 *--to--
 *	x,_rlabel,contlb,_rlabel,_leavlb,_enter,x
 *
 * M_EXECUTE:
 *	loopstack: x    --to--   <contlb,leavlb>,x
 */
_enter(l,p) int (*l[])(),p;
{
    union value loc;

    if((status&XMODE) == M_EXECUTE) {
	lpstkp++;
	loc = pop();
if(dbg) printf("_enter:EXEC:lpsp:%d:leav.list:%o:leav.pl:%d",lpstkp,
	loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].leavlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].leavlb.place = loc.lval.place;
	loc = pop();
if(dbg) printf(":cont.list:%o:cont.pl:%d\n",loc.lval.codelist,loc.lval.place);
	lpstk[lpstkp].contlb.codelist = loc.lval.codelist;
	lpstk[lpstkp].contlb.place = loc.lval.place;
    }
    return(p);
}

/* M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x    --to--   x
 *	other: ensures that lpstkp doesnt get less that -1;
 */
_exitlp(l,p) int (*l[])(),p;
{
    if((status&XMODE) == M_EXECUTE)
	if(lpstkp >= 0)
	    lpstkp--;
	else
	    lpstkp = -1;
if(dbg) printf("_exitlp:M_%d:lpstkp:%d\n",status,lpstkp);
    return(p);
}

/* M_COMPILE:
 *	x leave x   --to--   x,_leave,0,x
 *	(the 0 is for the benefit of interp())
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: branches to leavlb.  exitlp takes care of cleaning up stack.
 */
_leave(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    if(lpstkp == -1) /* not inside a loop, ergo cannot leave a loop */
		LVerror(l,p);
	    Thisline = lpstk[lpstkp].leavlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].leavlb.place;
	    return(p);
	default: STerror("leave");
    }
}

/* M_COMPILE:
 *	x contin x    --to--    x,_contin,0,x
 *
 * M_EXECUTE:
 *	loopstack: <contlb,leavlb>,x   --to--   <contlb,leavlb>,x
 *	other: jumps to contlb.
 */
_contin(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    if(lpstkp == -1) /* cannot continue a loop we're not in */
		CNerror(l,p);
	    Thisline = lpstk[lpstkp].contlb.codelist;
	    Thisline--;
	    Thisp = lpstk[lpstkp].contlb.place;
	    return(p);
	default: STerror("contin");
    }
}



/* M_COMPILE:
 *	x rlabel name if x    --to--   x,_rlabel,vp,if,0,x
 *	(the 0 is for the benefit for interp()).
 * M_EXECUTE:
 *	stack: loc,bool,x     --to--   x
 *	p: if bool, p=p else p=loc->place
 */
_if(l,p)
int (*l[])(),p;
{
    union value bv,lv;

    switch(status&XMODE) {
	case M_EXECUTE:
	    lv = pop();
	    bv = pop();
if(dbg) printf("_if:M_EXECUTE:lv.pl:%d:p:%d:bv.iv:%D\n",lv.lval.place,
	p,bv.ival);
	    if(bv.ival == (long)0) { /* jump to else part. */
		Thisline = lv.lval.codelist;
		Thisline--;
		Thisp = lv.lval.place;
	    }
	    else p++;	/* skip the 0 so we get to the then part */
	    return(p);
	case M_FIXUP:
	case M_COMPILE: l[p++] = 0; return(p);
	default: STerror("if");
    }
}

/* M_COMPILE:
 *	var name <from>expr <to>expr <step>expr <flag>con 0 dlabel FORx rlabel FORx+1 for
 *--to--
 *	_var,vp,<from>,<to>,<step>,<flag>,0,_dlabel,lblp,_rlabel,lblp2,_for
 *
 * M_EXECUTE:
 *	stack: xitpt,vizd,step,to,from,vp,x
 *	other: if exit conditions are correct, jump to exit point.
 *		vizd is used to hold the data type for vp.  Data types
 *		are always non-zero so the test for the first visit to
 *		the loop is to see if vizd is 0.
 */
_for(l,p) int(*l[])(),p;
{
    union value xitpt,vizd,from,to,step,place;

    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: l[p++] = 0; return(p);
	case M_EXECUTE:
	    xitpt = pop();	vizd = pop();
	    step = pop();	to = pop();
	    from = pop();
if(dbg) printf("_for:EXEC:xit.l:%o:xit.pl:%d:viz.iv:%D:step.iv:%D:to.iv:%D:from.iv:%D:",
	xitpt.lval.codelist,xitpt.lval.place,(long)vizd.ival,(long)step.ival,(long)to.ival,(long)from.ival);
	    if(vizd.ival == 0) { /* first visit to loop */
		place = pop();
if(dbg) printf("first time:var:%s:",place.vpval->name);
		vizd.ival = place.vpval->type_of_value&T_TMASK; /* != 0 */
		place.plval = getplace(place.vpval);
		*(place.plval) = from;	/* since first time, set starting val */
if(dbg) printf("var.pl:%o:var.val:%D:",place.plval,(long)place.plval->ival);
		if(vizd.ival==T_INT && step.ival==0)
			if(to.ival < from.ival)
				step.ival = -1;
			else
				step.ival = 1;
		else if(vizd.ival==T_DBL && step.rval==0)
			if(to.rval < from.rval)
				step.rval = -1;
			else
				step.rval = 1;
	    }
	    else place = pop();
if(dbg) printf("var.place:%o:",place.plval);

	    /* The stack frame is now correctly popped off.
	     * Next, we check if the loop is finished.
	     */

	    if(vizd.ival == T_INT)
		if(step.ival<0 && place.plval->ival<to.ival) goto loop_done;
		else if(step.ival>0 && place.plval->ival>to.ival) goto loop_done;
	    else /* vizd.ival == T_DBL */
		if(step.rval<0 && place.plval->rval<to.rval) goto loop_done;
		else if(step.rval>0 && place.plval->rval>to.rval) goto loop_done;

	    /* Loop is not done yet, push back stack frame. */

if(dbg) printf("loop not done, push everything back\n");
	    push(place);	push(from);	push(to);
	    push(step);		push(vizd);	push(xitpt);
	    return(p);

	/* Come here when the loop is finished. */
loop_done:
if(dbg) printf("loop done, jump to xitpt\n");
	    Thisline = xitpt.lval.codelist;
	    Thisline--;
	    Thisp = xitpt.lval.place;
	    return(p);
	default: STerror("for");
    }
}

/* M_COMPILE:
 *	var name next rlabel FORx go@ dlabel FORx+1
 *--to--
 *	_var,vp,_next,_rlabel,lblp,_go_at,dlabel,lblp2
 *
 * M_EXECUTE:
 *	stack: same as M_EXECUTE in _for.
 *	other: adds step to (control var)->val.
 */
_next(l,p) int(*l[])(),p;
{
    union value vp,xitpt,vizd,step,to,from,place;

    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: return(p);
	case M_EXECUTE:
	    vp = pop();
if(dbg) printf("_next():EXEC:var:%s",vp.vpval->name);
	    vp.plval = getplace(vp.vpval);
if(dbg) printf(":vp.pl:%o:",vp.plval);
	    xitpt = pop();	vizd = pop();	step = pop();
	    to = pop();		from = pop();	place = pop();
if(dbg) printf("pl.pl:%o:from.iv:%D:to.iv:%D:step.iv:%D:viz.iv:%D:",
	place.plval,(long)from.ival,(long)to.ival,(long)step.ival,(long)vizd.ival);
if(dbg) printf("xit.list:%o:xit.pl:%d:xit.num:%u\n",xitpt.lval.codelist,
	xitpt.lval.place,xitpt.lval.codelist->num);
	    if(place.plval != vp.plval) FNerror(l,p);
	    if(vizd.ival == T_INT)
		place.plval->ival += step.ival;
	    else
		place.plval->rval += step.rval;
	    push(place);	push(from);	push(to);	
	    push(step);		push(vizd);	push(xitpt);
	    return(p);
	default: STerror("next");
    }
}

/* variables needed for M_READ. */

struct line *dlist[DLSIZ];
int dlp = 0;
int dlindx = 2;		/* skips <_data,0> */
int dtype;		/* type of last operation. */


/* M_COMPILE:
 *	x data x     --to--    x,_data,0,x     (0 is for interp())
 * M_FIXUP:
 *	allocates a spot in dlist, stores pointer to llist entry for
 *	this line at that spot.
 * M_EXECUTE:
 *	Returns, with p pointing at the zero, making interp() return.
 */
_data(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_COMPILE:
	    l[p++] = 0;
	    return(p);
	case M_FIXUP:
	    dlist[dlp++] = gllentry(l);
	    p++;
	case M_EXECUTE: return(p);
	default:
	    STerror("data");
    }
}

/* M_COMPILE:  x dsep x   --to--   x,_dsep,0,x
 */
_dsep(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP:
	    l[p++] = 0;
	case M_READ:
	case M_EXECUTE: return(p);
	default: STerror("dsep");
    }
}

/* routines for changing the interpretors state. */

struct statstk {	/* for saving old states */
	int stkp;
	int stat;
} sstk[30];
int sstktop = 0;

/* M_COMPILE:
 *	x pushstate <state> x    --to--    x,pushstate,<state>,x
 * M_FIXUP:
 *	skip <state>
 * any other state:
 *	save old state and stack pointer.
 *	set state to <state>.
 */
_pushstate(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
	case M_FIXUP: return(++p);
	default:
	    sstk[sstktop].stkp = stackp;
	    sstk[sstktop].stat = status;
	    sstktop++;
	    status = l[p++];
	    return(p);
    }
}
_popstate(l,p) int (*l[])(),p;
{
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: return(p);
	default:
	    sstktop--;
	    stackp = sstk[sstktop].stkp;
	    status = sstk[sstktop].stat&XMODE;
	    return(p);
    }
}


/* stack maintanence routines.
 */


/* M_COMPILE:
 *	x spop x    --to--    x,_spop,x
 * M_EXECUTE:
 *	stack: string,x   --to--   x
 *	other: frees storage used by string (if any).
 */
_spop(l,p) int(*l[])(),p;
{
    union value s;

    switch(status&XMODE) {
	case M_EXECUTE:
	    s=pop();
	    if(s.sval != 0) free(s.sval);
	case M_COMPILE: return(p);
	case M_FIXUP: return(p);
	default:
	    STerror("spop");
    }
}

/* M_COMPILE:
 *	x pop x    --to--    x,_pop,x
 * M_EXECUTE:
 *	stack: int,x    --to--   x
 */
_pop(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_EXECUTE: pop(); return(p);
	default:
	    STerror("pop");
    }
}

_stop(l,p) int(*l[])(),p;
{
    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_EXECUTE: exit(1);
	default:
	    STerror("stop");
    }
}
_end(l,p) int (*l[])(),p; { return(_stop(l,p)); }


/* operator list for the intermediate language. */
struct wlnode wlist[] = {
	"itoa",_itoa,	"print",_print,	"goto",_goto,	"if",_if,  "rtoa",_rtoa,
	"itor",_itor,	"rtoi",_rtoi,	"gosub",_gosub,  "return",_return,
	"scon",_scon,	"icon",_icon,	"i+",_iadd,	"-",_isub,
	"rcon",_rcon,	"r+",_radd,	"r-",_rsub,
	"i*",_imult,	"i/",_idiv,	"i%",_imod,	",",_comma,
	"r*",_rmult,	"r/",_rdiv,	";",_scolon,
	"i==",_ieq,	"s==",_seq,	"r==",_req,
	"i<>",_ineq,	"r<>",_rneq,	"s<>",_sneq,
	"i<=",_ileq,	"s<=",_sleq,	"r<=",_rleq,
	"i<",_ilt,	"s<",_slt,	"r<",_rlt,
	"i>=",_igeq,	"s>=",_sgeq,	"r>=",_rgeq,
	"i>",_igt,	"s>",_sgt,	"r>",_rgt,
	"or",_or,	"and",_and,	"val",_val,	"not",_not,
	"pop",_pop,	"spop",_spop,
	"stop",_stop,	"end",_end,	"var",_var,	"store",_store,
	"for",_for,	"next",_next,
	"dlabel",_dlabel,	"rlabel",_rlabel,
	"contin",_contin,  "leave",_leave,  "enter",_enter,  "exitlp",_exitlp,
	"data",_data,	"dsep",_dsep,
	"pushstate",_pushstate,		"popstate",_popstate,
    0,0
};

SHAR_EOF
if test 14073 -ne "`wc -c < 'bs2/action.c'`"
then
	echo shar: error transmitting "'bs2/action.c'" '(should have been 14073 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/bsdefs.h'" '(4472 characters)'
if test -f 'bs2/bsdefs.h'
then
	echo shar: will not over-write existing file "'bs2/bsdefs.h'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/bsdefs.h'
/* bsdefs.h -- definition file for bs.
 */

#include <stdio.h>
#include <ctype.h>

/* 'Machine' status */
extern int status;
#define M_COMPILE	(1<<0)
#define M_EXECUTE	(1<<1)
#define M_INPUT		(1<<2)
#define M_FIXUP		(1<<3)
#define M_READ		(1<<4)

#define XMODE	(M_COMPILE|M_EXECUTE|M_INPUT|M_FIXUP|M_READ)


/* line table. */
#define MAXLN	((unsigned)65535)
#define NUMLINES	1000
#define LASTLINE	(&llist[NUMLINES-1])

extern int (*_null[])();

struct line {
    unsigned num;
    int (**code)();
    char *text;
};

extern struct line llist[];
extern struct line *lastline;
extern struct line *Thisline;
extern int Thisp;


/* Variable types */
#define Q_NRM	0	/* nice, ordinary variable */
#define Q_ARY	1	/* array */
#define Q_BF	2	/* builtin-function */
#define Q_UFL	3	/* long user function */
#define Q_UFS	4	/* short user function */

			/* in type part, a zero value is an undefined type. */
#define T_INT	(1<<6)
#define T_CHR	(2<<6)
#define T_DBL	(3<<6)
#define T_LBL	(4<<6)

#define T_QMASK		037		/* lower 5 bits for type qualifier */
#define T_TMASK		(T_INT|T_CHR|T_DBL|T_LBL)

/* variable table */
#define VLSIZ	150

struct label {
    char *name;
    int (**codelist)();		/* what line it is on */
    int place;			/* where on the line it is. */
};
/* For arrays, storage of them is defined as follows:
 *
 *   1st item: number of dimensions in array <NDIMS>.
 *   next <NDIMS> items: size of each dimension.
 *   rest of items: the actual values.
 *
 * Until we can support varrying sized arrays this is the setup:
 *
 *   1,10,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10
 *
 * for a total size of 13 items.
 */
union value {
    long ival;		/* T_INT */
    double rval;	/* T_DBL */
    char *sval;		/* T_CHR */
    struct label lval;  /* T_LBL */
    union value *arval; /* any+Q_ARY */
    struct dictnode *vpval; /* for use when pushing variable pointers */
    union value *plval; /* for use when pushing pointers to a value */
};

struct dictnode {	/* format of vlist entry */
    char *name;
    int type_of_value;
    union value val;
};

extern struct dictnode vlist[];

/* '_' Function table */
extern
	_print(),   _goto(),	_if(),	_else(),   _for(),
	_next(),   _read(),	_data(),   _dsep(),   _spop(),
	_pop(),   _stop(),   _end(),   _dlabel(),   _rlabel(),
	_contin(),  _leave(),  _enter(),  _exitlp(),
	_iadd(),   _isub(),   _imult(),   _idiv(),   _imod(),   _comma(),
	_radd(),   _rsub(),   _rmult(),   _rdiv(),
	_scolon(),   _gosub(),   _return(),	_not(),
	_ieq(),		_req(),		_seq(),
	_ineq(),	_rneq(),	_sneq(),
	_ileq(),	_rleq(),	_sleq(),
	_ilt(),		_rlt(),		_slt(),
	_igeq(),	_rgeq(),	_sgeq(),
	_igt(),		_rgt(),		_sgt(),	_or(),		_and(),
	_itoa(),	_rtoa(),	_itor(),	_rtoi(),
	_pushstate(),	_popstate(),
	_scon(),	_rcon(),   _icon(),   _val(),   _store(),   _var();

/* interpretor operator table */
struct wlnode {
    char *name;
    int (*funct)();
};

extern struct wlnode wlist[];

/* Data table.  Array of pointers into llist.  Each is a line wich has data. */
#define DLSIZ	100
extern struct line *dlist[]; /* actual table, number of elems. is DLSIZ */
extern int dlp;		/* index into dlist for current line of data */
extern int dlindx;	/* index into current line for current data item. */
extern int dtype;	/* in M_READ, operators set this to the type of 
			 * their operation.  When the expression is done
			 * executing, this variable will indicate its type.
			 */

/* error routines */
extern int ULerror();
extern int STerror();
extern int FNerror();
extern int ODerror();
extern int BDerror();
extern int VTerror();


/* unions for storing data types in the code list */

union doni {
    double d_in_doni;
    int i_in_doni[sizeof(double)/sizeof(int)];
};
union loni {
    long l_in_loni;
    int i_in_loni[sizeof(long)/sizeof(int)];
};
union voni {
    union value v_in_voni;
    int i_in_voni[sizeof(union value)/sizeof(int)];
};


/* miscellaneous definitions. */

#define STKSIZ	500
extern union value stack[];
extern int stackp;
extern int push();
extern union value pop();

#define CSTKSIZ	5
#define BFSIZ	200	/* input buffer */
extern char pbbuf[];	/* unput() buffer */
extern char ibuf[];
extern int iptr,pbptr;
extern char input();
extern rdlin(),unput();

extern blcpy();

extern char bslash();
extern char *scon_in();
extern int num_in();

extern char *myalloc();
extern union value *getplace();
extern struct line *gllentry();

extern FILE *bsin;

extern int dbg;		/* debugging flag. */
extern long atol();
extern double atof();
SHAR_EOF
if test 4472 -ne "`wc -c < 'bs2/bsdefs.h'`"
then
	echo shar: error transmitting "'bs2/bsdefs.h'" '(should have been 4472 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/bsgram.y'" '(6761 characters)'
if test -f 'bs2/bsgram.y'
then
	echo shar: will not over-write existing file "'bs2/bsgram.y'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/bsgram.y'
	/* bsgram.y -- grammer specification for bs.
	 */
%{
#include "bsdefs.h"

char *p;		/* the generic pointer */
int i;			/* the generic counter */

struct stk {
    int stack[40];
    int stkp;
};

struct stk ifstk,whstk,forstk,repstk,lpstk;
int gomax=0; int ifmax=0; int whmax=0; int formax=0; int repmax=0; int lpmax=0;

extern char *yytext;
extern char *bsyysval;
extern int yyleng;
%}

%term EQUAL	NEQ	LE	LT	GE	WHILE
%term GT	OR	AND	NOT	RET	REPEAT
%term IF	THEN	ELSE	GOTO	GOSUB	UNTIL
%term STOP	END	INTEGER	REAL	SCONST	ELIHW
%term LET	SWORD	PRINT	INPUT	DATA	CFOR
%term FOR	TO	STEP	READ	WRITE	NEXT
%term DEFINE	LFUN	SFUN	FDEF	SYMBOL	DIM
%term VALUE	IWORD	RWORD	ROFC	LOOP	EXITIF
%term ITOR	RTOI	ITOA	RTOA	LEAVE	CONTINUE
%term POOL

%left ',' ';'
%right '='
%nonassoc OR AND
%nonassoc LE LT GE GT EQUAL NEQ
%left '+' '-'
%left '*' '/' '%'
%left UNARY
%left '('


%start lines

%%

lines		: /* empty */
		| lines line
		;

line		: lnum stat '\n'
			{ printf("\n"); }
		| '\n'
		;

lnum		: INTEGER
			{ printf(" line %s ",$1); }
		;

stat		: LET let_xpr
		| let_xpr
		| PRINT pe
			{ printf(" print "); }
		| GOTO INTEGER
			{ printf(" rlabel LN%s goto ",$2); }
		| GOSUB INTEGER
			{ printf(" rlabel LN%s gosub ",$2); }
		| LEAVE
			{ printf(" leave "); }
		| CONTINUE
			{ printf(" contin "); }
		| RET
			{ printf(" return "); }
		| IF bexpr
			{
				lpush(&ifstk,ifmax);
				printf(" rlabel IF%d if ",ifmax);
				ifmax += 2;
			}
		  THEN stat
			{
				i = ltop(&ifstk);
				printf(" rlabel IF%d goto ",i+1);
			}
		  if_else
		| INPUT 
			{ printf(" pushstate %d ",M_INPUT); }
		  var_lst
			{ printf(" popstate "); }
		| STOP
			{ printf(" stop "); }
		| END
			{ printf(" end "); }
		| FOR ivar '=' rexpr TO rexpr for_step
			{
				lpush(&forstk,formax);
				printf(" rlabel FOR%d rlabel FOR%d enter",
					formax+2,formax+1);
				printf(" icon 0 rlabel FOR%d dlabel FOR%d for ",
					formax+1,formax);
				formax += 3;
			}
		| NEXT
			{
				i = ltop(&forstk);
				printf(" dlabel FOR%d ",i+2);
			}
		  ivar
			{
				i = lpop(&forstk);
				printf(" next rlabel FOR%d goto dlabel FOR%d ",
					i,i+1);
				printf("exitlp ");
			}
		| READ { printf(" pushstate %d ",M_READ); } var_lst
			{ printf(" popstate "); }
		| DATA { printf(" data "); } data_lst
		| LOOP
			{
				lpush(&lpstk,lpmax);
				printf(" rlabel LP%d rlabel LP%d enter",
					lpmax+2,lpmax+1);
				printf(" dlabel LP%d ",lpmax);
				lpmax += 3;
			}
		| EXITIF bexpr
			{
				i = ltop(&lpstk);
				printf(" not rlabel LP%d if ",i+1);
			}
		| POOL
			{
				i = lpop(&lpstk);
				printf(" dlabel LP%d rlabel LP%d goto",i+2,i);
				printf(" dlabel LP%d exitlp ",i+1);
			}
		| WHILE
			{
				lpush(&whstk,whmax);
				printf(" rlabel WH%d rlabel WH%d enter",
					whmax+2,whmax+1);
				printf(" dlabel WH%d ",whmax);
				whmax += 3;
			}
		  bexpr
			{
				i = ltop(&whstk);
				printf(" rlabel WH%d if ",i+1);
			}
		| ELIHW
			{
				i = lpop(&whstk);
				printf(" dlabel WH%d",i+2);
				printf(" rlabel WH%d goto dlabel WH%d exitlp ",i,i+1);
			}
		| REPEAT
			{
				lpush(&repstk,repmax);
				printf(" rlabel REP%d rlabel REP%d enter",
					repmax+1,repmax+2);
				printf(" dlabel REP%d ",repmax);
				repmax += 3;
			}
		| UNTIL
			{
				i = ltop(&repstk);
				printf(" dlabel REP%d ",i+1);
			}
		  bexpr
			{
				i = lpop(&repstk);
				printf(" not rlabel REP%d if",i);
				printf(" dlabel REP%d exitlp ",i+2);
			}
		;

let_xpr		: ivar '=' rexpr
			{ printf(" rtoi store %d pop ",T_INT); }
		| rvar '=' rexpr
			{ printf(" store %d pop ",T_DBL); }
		| svar '=' sexpr
			{ printf(" store %d spop ",T_CHR); }
		;

data_lst	: rexpr
			{ printf(" dsep "); }
		| sexpr
			{ printf(" dsep "); }
		| data_lst ',' rexpr
			{ printf(" dsep "); }
		| data_lst ',' sexpr
			{ printf(" dsep "); }
		;

ind_lst		: rexpr
		| ind_lst ',' rexpr
		;

for_step	: /* empty */
			{ printf(" icon 0 "); }
		| STEP rexpr
		;

if_else		: /* empty */
			{
				i = lpop(&ifstk);
				printf(" dlabel IF%d dlabel IF%d ",i,i+1);
			}
		| ELSE { i=ltop(&ifstk); printf(" dlabel IF%d ",i); } stat
			{ i=lpop(&ifstk); printf(" dlabel IF%d ",i+1); }
		;


pe		: sexpr ','
			{ printf(" scon \"\" , "); }
		| sexpr ';'
		| sexpr
			{ printf(" scon \"\\n\" ; "); }
		| /* empty */
			{ printf(" scon \"\\n\" "); }
		;


var_lst		: ivar
		| rvar
		| svar
		| var_lst ',' var_lst
		;

sexpr		: SCONST
			{ printf(" scon \"%s\" ",$1); }
		| svar
			{ printf(" val %d ",T_CHR); }
		| rexpr
			{ printf(" rtoa "); }
		| svar '=' sexpr
			{ printf(" store %d ",T_CHR); }
		| sexpr ';' sexpr
			{ printf(" ; "); }
		| sexpr '+' sexpr
			{ printf(" ; "); }
		| sexpr ',' sexpr
			{ printf(" , "); }
		| '(' sexpr ')'
		;
sbe		: sexpr EQUAL sexpr
			{ printf(" s== "); }
		| sexpr NEQ sexpr
			{ printf(" s<> "); }
		| sexpr LE sexpr
			{ printf(" s<= "); }
		| sexpr LT sexpr
			{ printf(" s< "); }
		| sexpr GE sexpr
			{ printf(" s>= "); }
		| sexpr GT sexpr
			{ printf(" s> "); }
		;

ivar		: IWORD
			{ printf(" var %d %s ",T_INT,$1); }
		| IWORD '(' {printf(" pushstate %d ",M_EXECUTE); } ind_lst ')'
			{ printf(" popstate var %d %s ",T_INT+Q_ARY,$1); }
		;
rvar		: RWORD
			{ printf(" var %d %s ",T_DBL,$1); }
		| RWORD '(' { printf(" pushstate %d ",M_EXECUTE); } ind_lst ')'
			{ printf(" popstate var %d %s ",T_DBL+Q_ARY,$1); }
		;

svar		: SWORD
			{ printf(" var %d %s ",T_CHR,$1); }
		| SWORD '(' { printf(" pushstate %d ",M_EXECUTE); } ind_lst ')'
			{ printf(" popstate var %d %s ",T_CHR+Q_ARY,$1); }
		;



rexpr		: rvar
			{ printf(" val %d ",T_DBL); }
		| REAL
			{ printf(" rcon %s ",$1); }
		| INTEGER
			{ printf(" rcon %s ",$1); }
		| ivar
			{ printf(" val %ditor ",T_INT); }
		| rvar '=' rexpr
			{ printf(" store %d ",T_DBL); }
		| '(' rexpr ')'
		| rexpr '+' rexpr
			{ printf(" r+ "); }
		| rexpr '-' rexpr
			{ printf(" r- "); }
		| rexpr '*' rexpr
			{ printf(" r* "); }
		| rexpr '/' rexpr
			{ printf(" r/ "); }
		| '+' rexpr	%prec UNARY
		| '-' rexpr	%prec UNARY
			{ printf(" rcon -1 r* "); }
		;

rbe		: rexpr EQUAL rexpr
			{ printf(" r== "); }
		| rexpr NEQ rexpr
			{ printf(" r<> "); }
		| rexpr LE rexpr
			{ printf(" r<= "); }
		| rexpr LT rexpr
			{ printf(" r< "); }
		| rexpr GE rexpr
			{ printf(" r>= "); }
		| rexpr GT rexpr
			{ printf(" r> "); }
		;
bexpr		: sbe
		| rbe
		| NOT bexpr	%prec UNARY
			{ printf(" not "); }
		| bexpr OR bexpr
			{ printf(" or "); }
		| bexpr AND bexpr
			{ printf(" and "); }
		| '(' bexpr ')'
		;
%%

main()
{
    rdlin(bsin);
    return(yyparse());
}

yyerror(s)
char *s;
{
    fprintf(stderr,"%s\n",s);
}

lpush(stack,val) struct stk *stack; int val;
{ stack->stack[stack->stkp++] = val; }

int ltop(stack) struct stk *stack;
{ return(stack->stack[stack->stkp-1]); }

int lpop(stack) struct stk *stack;
{ return(stack->stack[--stack->stkp]); }
SHAR_EOF
if test 6761 -ne "`wc -c < 'bs2/bsgram.y'`"
then
	echo shar: error transmitting "'bs2/bsgram.y'" '(should have been 6761 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/bsgram.y.orig'" '(7701 characters)'
if test -f 'bs2/bsgram.y.orig'
then
	echo shar: will not over-write existing file "'bs2/bsgram.y.orig'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/bsgram.y.orig'
	/* bsgram.y -- grammer specification for bs.
	 */
%{
#include "bsdefs.h"

char *p;		/* the generic pointer */
int i;			/* the generic counter */

struct stk {
    int stack[40];
    int stkp;
};

struct stk ifstk,whstk,forstk,repstk,lpstk;
int gomax=0; int ifmax=0; int whmax=0; int formax=0; int repmax=0; int lpmax=0;

extern char *yytext;
extern char *bsyysval;
extern int yyleng;
%}

%term EQUAL	NEQ	LE	LT	GE	WHILE
%term GT	OR	AND	NOT	RET	REPEAT
%term IF	THEN	ELSE	GOTO	GOSUB	UNTIL
%term STOP	END	INTEGER	REAL	SCONST	ELIHW
%term LET	SWORD	PRINT	INPUT	DATA	CFOR
%term FOR	TO	STEP	READ	WRITE	NEXT
%term DEFINE	LFUN	SFUN	FDEF	SYMBOL	DIM
%term VALUE	IWORD	RWORD	ROFC	LOOP	EXITIF
%term ITOR	RTOI	ITOA	RTOA	LEAVE	CONTINUE
%term POOL

%left ',' ';'
%right '='
%nonassoc OR AND
%nonassoc LE LT GE GT EQUAL NEQ
%left '+' '-'
%left '*' '/' '%'
%left UNARY
%left '('


%start lines

%%

lines		: /* empty */
		| lines line
		;

line		: lnum stat '\n'
			{ printf("\n"); }
		| '\n'
		;

lnum		: INTEGER
			{ printf(" line %s ",$1); }
		;

stat		: LET let_xpr
		| let_xpr
		| PRINT pe
			{ printf(" print "); }
		| GOTO INTEGER
			{ printf(" rlabel LN%s goto ",$2); }
		| GOSUB INTEGER
			{ printf(" rlabel LN%s gosub ",$2); }
		| LEAVE
			{ printf(" leave "); }
		| CONTINUE
			{ printf(" contin "); }
		| RET
			{ printf(" return "); }
		| IF bexpr
			{
				lpush(&ifstk,ifmax);
				printf(" rlabel IF%d if ",ifmax);
				ifmax += 2;
			}
		  THEN stat
			{
				i = ltop(&ifstk);
				printf(" rlabel IF%d goto ",i+1);
			}
		  if_else
		| INPUT { printf(" pushstate %d ",M_INPUT); } var_lst
			{ printf(" popstate "); }
		| STOP
			{ printf(" stop "); }
		| END
			{ printf(" end "); }
		| FOR ivar '=' iexpr TO iexpr for_step
			{
				lpush(&forstk,formax);
				printf(" rlabel FOR%d rlabel FOR%d enter",
					formax+2,formax+1);
				printf(" icon 0 rlabel FOR%d dlabel FOR%d for ",
					formax+1,formax);
				formax += 3;
			}
		| NEXT
			{
				i = ltop(&forstk);
				printf(" dlabel FOR%d ",i+2);
			}
		  ivar
			{
				i = lpop(&forstk);
				printf(" next rlabel FOR%d goto dlabel FOR%d ",
					i,i+1);
				printf("exitlp ");
			}
		| READ { printf(" pushstate %d ",M_READ); } var_lst
			{ printf(" popstate "); }
		| DATA { printf(" data "); } data_lst
		| LOOP
			{
				lpush(&lpstk,lpmax);
				printf(" rlabel LP%d rlabel LP%d enter",
					lpmax+2,lpmax+1);
				printf(" dlabel LP%d ",lpmax);
				lpmax += 3;
			}
		| EXITIF bexpr
			{
				i = ltop(&lpstk);
				printf(" not rlabel LP%d if ",i+1);
			}
		| POOL
			{
				i = lpop(&lpstk);
				printf(" dlabel LP%d rlabel LP%d goto",i+2,i);
				printf(" dlabel LP%d exitlp ",i+1);
			}
		| WHILE
			{
				lpush(&whstk,whmax);
				printf(" rlabel WH%d rlabel WH%d enter",
					whmax+2,whmax+1);
				printf(" dlabel WH%d ",whmax);
				whmax += 3;
			}
		  bexpr
			{
				i = ltop(&whstk);
				printf(" rlabel WH%d if ",i+1);
			}
		| ELIHW
			{
				i = lpop(&whstk);
				printf(" dlabel WH%d",i+2);
				printf(" rlabel WH%d goto dlabel WH%d exitlp ",i,i+1);
			}
		| REPEAT
			{
				lpush(&repstk,repmax);
				printf(" rlabel REP%d rlabel REP%d enter",
					repmax+1,repmax+2);
				printf(" dlabel REP%d ",repmax);
				repmax += 3;
			}
		| UNTIL
			{
				i = ltop(&repstk);
				printf(" dlabel REP%d ",i+1);
			}
		  bexpr
			{
				i = lpop(&repstk);
				printf(" not rlabel REP%d if",i);
				printf(" dlabel REP%d exitlp ",i+2);
			}
		;

let_xpr		: ivar '=' iexpr
			{ printf(" store %d pop ",T_INT); }
		| rvar '=' rexpr
			{ printf(" store %d pop ",T_DBL); }
		| svar '=' sexpr
			{ printf(" store %d spop ",T_CHR); }
		;

data_lst	: iexpr
			{ printf(" dsep "); }
		| rexpr
			{ printf(" dsep "); }
		| sexpr
			{ printf(" dsep "); }
		| data_lst ',' iexpr
			{ printf(" dsep "); }
		| data_lst ',' rexpr
			{ printf(" dsep "); }
		| data_lst ',' sexpr
			{ printf(" dsep "); }
		;

ind_lst		: iexpr
		| ind_lst ',' iexpr
		;

for_step	: /* empty */
			{ printf(" icon 0 "); }
		| STEP iexpr
		;

if_else		: /* empty */
			{
				i = lpop(&ifstk);
				printf(" dlabel IF%d dlabel IF%d ",i,i+1);
			}
		| ELSE { i=ltop(&ifstk); printf(" dlabel IF%d ",i); } stat
			{ i=lpop(&ifstk); printf(" dlabel IF%d ",i+1); }
		;


pe		: sexpr ','
			{ printf(" scon \"\" , "); }
		| sexpr ';'
		| sexpr
			{ printf(" scon \"\\n\" ; "); }
		| /* empty */
			{ printf(" scon \"\\n\" "); }
		;


var_lst		: ivar
		| rvar
		| svar
		| var_lst ',' var_lst
		;

sexpr		: SCONST
			{ printf(" scon \"%s\" ",$1); }
		| svar
			{ printf(" val %d ",T_CHR); }
		| iexpr
			{ printf(" itoa "); }
		| rexpr
			{ printf(" rtoa "); }
		| svar '=' sexpr
			{ printf(" store %d ",T_CHR); }
		| sexpr ';' sexpr
			{ printf(" ; "); }
		| sexpr '+' sexpr
			{ printf(" ; "); }
		| sexpr ',' sexpr
			{ printf(" , "); }
		| '(' sexpr ')'
		;
sbe		: sexpr EQUAL sexpr
			{ printf(" s== "); }
		| sexpr NEQ sexpr
			{ printf(" s<> "); }
		| sexpr LE sexpr
			{ printf(" s<= "); }
		| sexpr LT sexpr
			{ printf(" s< "); }
		| sexpr GE sexpr
			{ printf(" s>= "); }
		| sexpr GT sexpr
			{ printf(" s> "); }
		;

ivar		: IWORD
			{ printf(" var %d %s ",T_INT,$1); }
		| IWORD '(' {printf(" pushstate %d ",M_EXECUTE); } ind_lst ')'
			{ printf(" popstate var %d %s ",T_INT+Q_ARY,$1); }
		;
rvar		: RWORD
			{ printf(" var %d %s ",T_DBL,$1); }
		| RWORD '(' { printf(" pushstate %d ",M_EXECUTE); } ind_lst ')'
			{ printf(" popstate var %d %s ",T_DBL+Q_ARY,$1); }
		;

svar		: SWORD
			{ printf(" var %d %s ",T_CHR,$1); }
		| SWORD '(' { printf(" pushstate %d ",M_EXECUTE); } ind_lst ')'
			{ printf(" popstate var %d %s ",T_CHR+Q_ARY,$1); }
		;

iexpr		: ivar
			{ printf(" val %d ",T_INT); }
		| INTEGER
			{ printf(" icon %s ",$1); }
		| REAL
			{ printf(" rcon %s rtoi ",$1); }
		| ivar '=' iexpr
			{ printf(" store %d ",T_INT); }
		| RTOI '(' rexpr ')'
			{ printf(" rtoi "); }
		| '(' iexpr ')'
		| iexpr '+' iexpr
			{ printf(" i+ "); }
		| iexpr '-' iexpr
			{ printf(" i- "); }
		| iexpr '*' iexpr
			{ printf(" i* "); }
		| iexpr '/' iexpr
			{ printf(" i/ "); }
		| iexpr '%' iexpr
			{ printf(" i%% "); }
		| '+' iexpr	%prec UNARY
		| '-' iexpr	%prec UNARY
			{ printf(" icon -1 i* "); }
		;

ibe		: iexpr EQUAL iexpr
			{ printf(" i== "); }
		| iexpr NEQ iexpr
			{ printf(" i<> "); }
		| iexpr LE iexpr
			{ printf(" i<= "); }
		| iexpr LT iexpr
			{ printf(" i< "); }
		| iexpr GE iexpr
			{ printf(" i>= "); }
		| iexpr GT iexpr
			{ printf(" i> "); }
		;

rexpr		: rvar
			{ printf(" val %d ",T_DBL); }
		| REAL
			{ printf(" rcon %s ",$1); }
		| INTEGER
			{ printf(" rcon %s ",$1); }
		| rvar '=' rexpr
			{ printf(" store %d ",T_DBL); }
		| ITOR '(' iexpr ')'
			{ printf(" itor "); }
		| '(' rexpr ')'
		| rexpr '+' rexpr
			{ printf(" r+ "); }
		| rexpr '-' rexpr
			{ printf(" r- "); }
		| rexpr '*' rexpr
			{ printf(" r* "); }
		| rexpr '/' rexpr
			{ printf(" r/ "); }
		| '+' rexpr	%prec UNARY
		| '-' rexpr	%prec UNARY
			{ printf(" rcon -1 r* "); }
		;

rbe		: rexpr EQUAL rexpr
			{ printf(" r== "); }
		| rexpr NEQ rexpr
			{ printf(" r<> "); }
		| rexpr LE rexpr
			{ printf(" r<= "); }
		| rexpr LT rexpr
			{ printf(" r< "); }
		| rexpr GE rexpr
			{ printf(" r>= "); }
		| rexpr GT rexpr
			{ printf(" r> "); }
		;
bexpr		: sbe
		| ibe
		| rbe
		| NOT bexpr	%prec UNARY
			{ printf(" not "); }
		| bexpr OR bexpr
			{ printf(" or "); }
		| bexpr AND bexpr
			{ printf(" and "); }
		| '(' bexpr ')'
		;
%%

main()
{
    rdlin(bsin);
    return(yyparse());
}

yyerror(s)
char *s;
{
    fprintf(stderr,"%s\n",s);
}

lpush(stack,val) struct stk *stack; int val;
{ stack->stack[stack->stkp++] = val; }

int ltop(stack) struct stk *stack;
{ return(stack->stack[stack->stkp-1]); }

int lpop(stack) struct stk *stack;
{ return(stack->stack[--stack->stkp]); }
SHAR_EOF
if test 7701 -ne "`wc -c < 'bs2/bsgram.y.orig'`"
then
	echo shar: error transmitting "'bs2/bsgram.y.orig'" '(should have been 7701 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/bsint.c'" '(12093 characters)'
if test -f 'bs2/bsint.c'
then
	echo shar: will not over-write existing file "'bs2/bsint.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/bsint.c'
/* 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];


/* bslash() -- have seen '\', use input() to say what is actually wanted.
 */
char bslash()
{
    char text[8];
    register char *s,c;
    int v;

    c=input();
    if(c == 'n') c='\n';
    else if(c == 't') c='\t';
    else if(c == 'b') c='\b';
    else if(c == 'r') c='\r';
    else if(c == 'f') c='\f';
    else if(c>='0' && c<='7') { /* octal digit string */
	s = &text[0];
	*s++ = c;
	c=input();
	while(c>='0' && c<='7') {
		*s++ = c;
		c=input();
	}
	*s++ = '\0';
	sscanf(text,"%o",&v);
	c = (char) v;
    }
    else if(c=='\n') rdlin(bsin);
    return(c);
}


/* scon_in() -- read in a string constant using input.
 *	Format of an scon is either a quoted string, or a sequence
 *	of characters ended with a seperator (' ', '\t' or '\n' or ',').
 *
 *	In either mode, you can get funny characters into the string by
 *	"quoting" them with a '\'.
 *
 * scon_in() uses myalloc() to create space to store the string in.
 */
char *scon_in()
{
    register char c,*s;
    static char text [80];

    s = &text[0];

/* beginning state, skip seperators until something interesting comes along */

l1: c=input();
    if(c == '"') goto l2;
    else if(c=='\n' || c=='\0') {
	rdlin(bsin);
	goto l1;
    }
    else if(c==' ' || c=='\t' || c==',') goto l1;
    else goto l3;

/* have skipped unwanted material, seen a '"', read in a quoted string */

l2: c=input();
    if(c == '\n') {
	fprintf(stderr,"scon_in: unterminated string\n");
	exit(1);
    }
    else if(c == '\\') { *s++ = bslash(bsin); goto l2; }
    else if(c == '"')
	if((c=input()) == '"') {
	    *s++ = '"';
	    goto l2;
	}
	else goto done;
    else { *s++ = c; goto l2; }

/* skipped unwanted, seen something interesting, not '"', gather until sep */

l3: *s++ = c;
    c=input();
    if(c == '\\') { c = bslash(bsin); goto l3; }
    else if(c==' ' || c=='\t' || c==',' || c=='\n') goto done;
    else goto l3;

/* final state (if machine finished ok.) */

done: unput(c);
    *s++ = '\0';
    s=myalloc(strlen(text)+1);
    strcpy(s,text);
    return(s);
}

/* int_in() -- tokenizer routine for inputting a number.
 * int_in() returns a pointer to a static data area.  This area gets 
 * overwritten with each call to int_in so use the data before calling
 * int_in() again.
 */
char * int_in()
{
    register char c,*s;
    static char text[20];

    s = &text[0];

/* beginning state, skip junk until either '-' or ['0'-'9'] comes along */

l1: c=input();
    if(c>='0' && c<='9') goto l3;
    else if(c == '-') goto l2;
    else {
	if(c=='\n' || c=='\0') rdlin(bsin);
	goto l1;
    }

/* skipped junk, seen '-', gather it and make sure next char is a digit */

l2: *s++ = c;
    c=input();
    if(c==' ' || c=='\t') goto l2; /* allow white between sign and digit */
    else if(c>='0' && c<='9') goto l3;
    else { /* seen something not allowed. */
	s = &text[0];
	printf("\n\007??");
	goto l1; /* restart machine */
    }

/* skipped junk, seen a digit, gather until a non-digit appears */

l3: *s++ = c;
    c=input();
    if(c>='0' && c<='9') goto l3;
    else {
	/* have reached successful conclusion to machine. */
	unput(c);
	*s++ = '\0';
	return(text);
    }
}

/* real_in() -- read in a floating point number using input().
 *
 * real_in() returns a pointer to a static data area.  This data area
 * gets overwritten with each call to real_in(), so use it quickly.
 */
char *real_in()
{
    register char *s,c;
    static char bf[30];

    s = &bf[0];

/* starting state.  loops back until something interesting seen */

state1:	c=input();
	if(c == '-') goto state3;
	else if(c>='0' && c<='9') goto state2;
	else if(c == '.') goto state4;
	else {
		if(c=='\n' || c=='\0') rdlin(bsin);
		goto state1;
	}

/* seen a digit.  gather all digits following. */

state2: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state2;
	else if(c == '.') goto state4;
	else goto state9;	/* done */

/* seen a sign character before start of number.  loop back for whitespace. */

state3: *s++ = c;
state3_a: c=input();
	if(c==' ' || c=='\t') goto state3_a;
	else if(c>='0' && c<='9') goto state2;
	else if(c == '.') goto state4;
	else goto state10;	/* error, had a sign so we have to have digs. */

/* seen digit(s) and a decimal point. looking for more digs or ('e'|'E') */

state4: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state5;
	else if(c=='e' || c=='E') goto state6;
	else goto state9;	/* done */

/* seen (digs '.' dig).  look for more digs or ('e'|'E'). */

state5:	*s++ = c;
	c=input();
	if(c=='e' || c=='E') goto state6;
	else if(c>='0' && c<='9') goto state5;
	else goto state9;

/* seen (digs '.' digs (e|E)). looking for sign or digs, else error. */

state6: *s++ = c;
	c=input();
	if(c=='+' || c=='-') goto state7;
	else if(c>='0' && c<='9') goto state8;
	else goto state10;	/* error */

/* seen (digs '.' digs (e|E) sign). looking for digs, else error. */

state7: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state8;
	else goto state10;	/* error */

/* seen (digs '.' digs (e|E) [sign] dig). looking for digs. */

state8: *s++ = c;
	c=input();
	if(c>='0' && c<='9') goto state8;
	else goto state9;	/* done */

/* seen a complete number.  machine successfully completed.  whew! */

state9: unput(c);	/* might want that later */
	*s++ = '\0';
	return(bf);

/* Uh oh.  An error.  Print an error and restart. */

state10: printf("\n\007??");
	goto state1;
}

/* 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);
}

/* gvadr() -- Get variable address from vlist, with type checking.
 *	This routine allows numerous copies of same name as long as
 *	all copies have different types.  Probably doesnt matter since
 *	the parser does the type checking.
 */
struct dictnode *gvadr(s,ty)
char *s;
int ty;
{
    register int i;
    register int qual; /* type qualifier */

    for(i=0; vlist[i].name!=0 && i<VLSIZ; i++)
	if(vlist[i].type_of_value==ty && strcmp(s,vlist[i].name)==0)
		break; /* match found */
    if(i >= VLSIZ) {
	fprintf(stderr,"gvadr: out of room in variable list for %s\n",s);
	exit(1);
    }
    if(vlist[i].name == 0) { /* not on list, enter it */
	vlist[i].name = myalloc(strlen(s)+1);
	strcpy(vlist[i].name,s);
	vlist[i].val.rval = 0;
	vlist[i].type_of_value = ty;
	if(ty&T_QMASK == Q_ARY)
	    vlist[i].val.arval = myalloc(13*sizeof(union value));
    }
    return(&vlist[i]);
}

/* getplace() -- get a pointer to place of value for vlist entry on top of stack
 *	For arrays, getplace() expects the indexes to be on the stack as well.
 *	The parser should properly arrange for this to happen.
 */
union value *getplace(dp)
struct dictnode *dp;
{
    int qual;
    union value ind,*place;

    qual = dp->type_of_value&T_QMASK;
    if(qual == Q_ARY) {
	ind = pop();
	mpop();
	place = & dp->val.arval[ind.ival+2];
    }
    else
	place = & dp->val;
    return(place);
}

/* 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();
}
SHAR_EOF
if test 12093 -ne "`wc -c < 'bs2/bsint.c'`"
then
	echo shar: error transmitting "'bs2/bsint.c'" '(should have been 12093 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/bslib.c'" '(1553 characters)'
if test -f 'bs2/bslib.c'
then
	echo shar: will not over-write existing file "'bs2/bslib.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/bslib.c'
/* bslib.c -- subroutine library, routines useful anywhere.
 */

#include "bsdefs.h"

XFILE *bsin = stdin;

/* blcpy -- copies a block of memory (l bytes) from s to d.
 */
blcpy(d,s,l)
char *d,*s;
int l;
{
    for(; l >= 0; (l--)) *(d++) = *(s++);
}

/* Input routines.  These routines buffer input a line at a time into
 * ibuf.  Unputted input goes to pbbuf, and gets read before things in
 * ibuf, if anything in pbbuf.
 */

char pbbuf[CSTKSIZ],ibuf[BFSIZ];

int iptr = -1;
int pbptr = -1;

char input()
{
    if(pbptr > -1)
	return(pbbuf[pbptr--]);
    else {
	if(ibuf[iptr] == '\0') rdlin(bsin);
	if(ibuf[iptr]!='\0' && !feof(bsin))
	    return(ibuf[iptr++]);
	else
	    return(0);
    }
}

rdlin(f) FILE *f;
{
    char c;

    iptr = 0;
    for(c=fgetc(f); c!='\n' && c!=EOF; c=fgetc(f)) ibuf[iptr++] = c;
    ibuf[iptr++] = c;
    ibuf[iptr++] = '\0';
    iptr = 0;
}

unput(c) char c;
{ pbbuf[++pbptr] = c; }

/* myalloc() -- allocate, checking for out of memory.
 */
char *myalloc(nb)
int nb;
{
    char *rval;
    rval = malloc(nb);
/*
    printf("myalloc:tos:%o,rv:%o,nb:%d,e:%o\n",&rval,rval,nb,sbrk(0));
*/
    if(rval == 0) {
	fprintf(stderr,"myalloc: out of memory\n");
	exit(1);
    }
    return(rval);
}



/* Stack routines.  Very simple. */

union value stack[STKSIZ];
int stackp = -1;

push(i) union value i;
{
    stack[++stackp] = i;
}

union value pop()
{
    return(stack[stackp--]);
}

/* Mark stack.  Also very simple. */
int mstack[5];
int mstkp = -1;
mpush()
{ mstack[++mstkp] = stackp; }
mpop()
{ stackp = mstack[mstkp--]; }
SHAR_EOF
if test 1553 -ne "`wc -c < 'bs2/bslib.c'`"
then
	echo shar: error transmitting "'bs2/bslib.c'" '(should have been 1553 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/errors.c'" '(1583 characters)'
if test -f 'bs2/errors.c'
then
	echo shar: will not over-write existing file "'bs2/errors.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/errors.c'
/* errors.c -- error message routines for int.
 */

#include "bsdefs.h"


/* ULerror() -- unknown line (cannot find wanted line)
 */
ULerror(l,p) int(*l[])(),p;
{
    fprintf(stderr,"Unknown line %d\n",*(l[p]));
    exit(1);
}

/* STerror() -- wrong value for status variable
 */
XSTerror(f) char *f;
{
    fprintf(stderr,"%s: illegal status %o\n",f,status);
    exit(1);
}
/* FNerror() -- For Next error
 */
XFNerror(l,p)
int (*l[])(),p;
{
    struct dictnode *nv;
    struct line *ll;

    ll = gllentry(l);
    nv = l[p-2];
    fprintf(stderr,"Next %s, For (something else), at line %u\n",
	nv->name,ll->num);
    exit(1);
}

ODerror(l,p)
int (*l[])(),p;
{
    struct line *ll;
    char *s;
    ll = gllentry(l);
    s = ((struct dictnode *)l[p])->name;
    fprintf(stderr,"Out of Data in line %u at var %s\b",ll->num,s);
    exit(1);
}

BDerror(l,p)
int (*l[])(),p;
{
    struct line *ll;
    char *s;
    ll = gllentry(l);
    s = ((struct dictnode *)l[p])->name;
    fprintf(stderr,"Bad Data type in line %u at var %s\n",ll->num,s);
    exit(1);
}

VTerror(l,p)
int (*l[])(),p;
{
    struct dictnode *vp;
    vp = (struct dictnode *)l[p];
    fprintf(stderr,"Invalid data type %d for var %s\n",vp->type_of_value,vp->name);
    exit(1);
}

LVerror(l,p) int(*l[])(),p;
{
    struct line *ll;
    ll = gllentry(l);
    fprintf(stderr,"Tried to leave while not in a loop, at line %u\n",ll->num);
    exit(1);
}

CNerror(l,p) int(*l[])(),p;
{
    struct line *ll;
    ll = gllentry(l);
    fprintf(stderr,"Tried to continue while not in a loop, at line %u\n",ll->num);
    exit(1);
}
SHAR_EOF
if test 1583 -ne "`wc -c < 'bs2/errors.c'`"
then
	echo shar: error transmitting "'bs2/errors.c'" '(should have been 1583 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/operat.c'" '(9158 characters)'
if test -f 'bs2/operat.c'
then
	echo shar: will not over-write existing file "'bs2/operat.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/operat.c'
/* operat.c -- operations, as opposed to actions.  FOR is an action,
 *	'+' is an operation.
 *
 * More operators can be found in the machine generated file "operat2.c".
 */

#include "bsdefs.h"


/*	BINARY OPERATORS	*/

/* Common description for the binary ops.
 *  also applies to all ops in operat2.c
 *
 * M_COMPILE:
 *	x op x   --to--   x,_op,x
 * M_EXECUTE:
 *	stack: ar2,ar1,x   --to--   (ar1 op ar2),x
 */


_comma(l,p) int (*l[])(),p;
{
    union value s1,s2,s3;
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: return(p);
	case M_READ: dtype = T_CHR;
	case M_EXECUTE:
	    s1 = pop();
	    s2 = pop();
	    s3.sval = myalloc(strlen(s1.sval)+strlen(s2.sval)+3);
	    strcpy(s3.sval,s2.sval);
	    strcat(s3.sval,"\t");
	    strcat(s3.sval,s1.sval);
	    if(s1.sval != 0) free(s1.sval);
	    if(s2.sval != 0) free(s2.sval);
	    push(s3);
	    return(p);
	default: STerror("comma");
    }
}
_scolon(l,p) int(*l[])(),p;
{
    union value s1,s2,s3;
    switch(status&XMODE) {
	case M_COMPILE:
	case M_FIXUP: return(p);
	case M_READ: dtype = T_CHR;
	case M_EXECUTE:
	    s1 = pop();
	    s2 = pop();
	    s3.sval = myalloc(strlen(s1.sval)+strlen(s2.sval)+2);
	    strcpy(s3.sval,s2.sval);
	    strcat(s3.sval,s1.sval);
	    push(s3);
	    if(s1.sval != 0) free(s1.sval);
	    if(s2.sval != 0) free(s2.sval);
	    return(p);
	default:
	    STerror("scolon");
    }
}
/* last of binary operators */

/* M_COMPILE:
 *	x not x    --to--    x,_not,x
 * M_EXECUTE:
 *	stack: bool,x    --to--     !(bool),x
 */
_not(l,p) int (*l[])(),p;
{
    union value val;

    if((status&XMODE) == M_EXECUTE) {
	val = pop();
	val.ival = ! val.ival;
	push(val);
    }
    return(p);
}

/* M_COMPILE:
 *	x itoa x   --to--   x,_itoa,x
 * M_EXECUTE:
 *	stack: int,x   --to--   string,x
 */
_itoa(l,p)
int (*l[])(),p;
{
    union value val;
    char s2[30];

    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_READ:
	    dtype = T_CHR;
	case M_EXECUTE:
	    val=pop();
	    sprintf(s2,"%D",val.ival);	/* optimize later */
if(dbg) printf("_icon():M_EXECUTE:ival:%D to sval:%s\n",val.ival,s2);
	    val.sval=myalloc(strlen(s2)+1);
	    strcpy(val.sval,s2);
	    push(val);
	    return(p);
	default:
	    STerror("itoa");
    }
}
_rtoa(l,p)
int (*l[])(),p;
{
    union value val;
    char s2[30];

    switch(status&XMODE) {
	case M_FIXUP:
	case M_COMPILE: return(p);
	case M_READ: dtype = T_CHR;
	case M_EXECUTE:
	    val = pop();
	    sprintf(s2,"%g",val.rval);
if(dbg) printf("_rtoa():M_EXECUTE:rval:%g to sval:%s\n",val.rval,s2);
	    val.sval = myalloc(strlen(s2)+1);
	    strcpy(val.sval,s2);
	    push(val);
	    return(p);
	default: STerror("rtoa");
    }
}
_itor(l,p)
int (*l[])(),p;
{
    union value v1,v2;

    switch(status&XMODE) {
	case M_READ: dtype = T_DBL;
	case M_EXECUTE:
	    v1 = pop();
	    v2.rval = (double)v1.ival;
	    push(v2);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default: STerror("itor");
    }
}
_rtoi(l,p)
int (*l[])(),p;
{
    union value v1,v2;

    switch(status&XMODE) {
	case M_READ: dtype = T_INT;
	case M_EXECUTE:
	    v1 = pop();
	    v2.ival = (int)v1.rval;
	    push(v2);
	case M_FIXUP:
	case M_COMPILE: return(p);
	default: STerror("rtoi");
    }
}

/* M_COMPILE:
 *	x scon "quoted string" x   --to--   x,_scon,*string,x
 * M_EXECUTE:
 *	stack: x   --to--   string,x
 *	other: pushes a COPY of the string, not the original.
 */
_scon(l,p)
int (*l[])(),p;
{
    char *s,c;
    union value val;
    int i;

    switch(status&XMODE) {
	case M_COMPILE:
	    l[p++] = scon_in();
	    return(p);
	case M_READ:
	    dtype = T_CHR;
	case M_EXECUTE:
	    s = l[p++];
	    val.sval = myalloc(strlen(s)+1);
	    strcpy(val.sval,s);
	    push(val);
if(dbg) printf("_scon():M_EXECUTE:sval:%s\n",val.sval);
	    return(p);
	case M_FIXUP: p++; return(p);
	default: STerror("scon");
    }
}

/* M_COMPILE:
 *	x icon int x   --to--   x,_icon,int,x
 * M_EXECUTE:
 *	stack: x   --to--   int,x
 */
_icon(l,p)
int (*l[])(),p;
{
    union value val;
    union loni v;
    int i;

    switch(status&XMODE) {
	case M_COMPILE:
	    v.l_in_loni = atol(int_in());
	    for(i=0; i<(sizeof(long)/sizeof(int)); i++)
		l[p++] = v.i_in_loni[i];
	    return(p);
	case M_READ: dtype = T_INT;
	case M_EXECUTE:
	    for(i=0; i<(sizeof(long)/sizeof(int)); i++)
		v.i_in_loni[i] = l[p++];
	    val.ival = v.l_in_loni;
	    push(val);
if(dbg) printf("_icon():M_EXECUTE:ival:%D\n",val.ival);
	    return(p);
	case M_FIXUP:
	    p += (sizeof(long)/sizeof(int));
	    return(p);
	default: STerror("icon");
    }
}
_rcon(l,p)
int (*l[])(),p;
{
    union doni v;
    int i;
    union value val;

    switch(status&XMODE) {
	case M_COMPILE:
	    v.d_in_doni = atof(real_in());
	    for(i=0; i<(sizeof(double)/sizeof(int)); i++)
		l[p++] = v.i_in_doni[i];
	    return(p);
	case M_FIXUP:
	    p += (sizeof(double)/sizeof(int));
	    return(p);
	case M_READ: dtype = T_DBL;
	case M_EXECUTE:
	    for(i=0; i<(sizeof(double)/sizeof(int)); i++)
		v.i_in_doni[i] = l[p++];
	    val.rval = v.d_in_doni;
	    push(val);
	    return(p);
	default: STerror("rcon");
    }
}

/* M_COMPILE:
 *	x val type x   --to--   x,_val,type,x
 * M_EXECUTE:
 *	stack:	place,x   --to--   value,x
 *	other: for strings, pushes a copy of the string.
 */
_val(l,p) int(*l[])(),p;
{
    union value place,val;
    int ty;

    switch(status&XMODE) {
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
	case M_READ:
	    dtype = l[p];
	case M_EXECUTE:
	    ty = l[p];
	    place = pop();
if(dbg) printf("_val():M_EXECUTE:var:%s",place.vpval->name);
	    place.plval = getplace(place.vpval);
	    if(ty==T_CHR && place.plval->sval!=0) {
		val.sval = myalloc(strlen(place.plval->sval)+1);
		strcpy(val.sval,place.plval->sval);
		push(val);
	    }
	    else push(*place.plval);
if(dbg) printf(":ival:%D:rval:%g:sval:%s\n",ty==T_INT?place.plval->ival:(long)0,
	ty==T_DBL?place.plval->rval:(double)0,ty==T_CHR?place.plval->sval:0);
	case M_FIXUP: p++; return(p);
	default: STerror("val");
    }
}

/* M_COMPILE:
 *	x store typ x   --to--    x,_store,type,x
 * M_EXECUTE:
 *	stack: value,location,x   --to--   value,x
 *		(stores value at location).
 */
_store(l,p) int(*l[])(),p;
{
    union value place,val;
    int ty;

    switch(status&XMODE) {
	case M_COMPILE:
	    l[p++] = atoi(int_in());
	    return(p);
	case M_READ:
	    dtype = l[p];
	case M_EXECUTE:
	    val = pop();
	    place = pop();
	    ty = l[p];
if(dbg) printf("_store():M_EXECUTE:var:%s:ival:%D:rval:%g:sval:%s\n",
	place.vpval->name,ty==T_INT?val.ival:(long)0,ty==T_DBL?val.rval:(double)0,ty==T_CHR?val.sval:0);
	    place.plval = getplace(place.vpval);
	    if(ty==T_CHR && place.plval->sval!=0) free(place.plval->sval);
	    (*place.plval) = val;
	    push(val);
	case M_FIXUP:
	    p++;
	    return(p);
	default: STerror("store");
    }
}

/* M_COMPILE:
 *	x var typ name x   --to--    x,_var,&vlist entry,x
 * M_EXECUTE:
 *	stack: x   --to--   &vlist entry,x
 * M_INPUT:
 *	(&vlist entry)->val is set to input value.
 * M_READ:
 *	Moves the data list pointers to the next data item.  If no next
 *	data item, calls ODerror.
 *	Does a "gosub" to the data item, to get its value on the stack.
 *	Does T_INT to T_CHR conversion if necessary.
 *	Pops value into vp->val.
 */
_var(l,p) int(*l[])(),p; /* same proc for any variable type */
{
    char *s;
    struct dictnode *vp;
    struct line *thislist;
    union value place,val;
    int ty,qual;

    switch(status&XMODE) {
	case M_COMPILE:
	    ty = atoi(int_in());
	    s = gtok();
	    l[p++] = gvadr(s,ty);
	    return(p);
	case M_EXECUTE:
	    val.vpval = l[p++];
if(dbg) printf("_var():M_EXECUTE:var:(%d)%s\n",val.vpval->type_of_value,
	val.vpval->name);
	    push(val);
	    return(p);
	case M_INPUT:
	    vp = l[p++];
	    place.plval = getplace(vp);
	    ty = (vp->type_of_value) & T_TMASK;
	    if(ty == T_INT)
		place.plval->ival = atol(int_in());
	    else if(ty == T_DBL)
		place.plval->rval = atof(real_in());
	    else 
		place.plval->sval = scon_in();
if(dbg) printf("_var():M_INPUT:var:(%d)%s:ival:%D:rval:%g:sval:%s\n",
vp->type_of_value,vp->name,ty==T_INT?place.plval->ival:(long)0,
ty==T_DBL?place.plval->rval:(double)0,ty==T_CHR?place.plval->sval:0);
	    return(p);
	case M_READ:
nxdl:	    if(dlist[dlp] == 0) ODerror(l,p);	/* ran off end of dlist */
	    thislist = dlist[dlp];
	    if((thislist->code)[dlindx] == 0) {
		dlp++;
		dlindx = 2;	/* skips <_data,0> */
		goto nxdl;
	    }

	    status = M_EXECUTE;
	    dlindx = interp(thislist->code,dlindx);
	    status = M_READ;

	    val = pop();
	    vp = l[p];
	    place.plval = getplace(vp);
	    qual = vp->type_of_value&T_TMASK;
	    if(qual == T_INT)
		place.plval->ival = val.ival;
	    else if(qual == T_DBL)
		place.plval->rval = val.rval;
	    else if(qual == T_CHR) {
		if(dtype == T_INT) {
			push(val); _itoa(l,p); val = pop();
		}
		else if(dtype == T_DBL) {
			push(val); _rtoa(l,p); val = pop();
		}
		if(place.plval->sval != 0) free(place.plval->sval);
		place.plval->sval = myalloc(strlen(val.sval)+1);
		strcpy(place.plval->sval,val.sval);
	    }
	    else VTerror(l,p);
	case M_FIXUP:
	    p++;
	    return(p);
	default: STerror("var");
    }
}
SHAR_EOF
if test 9158 -ne "`wc -c < 'bs2/operat.c'`"
then
	echo shar: error transmitting "'bs2/operat.c'" '(should have been 9158 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0

sources-request@genrad.UUCP (08/01/85)

Mod.sources:  Volume 2, Issue 26
Submitted by: ukma!david (David Herron)


#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	bs2/bstokens.h
#	bs2/lex.c
#	bs2/makefile
#	bs2/mkop.c
#	bs2/mkop.sh
#	bs2/mkrbop.c
#	bs2/mksop.c
#	bstest/tary.bs
#	bstest/tdata.bs
#	bstest/tdata.int
#	bstest/tf.int
#	bstest/tfor.bs
#	bstest/tfor.int
#	bstest/tgs.bs
#	bstest/tgs.int
#	bstest/tif.bs
#	bstest/tif.int
#	bstest/tloop.bs
#	bstest/tloop.int
#	bstest/trp.bs
#	bstest/trp.int
#	bstest/tst6.bs
#	bstest/tst6.int
#	bstest/twh.bs
#	bstest/twh.int
# This archive created: Tue Jul 30 13:03:40 1985
export PATH; PATH=/bin:$PATH
if test ! -d 'bs2'
then
	echo shar: creating directory "'bs2'"
	mkdir 'bs2'
fi
echo shar: extracting "'bs2/bstokens.h'" '(1017 characters)'
if test -f 'bs2/bstokens.h'
then
	echo shar: will not over-write existing file "'bs2/bstokens.h'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/bstokens.h'
# define EQUAL 257
# define NEQ 258
# define LE 259
# define LT 260
# define GE 261
# define WHILE 262
# define GT 263
# define OR 264
# define AND 265
# define NOT 266
# define RET 267
# define REPEAT 268
# define IF 269
# define THEN 270
# define ELSE 271
# define GOTO 272
# define GOSUB 273
# define UNTIL 274
# define STOP 275
# define END 276
# define INTEGER 277
# define REAL 278
# define SCONST 279
# define ELIHW 280
# define LET 281
# define SWORD 282
# define PRINT 283
# define INPUT 284
# define DATA 285
# define CFOR 286
# define FOR 287
# define TO 288
# define STEP 289
# define READ 290
# define WRITE 291
# define NEXT 292
# define DEFINE 293
# define LFUN 294
# define SFUN 295
# define FDEF 296
# define SYMBOL 297
# define DIM 298
# define VALUE 299
# define IWORD 300
# define RWORD 301
# define ROFC 302
# define LOOP 303
# define EXITIF 304
# define ITOR 305
# define RTOI 306
# define ITOA 307
# define RTOA 308
# define LEAVE 309
# define CONTINUE 310
# define POOL 311
# define UNARY 312
SHAR_EOF
if test 1017 -ne "`wc -c < 'bs2/bstokens.h'`"
then
	echo shar: error transmitting "'bs2/bstokens.h'" '(should have been 1017 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/lex.c'" '(3933 characters)'
if test -f 'bs2/lex.c'
then
	echo shar: will not over-write existing file "'bs2/lex.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/lex.c'
/* lex.c -- tokeniser
 */

#include <stdio.h>
#include <ctype.h>
#include "bstokens.h"

#define gather(c)	{ yytext[yyleng++] = c; }
#define getdig(c)	{ for(;isdigit(c);c=input()) gather(c); }

#define ERROR (-1) /* yacc won't know what -1 is, gaurantees a syntax error */

#define YYTXTSIZ	200
char yytext[YYTXTSIZ];
int yyleng;
extern char *yylval;	/* to return values to Yacc with */
extern FILE *bsin;

struct word {
    int val;
    char *name;
} words[] = {
	OR,"or",	AND,"and",	NOT,"not",	RET,"return",
	IF,"if",	THEN,"then",	ELSE,"else",	WHILE,"while",
	GOTO,"goto",	GOSUB,"gosub",	STOP,"stop",	END,"end",
	LET,"let",	PRINT,"print",	INPUT,"input",	FOR,"for",
	TO,"to",	STEP,"step",	READ,"read",	WRITE,"write",
	NEXT,"next",	DATA,"data",	ELIHW,"elihw",	REPEAT,"repeat",
	UNTIL,"until",	DEFINE,"define", LFUN,"longf",	SFUN,"shortf",
	FDEF,"file",	DIM,"dim",	SYMBOL,"symbol", VALUE,"value",
	ITOR,"itor",	ITOA,"itoa",	RTOI,"rtoi",	RTOA,"rtoa",
	CONTINUE,"continue",		LEAVE,"leave",
	LOOP,"loop",	EXITIF,"exitif",	POOL,"pool",
	-1,0
};

int yylex()
{
    char c;
    int i,j,typ;

    yylval = &yytext[0];
loop:
    c=input();
			/* tab, or space */
    if(c=='\t' || c==' ')
	goto loop;
			/* numbers start with a digit or a dot */
    else if(isdigit(c) || c=='.')
    {
	yyleng=0;
	typ=INTEGER;
	getdig(c);
	if(c == '.')
	{
	    typ = REAL;
	    gather(c);
	    c = input();
	    getdig(c);
	}
	/* at this point, SOME digits must have been read, or else error */
	if(yyleng==1 && yytext[0]=='.') goto reterr; /* only "." read */
	if(yyleng == 0) goto reterr;
	j = yyleng;		/* save end of first part */
	if(c=='e' || c=='E')	/* number raised to something */
	{
	    typ = REAL;
	    gather(c);
	    c = input();
	    if(c=='-' || c=='+') {gather(c); c=input(); }
	    getdig(c);
		/* if no digits read since end of first part,
		 * then there is an error
		 */
	    for(i=yyleng; i>=j; i--)
		if(isdigit(yytext[i]))
		    break;
	    if(i <= j) goto reterr;
	}
	unput(c);
	gather('\0');
	yylval = malloc(yyleng);
	strcpy(yylval,yytext);
	return(typ);
reterr:
	yyerror("badly formed number\n");
	return(ERROR);
    }
			/* word of some kind */
    else if(isalpha(c))
    {
	yyleng=0;
	gather(c);
	for(c=input(); isalpha(c) || isdigit(c) || c=='$' || c=='%'; c=input())
	    gather(c);
	unput(c);
	gather('\0');

	fold(yytext);
	for(i=0; words[i].val!=-1; i++)
		if(strcmp(yytext,words[i].name)==0)
			break;
	yylval = malloc(yyleng);
	strcpy(yylval,yytext);
	if(words[i].val != -1)
	    return(words[i].val);
	else
	    switch(yytext[yyleng-2]) {
		case '$': return(SWORD);
		case '%': return(IWORD);
		default: return(RWORD);
	    }
    }
			/* string constant */
    else if(c == '\"')
    {
	yyleng=0;
	for(c=input(); ;c=input())
	{
	    if(c == '\"')
		if((c=input()) == '\"')
		{
		    gather('\\');
		    gather('\"');
		}
		else break;
	    else if(c == '\\')
	    {
		gather('\\');
		c=input();
		gather(c);
		if(c == '\n') rdlin(bsin);
	    }
	    else if(c == '\n')
	    {
		fprintf(stderr,"unclosed string constant: %s\n",yytext);
		rdlin(bsin);
		return(ERROR);
	    }
	    else gather(c);
	}
	unput(c);
	gather('\0');
	yylval = malloc(yyleng);
	strcpy(yylval,yytext);
	return(SCONST);
    }
    else if(c == '=')
				/* EQUAL == '==' */
	if((c=input()) == '=')
	    return(EQUAL);
				/* ASSIGN == '=' */
	else
	    { unput(c); return('='); }
    else if(c == '<')
				/* NEQ == '<>' */
	if((c=input()) == '>')
	    return(NEQ);
				/* LE == '<=' */
	else if(c == '=')
	    return(LE);
				/* LT == '<' */
	else
	    { unput(c); return(LT); }
    else if(c == '>')
				/* GE == '>=' */
	if((c=input()) == '=')
	    return(GE);
				/* GT == '>' */
	else
	    { unput(c); return(GT); }
			/* anything else */
    else return(c);
}

/* fold(s) -- change string to all lower-case letters.
 */
fold(s) char *s;
{
    int i;
    for(i=0; s[i]!='\0'; i++)
	if(isupper(s[i]))
	    s[i] = s[i] + ('a'-'A');
    return(s);
}
SHAR_EOF
if test 3933 -ne "`wc -c < 'bs2/lex.c'`"
then
	echo shar: error transmitting "'bs2/lex.c'" '(should have been 3933 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/makefile'" '(651 characters)'
if test -f 'bs2/makefile'
then
	echo shar: will not over-write existing file "'bs2/makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/makefile'
OFILES = lex.o bsint.o action.o operat.o bslib.o errors.o
PRSO= bsgram.o lex.o bslib.o
INTO= bsint.o action.o operat2.o operat.o bslib.o errors.o

all: prs int
prs: ${PRSO}
	cc -s ${PRSO} -o prs
bsgram.o: bsgram.c bsdefs.h
	cc -c bsgram.c
bsgram.c: bsgram.y
	yacc -d bsgram.y
	mv y.tab.c bsgram.c
	mv y.tab.h bstokens.h

int: ${INTO}
	cc ${INTO} -o int

${OFILES}: bsdefs.h

operat2.o: mkop.c mkrbop.c mksop.c mkop.sh bsdefs.h
	cc mkop.c -o op
	cc mkrbop.c -o rop
	cc mksop.c -o sop
	mkop.sh >operat2.c
	cc -c operat2.c
	rm operat2.c op sop rop

pr:
	pr bsgram.y lex.c bsdefs.h bslib.c bsint.c action.c operat.c mkop.c mkrbop.c mksop.c errors.c | lpr
SHAR_EOF
if test 651 -ne "`wc -c < 'bs2/makefile'`"
then
	echo shar: error transmitting "'bs2/makefile'" '(should have been 651 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/mkop.c'" '(1199 characters)'
if test -f 'bs2/mkop.c'
then
	echo shar: will not over-write existing file "'bs2/mkop.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/mkop.c'
/* mkop.c -- make operator function for bs.
 *
 *	USAGE: op name type oper tag
 *
 * where:	name: name of function generated.
 *		type: data type of operation.
 *		oper: operator for operation.
 *		tag: structure tag name.
 *
 * This will only work with T_INT and T_DBL operators, T_CHR operations
 * do not boil down to a simple operation.
 */
#include <stdio.h>

main(argc,argv)
char **argv;
int argc;
{
    char *name,*type,*oper,*tag;

    if(argc != 5) {
	fprintf(stderr,"arg count\n");
	exit(1);
    }
    name = argv[1]; type = argv[2]; oper = argv[3]; tag = argv[4];

    printf("_%s(l,p)\n",name);
    printf("int (*l[])(),p;\n");
    printf("{\n");
    printf("    union value rg1,rg2,result;\n");
    printf("\n");
    printf("    switch(status&XMODE) {\n");
    printf("	case M_READ: dtype = T_%s;\n",type);
    printf("	case M_EXECUTE:\n");
    printf("	    rg2 = pop();\n");
    printf("	    rg1 = pop();\n");
    printf("	    result.%s = rg1.%s %s rg2.%s;\n",tag,tag,oper,tag);
    printf("	    push(result);\n");
    printf("	case M_FIXUP:\n");
    printf("	case M_COMPILE: return(p);\n");
    printf("	default: STerror(\"%s\");\n",name);
    printf("    }\n");
    printf("}\n");
}
SHAR_EOF
if test 1199 -ne "`wc -c < 'bs2/mkop.c'`"
then
	echo shar: error transmitting "'bs2/mkop.c'" '(should have been 1199 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/mkop.sh'" '(791 characters)'
if test -f 'bs2/mkop.sh'
then
	echo shar: will not over-write existing file "'bs2/mkop.sh'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/mkop.sh'
echo "/* operat2.c -- more operators for bs.  the ones that are all alike."
echo " */"
echo ""
echo "#include \"bsdefs.h\""
echo ""
op "iadd" "INT" "+" "ival"
op "radd" "DBL" "+" "rval" 
op "isub" "INT" "-" "ival" 
op "rsub" "DBL" "-" "rval" 
op "imult" "INT" "*" "ival" 
op "rmult" "DBL" "*" "rval" 
op "idiv" "INT" "/" "ival" 
op "rdiv" "DBL" "/" "rval" 
op "imod" "INT" "%" "ival" 
op "ieq" "INT" "==" "ival" 
rop "req" "=="
sop "seq" "=="
op "ineq" "INT" "!=" "ival" 
rop "rneq" "!="
sop "sneq" "!="
op "ileq" "INT" "<=" "ival" 
rop "rleq" "<="
sop "sleq" "<="
op "ilt" "INT" "<" "ival" 
rop "rlt" "<"
sop "slt" "<"
op "igeq" "INT" ">=" "ival" 
rop "rgeq" ">="
sop "sgeq" ">="
op "igt" "INT" ">" "ival" 
rop "rgt" ">"
sop "sgt" ">"
op "or" "INT" "||" "ival" 
op "and" "INT" "&&" "ival" 
SHAR_EOF
if test 791 -ne "`wc -c < 'bs2/mkop.sh'`"
then
	echo shar: error transmitting "'bs2/mkop.sh'" '(should have been 791 characters)'
fi
chmod +x 'bs2/mkop.sh'
fi # end of overwriting check
echo shar: extracting "'bs2/mkrbop.c'" '(987 characters)'
if test -f 'bs2/mkrbop.c'
then
	echo shar: will not over-write existing file "'bs2/mkrbop.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/mkrbop.c'
/* mkrbop.c -- make operator functions for bs.  (real-boolean functions.)
 *
 *	USAGE: op name oper
 *
 * where:	name: name of function generated.
 *		oper: operator for operation.
 */
#include <stdio.h>

main(argc,argv)
char **argv;
int argc;
{
    char *name,*oper;

    if(argc != 3) {
	fprintf(stderr,"arg count\n");
	exit(1);
    }
    name = argv[1]; oper = argv[2];

    printf("_%s(l,p)\n",name);
    printf("int (*l[])(),p;\n");
    printf("{\n");
    printf("    union value rg1,rg2,result;\n");
    printf("\n");
    printf("    switch(status&XMODE) {\n");
    printf("	case M_READ: dtype = T_INT;\n");
    printf("	case M_EXECUTE:\n");
    printf("	    rg2 = pop();\n");
    printf("	    rg1 = pop();\n");
    printf("	    result.ival = rg1.rval %s rg2.rval;\n",oper);
    printf("	    push(result);\n");
    printf("	case M_FIXUP:\n");
    printf("	case M_COMPILE: return(p);\n");
    printf("	default: STerror(\"%s\");\n",name);
    printf("    }\n");
    printf("}\n");
}
SHAR_EOF
if test 987 -ne "`wc -c < 'bs2/mkrbop.c'`"
then
	echo shar: error transmitting "'bs2/mkrbop.c'" '(should have been 987 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bs2/mksop.c'" '(932 characters)'
if test -f 'bs2/mksop.c'
then
	echo shar: will not over-write existing file "'bs2/mksop.c'"
else
sed 's/^X//' << \SHAR_EOF > 'bs2/mksop.c'
/* mksop.c -- make string comparator functions for bs.
 *
 *	USAGE: op name oper
 *
 * where:	name: name of function generated.
 *		oper: operator for operation.
 */
#include <stdio.h>

main(argc,argv)
char **argv;
int argc;
{
    char *name,*oper;

    if(argc != 3) {
	fprintf(stderr,"arg count\n");
	exit(1);
    }
    name = argv[1]; oper = argv[2];

    printf("_%s(l,p)\n",name);
    printf("int (*l[])(),p;\n");
    printf("{\n");
    printf("    union value rg1,rg2,result;\n");
    printf("\n");
    printf("    switch(status&XMODE) {\n");
    printf("	case M_EXECUTE:\n");
    printf("	    rg2 = pop();\n");
    printf("	    rg1 = pop();\n");
    printf("	    result.sval = strcmp(rg1.sval,rg2.sval) %s 0;\n",oper);
    printf("	    push(result);\n");
    printf("	case M_FIXUP:\n");
    printf("	case M_COMPILE: return(p);\n");
    printf("	default: STerror(\"%s\");\n",name);
    printf("    }\n");
    printf("}\n");
}
SHAR_EOF
if test 932 -ne "`wc -c < 'bs2/mksop.c'`"
then
	echo shar: error transmitting "'bs2/mksop.c'" '(should have been 932 characters)'
fi
fi # end of overwriting check
if test ! -d 'bstest'
then
	echo shar: creating directory "'bstest'"
	mkdir 'bstest'
fi
echo shar: extracting "'bstest/tary.bs'" '(113 characters)'
if test -f 'bstest/tary.bs'
then
	echo shar: will not over-write existing file "'bstest/tary.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tary.bs'
10 a=1.0
20 b(3)=2.0
30 b(2)=1.0
40 b(1)=0.0
45 print rtoa(a),rtoa(b(3)),rtoa(b(2)),rtoa(b(1)),rtoa(b(5))
50 end
SHAR_EOF
if test 113 -ne "`wc -c < 'bstest/tary.bs'`"
then
	echo shar: error transmitting "'bstest/tary.bs'" '(should have been 113 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tdata.bs'" '(134 characters)'
if test -f 'bstest/tdata.bs'
then
	echo shar: will not over-write existing file "'bstest/tdata.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tdata.bs'
10 data 10,20,15,30,5,35,12,32,0
20 read i%
30 if i%==0 then goto 200
40 print itoa(i%),
50 goto 20
200 print "\nOut of data"
210 end
SHAR_EOF
if test 134 -ne "`wc -c < 'bstest/tdata.bs'`"
then
	echo shar: error transmitting "'bstest/tdata.bs'" '(should have been 134 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tdata.int'" '(397 characters)'
if test -f 'bstest/tdata.int'
then
	echo shar: will not over-write existing file "'bstest/tdata.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tdata.int'
 line 10  data  icon 10  dsep  icon 20  dsep  icon 15  dsep  icon 30  dsep  icon 5  dsep  icon 35  dsep  icon 12  dsep  icon 32  dsep  icon 0  dsep 
 line 20  pushstate 16  var 64 i%  popstate 
 line 30  var 64 i%  val 64  icon 0  i==  if  goto 200  else 
 line 40  var 64 i%  val 64  itoa  scon "" ,  print 
 line 50  goto 20 
 line 200  scon "\nOut of data"  scon "\n" ;  print 
 line 210  end 
SHAR_EOF
if test 397 -ne "`wc -c < 'bstest/tdata.int'`"
then
	echo shar: error transmitting "'bstest/tdata.int'" '(should have been 397 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tf.int'" '(223 characters)'
if test -f 'bstest/tf.int'
then
	echo shar: will not over-write existing file "'bstest/tf.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tf.int'
 line 5  scon "Start please."  scon "\n" ;  print 
 line 6  input  var 32 a$  elst 
 line 10  var 0 i  con 1  con 10000  con 0  con 0 for 
 line 20  var 0 i  next 
 line 30  scon "Done."  scon "\n" ;  print 
 line 40  end 
SHAR_EOF
if test 223 -ne "`wc -c < 'bstest/tf.int'`"
then
	echo shar: error transmitting "'bstest/tf.int'" '(should have been 223 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tfor.bs'" '(130 characters)'
if test -f 'bstest/tfor.bs'
then
	echo shar: will not over-write existing file "'bstest/tfor.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tfor.bs'
5 for j% = 1 to 10
7 print itoa(j%);"    ";
10 for i% = 1 to 10
20 print itoa(i%);"   ";
30 next i%
32 print ""
35 next j%
50 end
SHAR_EOF
if test 130 -ne "`wc -c < 'bstest/tfor.bs'`"
then
	echo shar: error transmitting "'bstest/tfor.bs'" '(should have been 130 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tfor.int'" '(565 characters)'
if test -f 'bstest/tfor.int'
then
	echo shar: will not over-write existing file "'bstest/tfor.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tfor.int'
 line 5  var 64 j%  icon 1  icon 10  icon 0  rlabel FOR2 rlabel FOR1 enter icon 0 rlabel FOR1 dlabel FOR0 for 
 line 7  var 64 j%  val 64  itoa  scon "    "  ;  scon "" ;  print 
 line 10  var 64 i%  icon 1  icon 10  icon 0  rlabel FOR5 rlabel FOR4 enter icon 0 rlabel FOR4 dlabel FOR3 for 
 line 20  var 64 i%  val 64  itoa  scon "   "  ;  scon "" ;  print 
 line 30  dlabel FOR5  var 64 i%  next rlabel FOR3 goto dlabel FOR4 exitlp 
 line 32  scon ""  scon "\n" ;  print 
 line 35  dlabel FOR2  var 64 j%  next rlabel FOR0 goto dlabel FOR1 exitlp 
 line 50  end 
SHAR_EOF
if test 565 -ne "`wc -c < 'bstest/tfor.int'`"
then
	echo shar: error transmitting "'bstest/tfor.int'" '(should have been 565 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tgs.bs'" '(143 characters)'
if test -f 'bstest/tgs.bs'
then
	echo shar: will not over-write existing file "'bstest/tgs.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tgs.bs'
10 a%=0
20 while ( a%<20 )
29 print itoa(a%),
30 gosub 100
31 print itoa(a%),
40 elihw
50 print "Done."
60 stop
100 a%=a%+1
110 return
120 end
SHAR_EOF
if test 143 -ne "`wc -c < 'bstest/tgs.bs'`"
then
	echo shar: error transmitting "'bstest/tgs.bs'" '(should have been 143 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tgs.int'" '(408 characters)'
if test -f 'bstest/tgs.int'
then
	echo shar: will not over-write existing file "'bstest/tgs.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tgs.int'
 line 10  var 64 a%  icon 0  store 64 pop 
 line 20  loopto  var 64 a%  val 64  icon 20  i<  while 
 line 29  var 64 a%  val 64  itoa  scon "	" ;  print 
 line 30  gosub 100 
 line 31  var 64 a%  val 64  itoa  scon "	" ;  print 
 line 40  elihw 
 line 50  scon "Done."  scon "\n" ;  print 
 line 60  stop 
 line 100  var 64 a%  var 64 a%  val 64  icon 1  i+  store 64 pop 
 line 110  return 
 line 120  end 
SHAR_EOF
if test 408 -ne "`wc -c < 'bstest/tgs.int'`"
then
	echo shar: error transmitting "'bstest/tgs.int'" '(should have been 408 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tif.bs'" '(180 characters)'
if test -f 'bstest/tif.bs'
then
	echo shar: will not over-write existing file "'bstest/tif.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tif.bs'
10 a=3.0
20 input b
30 if a==b then goto 100 else goto 70
40 print "failed"
50 stop
70 print rtoa(a);" != ";rtoa(b)
80 goto 20
100 print rtoa(a);" == ";rtoa(b)
110 goto 20
120 end
SHAR_EOF
if test 180 -ne "`wc -c < 'bstest/tif.bs'`"
then
	echo shar: error transmitting "'bstest/tif.bs'" '(should have been 180 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tif.int'" '(538 characters)'
if test -f 'bstest/tif.int'
then
	echo shar: will not over-write existing file "'bstest/tif.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tif.int'
 line 10  var 192 a  rcon 3.0  store 192 pop 
 line 20  pushstate 4  var 192 b  popstate 
 line 30  var 192 a  val 192  var 192 b  val 192  r==  rlabel IF0 if  goto 100  rlabel IF1 go@  dlabel IF0  goto 70  dlabel IF1 
 line 40  scon "failed"  scon "\n" ;  print 
 line 50  stop 
 line 70  var 192 a  val 192  rtoa  scon " != "  ;  var 192 b  val 192  rtoa  ;  scon "\n" ;  print 
 line 80  goto 20 
 line 100  var 192 a  val 192  rtoa  scon " == "  ;  var 192 b  val 192  rtoa  ;  scon "\n" ;  print 
 line 110  goto 20 
 line 120  end 
SHAR_EOF
if test 538 -ne "`wc -c < 'bstest/tif.int'`"
then
	echo shar: error transmitting "'bstest/tif.int'" '(should have been 538 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tloop.bs'" '(164 characters)'
if test -f 'bstest/tloop.bs'
then
	echo shar: will not over-write existing file "'bstest/tloop.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tloop.bs'
10 loop
20    input a,b
30 exitif a==b
40    a% = rtoi(a)
50    b% = rtoi(b)
60    print "a:";(a);" a%:";(a%);" b:";(b);" b%:";(b%)
70 pool
80 print "Done."
90 end
SHAR_EOF
if test 164 -ne "`wc -c < 'bstest/tloop.bs'`"
then
	echo shar: error transmitting "'bstest/tloop.bs'" '(should have been 164 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tloop.int'" '(618 characters)'
if test -f 'bstest/tloop.int'
then
	echo shar: will not over-write existing file "'bstest/tloop.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tloop.int'
 line 10  rlabel LP2 rlabel LP1 enter dlabel LP0 
 line 20  pushstate 4  var 192 a  var 192 b  popstate 
 line 30  var 192 a  val 192  var 192 b  val 192  r==  not rlabel LP1 if 
 line 40  var 64 a%  var 192 a  val 192  rtoi  store 64 pop 
 line 50  var 64 b%  var 192 b  val 192  rtoi  store 64 pop 
 line 60  scon "a:"  var 192 a  val 192  rtoa  ;  scon " a%:"  ;  var 64 a%  val 64  itoa  ;  scon " b:"  ;  var 192 b  val 192  rtoa  ;  scon " b%:"  ;  var 64 b%  val 64  itoa  ;  scon "\n" ;  print 
 line 70  dlabel LP2 rlabel LP0 goto dlabel LP1 exitlp 
 line 80  scon "Done."  scon "\n" ;  print 
 line 90  end 
SHAR_EOF
if test 618 -ne "`wc -c < 'bstest/tloop.int'`"
then
	echo shar: error transmitting "'bstest/tloop.int'" '(should have been 618 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/trp.bs'" '(74 characters)'
if test -f 'bstest/trp.bs'
then
	echo shar: will not over-write existing file "'bstest/trp.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/trp.bs'
10 repeat
20 print "Guess ";
30 input a
40 until ( rtoi(a) == 20 )
50 end
SHAR_EOF
if test 74 -ne "`wc -c < 'bstest/trp.bs'`"
then
	echo shar: error transmitting "'bstest/trp.bs'" '(should have been 74 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/trp.int'" '(246 characters)'
if test -f 'bstest/trp.int'
then
	echo shar: will not over-write existing file "'bstest/trp.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/trp.int'
 line 10  rlabel REP1 rlabel REP2 enter dlabel REP0 
 line 20  scon "Guess "  print 
 line 30  pushstate 4  var 192 a  popstate 
 line 40  dlabel REP1  var 192 a  val 192  rtoi  icon 20  i==  not rlabel REP0 if dlabel REP2 exitlp 
 line 50  end 
SHAR_EOF
if test 246 -ne "`wc -c < 'bstest/trp.int'`"
then
	echo shar: error transmitting "'bstest/trp.int'" '(should have been 246 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tst6.bs'" '(438 characters)'
if test -f 'bstest/tst6.bs'
then
	echo shar: will not over-write existing file "'bstest/tst6.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tst6.bs'
5 l%=32000
6 h%=-32000
9 print "trailer==0, input one number at a time."
10 input a%
20 if a%==0 then goto 100
30 if a%<l% then goto 60 
40 if a%>h% then goto 80
41 print"made it through	l:";itoa(l%);"h:";itoa(h%);"a:";itoa(a%)
50 goto 10
60 l%=a%
61 print"a<l	l:";itoa(l%);"h:";itoa(h%);"a:";itoa(a%)
70 goto 10
80 h%=a%
81 print"a>h	l:";itoa(l%);"h:";itoa(h%);"a:";itoa(a%)
90 goto 10
100 print "low=";itoa(l%),"high=";itoa(h%)
110 end
SHAR_EOF
if test 438 -ne "`wc -c < 'bstest/tst6.bs'`"
then
	echo shar: error transmitting "'bstest/tst6.bs'" '(should have been 438 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/tst6.int'" '(1399 characters)'
if test -f 'bstest/tst6.int'
then
	echo shar: will not over-write existing file "'bstest/tst6.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/tst6.int'
 line 5  var 64 l%  icon 32000  store 64 pop 
 line 6  var 64 h%  icon 32000  icon -1 i*  store 64 pop 
 line 9  scon "trailer==0, input one number at a time."  scon "\n" ;  print 
 line 10  pushstate 4  var 64 a%  popstate 
 line 20  var 64 a%  val 64  icon 0  i==  rlabel IF0 if  rlabel LN100 goto  rlabel IF1 goto  dlabel IF0 dlabel IF1 
 line 30  var 64 a%  val 64  var 64 l%  val 64  i<  rlabel IF2 if  rlabel LN60 goto  rlabel IF3 goto  dlabel IF2 dlabel IF3 
 line 40  var 64 a%  val 64  var 64 h%  val 64  i>  rlabel IF4 if  rlabel LN80 goto  rlabel IF5 goto  dlabel IF4 dlabel IF5 
 line 41  scon "made it through	l:"  var 64 l%  val 64  itoa  ;  scon "h:"  ;  var 64 h%  val 64  itoa  ;  scon "a:"  ;  var 64 a%  val 64  itoa  ;  scon "\n" ;  print 
 line 50  rlabel LN10 goto 
 line 60  var 64 l%  var 64 a%  val 64  store 64 pop 
 line 61  scon "a<l	l:"  var 64 l%  val 64  itoa  ;  scon "h:"  ;  var 64 h%  val 64  itoa  ;  scon "a:"  ;  var 64 a%  val 64  itoa  ;  scon "\n" ;  print 
 line 70  rlabel LN10 goto 
 line 80  var 64 h%  var 64 a%  val 64  store 64 pop 
 line 81  scon "a>h	l:"  var 64 l%  val 64  itoa  ;  scon "h:"  ;  var 64 h%  val 64  itoa  ;  scon "a:"  ;  var 64 a%  val 64  itoa  ;  scon "\n" ;  print 
 line 90  rlabel LN10 goto 
 line 100  scon "low="  var 64 l%  val 64  itoa  ;  scon "high="  ,  var 64 h%  val 64  itoa  ;  scon "\n" ;  print 
 line 110  end 
SHAR_EOF
if test 1399 -ne "`wc -c < 'bstest/tst6.int'`"
then
	echo shar: error transmitting "'bstest/tst6.int'" '(should have been 1399 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/twh.bs'" '(201 characters)'
if test -f 'bstest/twh.bs'
then
	echo shar: will not over-write existing file "'bstest/twh.bs'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/twh.bs'
9 print "Guess a number ";
10 input a
20 while ( rtoi(a) <> 20)
25 gosub 100
30 elihw
40 print "You guessed it!"
100 print "Do it again ";
110 input a
111 print "number is ";rtoa(a)
120 return
200 end
SHAR_EOF
if test 201 -ne "`wc -c < 'bstest/twh.bs'`"
then
	echo shar: error transmitting "'bstest/twh.bs'" '(should have been 201 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'bstest/twh.int'" '(549 characters)'
if test -f 'bstest/twh.int'
then
	echo shar: will not over-write existing file "'bstest/twh.int'"
else
sed 's/^X//' << \SHAR_EOF > 'bstest/twh.int'
 line 9  scon "Guess a number "  scon "" ;  print 
 line 10  pushstate 4  var 192 a  popstate 
 line 20  rlabel WH2 rlabel WH1 enter dlabel WH0  var 192 a  val 192  rtoi  icon 20  i<>  rlabel WH1 if 
 line 25  rlabel LN100 gosub 
 line 30  dlabel WH2 rlabel WH0 goto dlabel WH1 exitlp 
 line 40  scon "You guessed it!"  scon "\n" ;  print 
 line 100  scon "Do it again "  scon "" ;  print 
 line 110  pushstate 4  var 192 a  popstate 
 line 111  scon "number is "  var 192 a  val 192  rtoa  ;  scon "\n" ;  print 
 line 120  return 
 line 200  end 
SHAR_EOF
if test 549 -ne "`wc -c < 'bstest/twh.int'`"
then
	echo shar: error transmitting "'bstest/twh.int'" '(should have been 549 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0