|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 10749 (0x29fd)
Types: TextFile
Names: »bas4.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/basic/bas4.c«
/*
* BASIC by Phil Cockcroft
*/
#include "bas.h"
/*
* Stringeval() will evaluate a string expression of any
* form. '+' is used as the concatenation operator
*
* gblock and gcursiz are used as global variables by the
* string routines. Gblock contains the resultant string while
* gcursiz holds the length of the resultant string ( even if not
* put in gblock ).
* For routines that need more than one result e.g. mid$ instr$
* then one result at least is put on the stack while the other
* ( possibly ) is put in gblock.
*/
/*
* The parameter to stringeval() is a pointer to where the
* result will be put.
*/
stringeval(gblck)
char *gblck;
{
int cursiz=0;
memp l;
int c;
char charac;
register char *p,*q;
register int i;
int m[2];
char chblock[256];
char *ctime();
checksp();
q=chblock;
for(;;){
gcursiz=0;
c=getch();
if(c&0200){ /* a string function */
if(c==DATE){ /* date does not want a parameter */
time(m);
p=ctime(m);
gcursiz=24;
}
else {
if(c<MINSTRING || c>MAXSTRING)
error(11);
if(*point++!='(')
error(1);
(*strngcommand[c-MINSTRING])();
if(getch()!=')')
error(1);
p=gblock; /* string functions return with */
} /* result in gblock */
}
else if(c=='"' || c=='`'){ /* a quoted string */
charac=c;
p=point;
while(*point && *point!= charac){
gcursiz++;
point++;
}
if(*point)
point++;
}
else if(isletter(c)){ /* a string variable */
point--;
l=getname();
if(vartype!=02)
error(SYNTAX);
if(p= ((stdatap)l)->stpt) /* newstring routines */
gcursiz= *p++ &0377;
}
else
error(SYNTAX);
/* all routines return to here with the string pointed to by p */
if(cursiz+gcursiz>255)
error(9);
i=gcursiz;
if(getch()!='+')
break;
cursiz += i;
if(i) do
*q++ = *p++;
while(--i);
}
point--; /* the following code is */
if(!cursiz){ /* horrible but it speeds */
if(p==gblck) /* execution by reducing the amount */
return; /* of movement of strings */
cursiz=gcursiz;
}
else {
cursiz+=gcursiz;
if(i) do
*q++ = *p++;
while(--i);
p=chblock;
}
q=gblck;
gcursiz=cursiz;
if(i=cursiz)
do
*q++ = *p++;
while(--i);
}
/*
* stringassign() will put the sting in gblock into the string
* pointed to by p.
* It will call the garbage collection routine as neccasary.
*/
stringassign(p)
struct stdata *p;
{
register char *q,*r;
register int i;
p->stpt=0;
if(!gcursiz)
return;
if(estdt-eostring <gcursiz+1){
garbage();
if(estdt-eostring <gcursiz+1)
error(3); /* out of string space */
}
p->stpt=eostring;
q=eostring;
i=gcursiz;
*q++ = i;
r= gblock;
do
*q++ = *r++;
while(--i);
eostring=q;
}
/*
* This will collect all unused strings and free the space
* It works that is about all tha can be said for it.
*/
garbage() /* new string routine */
{
register char *p,*q;
register struct stdata *r;
register int j;
p=ecore;
q=ecore;
while(p<eostring){
j= (*p&0377)+1;
for(r = (stdatap)estdt ; r < (stdatap)estring ; r++)
if(r->stpt==p)
if(q==p){
p+=j;
q=p;
goto more;
}
else {
r->stpt=q;
do{
*q++ = *p++;
}while(--j);
goto more;
}
p+=j;
more: ;
}
eostring=q;
}
/*
* The following routines implement string functions they are all quite
* straight forward in operation.
*/
strng()
{
int m;
register char *q,*p;
int cursiz=0;
int siz;
register int i;
char chblock[256];
checksp();
stringeval(chblock);
cursiz=gcursiz;
if(getch()!=',')
error(1);
m=evalint();
if(m>255 || m <0)
error(10);
if(!cursiz){
gcursiz=0;
return;
}
siz=m;
if((unsigned)(cursiz * siz) >255)
error(9);
gcursiz= cursiz *siz;
p=gblock;
while(siz--)
for(q=chblock,i=cursiz;i--;)
*p++ = *q++;
}
/* left$ string function */
leftst()
{
int l1;
register int i;
register char *p,*q;
int cursiz;
char chblock[256];
checksp();
stringeval(chblock);
cursiz=gcursiz;
if(getch()!=',')
error(SYNTAX);
l1=evalint();
if(l1<0 || l1 >255)
error(10);
i=l1;
if(l1>cursiz)
i=cursiz;
p=chblock;
q=gblock;
if(gcursiz=i) do
*q++ = *p++;
while(--i);
}
/* right$ string function */
rightst()
{
int l1,l2;
register int i;
register char *p,*q;
int cursiz;
char chblock[256];
checksp();
stringeval(chblock);
cursiz=gcursiz;
if(getch()!=',')
error(SYNTAX);
l1=evalint();
if(l1<0 || l1 >255)
error(10);
l2= cursiz-l1;
i=l1;
if(i>cursiz){
i=cursiz;
l2=0;
}
p= &chblock[l2];
q= gblock;
if(gcursiz=i) do
*q++ = *p++;
while(--i);
}
/*
* midst$ string function:-
* can have two or three parameters , if third
* parameter is missing then a value of cursiz
* is used.
*/
midst()
{
int l1,l2;
int cursiz;
register int i;
register char *q,*p;
char chblock[256];
checksp();
stringeval(chblock);
cursiz=gcursiz;
if(getch()!=',')
error(1);
l1=evalint()-1;
if(getch()!=','){
point--;
l2=255;
}
else
l2=evalint();
if(l1<0 || l2<0 || l1 >255 || l2 >255)
error(10);
l2+=l1;
if(l2>cursiz)
l2=cursiz;
if(l1>cursiz)
l1=cursiz;
i= l2-l1;
p=gblock;
q= &chblock[l1];
if(gcursiz=i) do
*p++ = *q++;
while(--i);
}
/* ermsg$ string routine , returns the specified error message */
estrng()
{
register char *p,*q,*r;
int l;
l=evalint();
if(l<1 || l> MAXERR)
error(22);
p=ermesg[l-1];
q=gblock;
r=p;
while(*q++ = *p++);
gcursiz= p-r-1;
}
/* chr$ string function , returns character from the ascii value */
chrstr()
{
register int i;
i=evalint();
if(i<0 || i>255)
error(FUNCT);
*gblock= i;
gcursiz=1;
}
/* str$ string routine , returns a string representation
* of the number given. There is NO leading space on positive
* numbers.
*/
nstrng()
{
register char *p,*q;
eval();
gcvt();
if(*gblock!=' ')
return;
q=gblock;
p= gblock+1;
while(*q++ = *p++);
gcursiz= --q -gblock;
}
/* val() maths function , returns the value of a string. If
* no numeric value is used then a value of zero is returned.
*/
val()
{
register char *tmp,*p;
register minus=0;
stringeval(gblock);
gblock[gcursiz]=0;
p=gblock;
while(*p++ == ' ');
if(*--p=='-'){
p++;
minus++;
}
if(!isnumber(*p) && *p!='.'){
res.i=0;
vartype=01;
return;
}
tmp=point;
point=p;
if(!getop()){
point=tmp;
error(36);
}
point=tmp;
if(minus)
negate();
}
/* instr() maths function , returns the index of the first string
* in the second. Starting either from the first character or from
* the optional third parameter position.
*/
instr()
{
int cursiz1;
int cursiz2;
register char *p,*q,*r;
int i=0;
char chbl1ck[256];
char chbl2ck[256];
checksp();
stringeval(chbl1ck);
cursiz1=gcursiz;
if(getch()!=',')
error(SYNTAX);
stringeval(chbl2ck);
cursiz2=gcursiz;
if(getch()==','){
i=evalint()-1;
if(i<0 || i>255)
error(10);
}
else
point--;
cursiz2-=cursiz1;
vartype=01;
r= &chbl2ck[cursiz1+i];
for(;i<=cursiz2;i++,r++){
p= chbl1ck;
q= &chbl2ck[i];
while(q < r && *p== *q)
p++,q++;
if( q == r ){
res.i = i+1;
return;
}
}
res.i = 0;
}
/* space$ string function returns a string of spaces the number
* of which is the argument to the function
*/
space()
{
register int i;
register char *q;
i=evalint();
if(i<0 || i>255)
error(10);
if(gcursiz=i){
q= gblock;
do{
*q++ =' ';
}while(--i);
}
}
/* get$() read a single character from a file */
getstf()
{
register struct filebuf *p;
register i;
i=evalint();
if(!i){
if(noedit) /* illegal function with silly terminals */
error(11);
if(!trapped){
set_term();
*gblock=readc();
rset_term(0);
}
if(!trapped)
gcursiz=1;
else
gcursiz =0;
}
else {
p=getf(i,_READ);
if(!(i = filein(p,gblock,1)) )
error(30);
gcursiz=i;
}
}
/* mid$() when on the left of an assignment */
/* can have optional third argument */
/* a$ = "this is me"
* mid$(a$,2) = "hello" -> a$ = "thello"
* mid$(a$,2,5) = "hello" -> a$ = "thellos me"
*/
lhmidst()
{
char chbl1ck[256];
char chbl2ck[256];
int cursiz,rhside,i1,i2;
memp pt;
register char *p,*q;
register int i;
if(*point++ !='(')
error(SYNTAX);
pt=getname();
if(vartype!=02)
error(VARREQD);
if(getch()!=',')
error(SYNTAX);
i1=evalint()-1;
if(getch()!=','){
i2=255;
point--;
}
else
i2= evalint();
if(i2<0 || i2>255 || i1<0 || i1>255)
error(10);
if(getch()!=')' )
error(SYNTAX);
if(getch()!='=')
error(4);
cursiz=0;
if(p= ((stdatap)pt)->stpt){
cursiz=i= *p++ & 0377;
q=chbl1ck;
do{
*q++ = *p++;
}while(--i);
}
if(i1>cursiz)
i1=cursiz;
i2+=i1;
if(i2>cursiz)
i2=cursiz;
rhside= cursiz -i2;
if(i=rhside){
p=chbl2ck;
q= &chbl1ck[i2];
do{
*p++ = *q++;
}while(--i);
}
stringeval(gblock);
check();
if(gcursiz+rhside+i1>255)
error(9);
p= &chbl1ck[i1];
q= gblock;
if(i=gcursiz)
do{ /* what a lot of data movement */
*p++ = *q++;
}while(--i);
gcursiz+=i1;
q=chbl2ck;
if(i=rhside)
do{
*p++ = *q++;
}while(--i);
gcursiz+=rhside;
p=gblock;
q=chbl1ck;
if(i=gcursiz)
do{
*p++ = *q++;
}while(--i);
stringassign( (stdatap)pt ); /* done it !! */
normret;
}
#ifdef _BLOCKED
/* mkint(a$)
* routine to make the first 2 bytes of string into a integer
* for use with formatted files.
*/
mkint()
{
register short *p = (short *)gblock;
stringeval(gblock);
if(gcursiz < sizeof(short) )
error(10);
res.i = *p;
vartype = 01;
}
/* ditto for string to double */
mkdouble()
{
stringeval(gblock);
if(gcursiz < sizeof(double) )
error(10);
#ifndef V6C
res = *( (value *)gblock);
#else
movein(gblock,&res);
#endif
vartype = 0;
}
/*
* mkistr$(x%)
* convert an integer into a string for use with disk files
*/
mkistr()
{
register short *p = (short *)gblock;
eval();
if(!vartype && conv(&res))
error(FUNCT);
*p = res.i;
gcursiz = sizeof(short);
}
/* mkdstr$(x)
* ditto for doubles.
*/
mkdstr()
{
eval();
if(vartype)
cvt(&res);
#ifndef V6C
*((value *)gblock) = res;
#else
movein(&res,gblock);
#endif
gcursiz = sizeof(double);
}
#else
mkdstr(){}
mkistr(){}
mkint(){}
mkdouble(){}
#endif