|
|
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: 11235 (0x2be3)
Types: TextFile
Names: »bas6.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/basic/bas6.c«
/*
* BASIC by Phil Cockcroft
*/
#include "bas.h"
#ifdef V7
#include <sys/ioctl.h>
#endif
/*
* This file contains all the routines to implement terminal
* like files.
*/
/*
* setupfiles is called only once, it finds out how many files are
* required and allocates buffers for them. It will also execute
* 'silly' programs that are given as parameters.
*/
setupfiles(argc,argv)
char **argv;
{
register int fp;
register int nfiles=2;
register struct filebuf *p;
char *q;
extern memp sbrk();
#ifdef NOEDIT
noedit=1;
#endif
while(argc > 1 ){
q = *++argv;
if(*q++ !='-')
break;
if(isnumber(*q)){
nfiles= atoi(q);
if(nfiles<0 || nfiles > MAXFILES)
nfiles=2;
}
else if(*q=='x')
noedit=1;
else if(*q=='e')
noedit=0;
argc--;
}
filestart= sbrk(0);
fendcore= filestart+(sizeof(struct filebuf) * nfiles);
brk(fendcore+sizeof(xlinnumb) ); /* allocate enough core */
for(p = (filebufp)filestart ; p < (filebufp)fendcore ; p++){
p->filedes=0;
p->userfiledes=0;
p->use=0;
p->nleft=0;
}
/* code added to execute silly programs */
if(argc <= 1)
return;
if((fp=open(*argv,0))!=-1)
runfile(fp);
prints("file not found\n");
_exit(1);
}
/*
* This routine executes silly programs. It has to load up
* the program and then simulate the environment as is usually seen
* in main. It works....
*/
runfile(fp)
{
int firsttime;
register lpoint p;
setupterm(); /* set up terminal - now done after files */
ecore= fendcore+sizeof(xlinnumb);
( (lpoint) fendcore )->linnumb=0;
firsttime=1; /* flag to say that we are just loading */
setexit(); /* the file at the moment */
if(ertrap) /* setexit is the return for error */
goto execut; /* and execute */
if(!firsttime) /* an error or cntrl-c */
quit();
firsttime=0;
readfi(fp);
clear(DEFAULTSTRING);
p= (lpoint)fendcore;
stocurlin=p;
if(!(curline=p->linnumb)) /* is this needed - yes */
quit();
point= p->lin;
elsecount=0;
runmode=1; /* go and run it */
execut:
execute();
}
/* commands implemented are :-
open / creat
close
input
print
*/
/* syntax of commands :-
open "filename" for input as <filedesc>
open "filename" [for output] as <filedesc>
close <filedesc> ,[<filedesc>]
input #<filedesc> , v1 , v2 , v3 ....
print #<filedesc> , v1 , v2 , v3 ....
*/
/* format of file buffers added 17-12-81
struct {
int filedes; / * Unix file descriptor
int userfiledes; / * name by which it is used
int posn; / * position of cursor in file
int dev; / * dev and inode are used to
int inode; / * stop r/w to same file
int use; / * r/w etc. + other info
int nleft; / * number of characters in buffer
char buf[BLOCKSIZ]; / * the actual buffer
} file_buffer ;
The file_buffers are stored between the end of initialised data
and fendcore. uses sbrk() at start up.
At start up there are two buffer spaces allocated.
*/
/*
* The 'open' command it allocates file descriptors and buffer
* space then sets about opening the file and checking weather the
* the file is opened already and then checks to see if that file
* was opened for reading or writing. It stops files being read and
* written at the same time
*/
fopen()
{
char chblock[256];
register struct filebuf *p;
register struct filebuf *q;
register int c;
int i;
int append=0;
int bl = 0;
int mode= _READ;
struct stat inod;
stringeval(chblock);
chblock[gcursiz]=0;
c=getch();
if(c== FOR){
c=getch();
if(c== OUTPUT)
mode = _WRITE;
else if(c== APPEND){
append++;
mode = _WRITE;
}
else if(c== TERMINAL)
mode = _TERMINAL;
else if(c != INPUT)
error(SYNTAX);
c=getch();
}
if(c!= AS)
error(SYNTAX);
i=evalint();
#ifdef _BLOCKED
if(getch() == ','){
bl = evalint();
if(bl <= 0 || bl > 255)
error(10);
}
else
point--;
#endif
check();
/* here we have mode set. i is the file descriptor 1-9
now check to see if already allocated then allocate the descriptor
and open file etc. */
if(i<1 || i>MAXFILES)
error(29);
for(q=0,p = (filebufp)filestart ; p < (filebufp)fendcore ; p++){
if(i== p->userfiledes)
error(29);
else if(!p->userfiledes && !q)
q=p;
}
if(!(p=q)) /* out of file descriptors */
error(31);
/* code to check to see if file is open twice */
if(stat(chblock,&inod)!= -1){
if( (inod.st_mode & S_IFMT) == S_IFDIR)
if(mode== _READ ) /* cannot deal with directories */
error(15);
else
error(14);
for(q = (filebufp)filestart ; q < (filebufp)fendcore ; q++)
if(q->userfiledes && q->inodnumber== inod.st_ino &&
q->device== inod.st_dev){
if(mode== _READ ){
if( q->use & mode )
break;
error(15);
}
else
error(14);
}
}
else if(mode == _TERMINAL) /* terminals */
error(15);
if(mode == _READ){
if( (p->filedes=open(chblock,0))== -1)
error(15);
}
else if(mode == _TERMINAL){
#ifdef _BLOCKED /* can't block terminals */
if(bl)
error(15);
#endif
if((p->filedes = open(chblock,2)) == -1)
error(15);
mode |= _READ | _WRITE;
}
else {
if(append){
p->filedes=open(chblock,1);
#ifndef V6C
lseek(p->filedes, 0L, 2);
#else
seek(p->filedes,0,2);
#endif
}
if(!append || p->filedes== -1)
if((p->filedes=creat(chblock,0644))== -1)
error(14);
}
p->posn = 0;
fstat(p->filedes,&inod);
#ifdef V7
ioctl(p->filedes,FIOCLEX,0); /* close on exec */
#endif
p->device= inod.st_dev; /* fill in all relevent details */
p->inodnumber= inod.st_ino;
p->userfiledes= i;
#ifdef _BLOCKED
if(bl){
p->blocksiz = bl;
mode |= _BLOCKED;
}
#endif
p->nleft=0;
p->use=mode;
normret;
}
/* the 'close' command it runs through the list of file descriptors
* and flushes all buffers and closes the file and clears all
* relevent entry in the structure
*/
fclosef()
{
register struct filebuf *p;
for(;;){
p=getf(evalint(),(_READ | _WRITE) );
if(p->use & _WRITE )
f_flush(p);
close(p->filedes);
p->filedes=0;
p->userfiledes=0;
p->nleft=0;
p->use=0;
if(getch()!=',')
break;
}
point--;
normret;
}
/* the 'seek' command thought to be neccasary
*/
fseek()
{
register struct filebuf *p;
register int j;
register long l;
if(getch() != '#')
error(SYNTAX);
p = getf(evalint(),(_READ | _WRITE)); /* get file */
if(getch() != ',')
error(SYNTAX);
eval();
if(getch() != ',')
error(SYNTAX);
if(!vartype && conv(&res))
error(FUNCT);
#ifdef _BLOCKED
if(p->use & _BLOCKED)
#ifndef pdp11
l = res.i * p->blocksiz;
#else
{ register k = 0; /* fast multiply for non */
for(l = 0 ; k < 8 ; k++) /* vax systems. this */
if(p->blocksiz & (1<<k) ) /* won't bring in the */
l += (long)res.i << k; /* library */
}
#endif
else /* watch this. note the indents */
#endif /* it is right */
l = res.i;
j = evalint();
check();
if(j < 0 || j > 5) /* out of range */
error(FUNCT);
if(p->use & _WRITE) /* flush out all buffered output */
f_flush(p);
if(j >=3){
j -= 3;
l <<= 10; /* blocks are 1024 */
}
#ifndef V6C
lseek(p->filedes, l ,j);
#else
if(l > 512)
seek(p->filedes, (int)(l >> 9) , j + 3);
seek(p->filedes,(int)l & 0777 ,j);
#endif
p->posn = 0;
p->nleft = 0;
p->use &= ~_EOF;
normret;
}
/* the 'eof' maths function eof is true if writting to the file
* or if the _EOF flag is set.
*/
eofl()
{
register struct filebuf *p;
p=getf(evalint(),(_READ | _WRITE) );
vartype=01;
if( p->use & ( _EOF | _WRITE) ){
res.i = -1;
return;
}
if(!p->nleft){
p->posn = 0;
if( (p->nleft= read(p->filedes,p->buf,BLOCKSIZ)) <= 0){
p->nleft=0;
p->use |= _EOF;
res.i = -1;
return;
}
}
res.i =0;
}
/* the 'posn' maths function returns the current 'virtual' cursor
* in the file. If the file descriptor is zero then the screen
* cursor is accessed.
*/
fposn()
{
register struct filebuf *p;
register i;
i=evalint();
vartype=01;
if(!i){
res.i =cursor;
return;
}
p=getf(i,(_READ | _WRITE) );
if(p->use & _WRITE)
res.i = p->posn;
else
res.i = 0;
}
/* getf() returns a pointer to a file buffer structure. with the
* relevent file descriptor and with the relevent access permissions
*/
struct filebuf *
getf(i,j)
register i; /* file descriptor */
register j; /* access permission */
{
register struct filebuf *p;
if(i == 0)
error(29);
j &= ( _READ | _WRITE ) ;
for(p= (filebufp)filestart ; p < (filebufp)fendcore ; p++)
if(p->userfiledes==i && ( p->use & j) )
return(p);
error(29); /* unknown file descriptor */
}
/* flushes the file pointed to by p */
f_flush(p)
register struct filebuf *p;
{
if(p->nleft ){
write(p->filedes,p->buf,p->nleft);
p->nleft=0;
}
}
/* will flush all files , for use in 'shell' and in quit */
flushall()
{
register struct filebuf *p;
for(p = (filebufp)filestart ; p < (filebufp)fendcore ; p++)
if(p->nleft && ( p->use & _WRITE ) ){
write(p->filedes,p->buf,p->nleft);
p->nleft=0;
}
}
/* closes all files and clears the relevent bits of info
* used in clear and new.
*/
closeall()
{
register struct filebuf *p;
flushall();
for(p= (filebufp)filestart ; p < (filebufp)fendcore ; p++)
if(p->userfiledes){
close(p->filedes);
p->filedes=0;
p->userfiledes=0;
p->nleft=0;
p->use=0;
}
}
/* write to a file , same as write in parameters (see print )
*/
putfile(p,q,i)
register struct filebuf *p;
register char *q;
int i;
{
register char *r;
if(!i)
return;
r= &p->buf[p->nleft];
do{
if(p->nleft >= BLOCKSIZ ){
f_flush(p);
r= p->buf;
}
*r++ = *q++;
p->nleft++;
}while(--i);
if(p->use & _TERMINAL)
f_flush(p);
}
/* gets a line into q (MAX 512 or j) from file p terminating with '\n'
* or _EOF returns number of characters read.
*/
filein(p,q,j)
register struct filebuf *p;
register char *q;
{
register char *r;
register int i=0;
if(p->use & _TERMINAL) /* kludge for terminal files */
p->use &= ~_EOF;
else if(p->use & _EOF)
return(0); /* end of file */
#ifdef _BLOCKED
if(p->use & _BLOCKED)
j = p->blocksiz;
#endif
r= &p->buf[p->posn];
for(;;){
if(!p->nleft){
r=p->buf;
if( (p->nleft= read(p->filedes,p->buf,BLOCKSIZ)) <=0){
p->nleft=0; /* a read error */
p->use |= _EOF; /* or end of file */
break;
}
}
*q= *r++;
p->nleft--;
if(++i == j){
q++;
break;
}
#ifdef _BLOCKED
if(*q++ == '\n' && !(p->use & _BLOCKED) ){
#else
if(*q++ =='\n'){
#endif
q--;
break;
}
if(i>=512){ /* problems */
p->posn= r - p->buf;
error(32);
}
} /* end of for loop */
*q=0;
if(p->use & _TERMINAL){
p->nleft = 0;
p->posn = 0;
}
else
p->posn = r - p->buf;
#ifdef _BLOCKED
if( (p->use & _BLOCKED) && j != i){
p->use |= _EOF;
p->nleft = 0;
return(0);
}
#endif
return(i);
}