A BASIC interpretor (Part 3 of 4)

sources-request at genrad.UUCP sources-request at genrad.UUCP
Wed Jul 31 20:18:37 AEST 1985


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



More information about the Mod.sources mailing list