fredf@uw-june (Fred Finster) (07/20/83)
This was typed in but never run. So good luck and be thankful you didnt type it in by hand. I would like anyone who puts this on a micro to report back their opinions of its operation to the net. I might play with it on a home built 6809 micro to see how well it runs. Cheers and Tears for the hackers who make it run and escape the control program for microcomputers curse ala CP/M Small C operating system as typed in from Dr. Dobb's Journal March 1983 puterr(str) Put a string to the console (cannot be redirected, used for error messages). getc(unit) Get a character from "unit," unit=0 standart input, unit=1 the communication port, returns character or 0 on end of file. putc(c,unit) Put a character to "unit" (see getc), returns "c". readf(unit) Read the next sequential group on opened file, returns 0 on end of file. writef(unit) Write the next sequential group. openf(name,buffer,fn) Open "name" for read(fn=1) write(fn=2) or append (fn=3) with "buffer" as the buffer address, returns a unit number or 0 if not found. create(name,buffer) As for openf, write assumed, any old file by that name is lost. closf(unit) Close the given unit number, flushes write buffer if required. readr(unit,N) Read n~th group from opened unit number, returns 0 if out of file group range. writer(unit,N) Write n~th group to open unit number, returns 0 if out of range. scndir(name) Scan the working directory for "name," returns number of entry in directory, 1 to n or 0 if not there. chdir(name) Look for "name" in the current directory and if it is a directory, change operations to it, if name==0 changes back to root directory of user. mkdir(name) Create a new directory "name," returns a 0 if name in use. rmfil(name,i) Remove directory entry "name," if not found, returns 0. Won't allow rmfil(".". If "i" is 0, won't allow directory entry removal. If "i" is 1, a recursive remove of the entry is undertaken, directory or file. alloc() Return the address of the next free top 512 byte block of memory. Addr will lie on a 512 byte boundary. dalloc(addr) Give back a 512 byte block of memory for future use. dirfn(i) For directory information: i=0 re- turns ptr to glinks[], i=1 returns ptr to loptr[], i=2, returns ptr to hiptr. dirio(rw) Refresh of save the directory pointer arrays: rw=1 (write) gives a save to disk, rw=2 (read) gives a refresh from disk. /** operating system written in Small-C **/ /** Brian McKeon 5/5/82 **/ #define eol 10 /* end of line char */ #define bufsiz 512 /* disk buffer size */ /** some memory control **/ #define usrprg 256 /* start and entry point of user program */ int memmap[8]; /* bitmap of 512 byte blocks of memory */ /** and directory structure **/ #define dirone 22 /* ptr to 1st grp of glinks-loptr-hiptr */ #define lnksiz 500 /* one link per 'bufsiz' bytes */ int glinks[lnksiz]; #define ptrsiz 50 /* seems to be enough */ int loptr[ptrsiz]; int hiptr[ptrsiz]; /** First few pointer pairs have special functions **/ /** zero ptrs are set to to 0 as traps **/ #define rsvptrs 4 /* reserved system pointer pairs */ #define sysdir loptr[1] /* ptr to system dir struct */ #define userdir loptr[2] /* ptr to root dir of user */ #define workdir loptr[3] /* ptr to -current- user dir structure */ #define freptr hiptr[1] /* ptr to free dotted pair list */ #define grpfree hiptr[2] /* ptr to first free disk group */ /** i/o structures **/ int stdout; /* and for standard output */ #define maxunits 10 /* max no. simul open files */ #define minunit 2 /* 0, 1 reserved for console and communication port */ int grw[maxunits]; /* 0 if free, 'rdfn' for read and 'wrfn', write */ #define rdfn 1 #define wrfn 2 #define apfn 3 /* append, used for openf call only */ /** structures to keep track of file i/o **/ int firgrp[maxunits]; /* first group of a file group list */ int lnkgrp[maxunits]; /* link group for sequential i/o */ int gbuffs[maxunits]; /* addr of the buffers assoc with a unit */ int gptrs[maxunits]; /* pointers into these buffers */ char sysinp[bufsiz]; /* system input buffer */ char sysout[bufsiz]; /* and output buffer */ /** command line argument passing to user programs **/ int argc; /* argument count */ int argv[10]; /* array of ptrs to argument strings */ /** line input buffer - argv[] strings **/ #define maxlin 128 /* max line input size */ char linbuf[maxlin]; /* line input buffer */ /** main entry point for system **/ /* call the system with the desired i/o parameters */ /* with arg0 the number of the system call */ /* */ #asm org 0a000h #endasm /* 0a000 gives blocks 1 to 79 spare */ #define maxblk 77 /* leave a couple of blocks for stack */ system(arg0,arg1,arg2,arg3) int arg0,arg1,arg2,arg3; { int munit,savedir; if(arg0==0)return (puts(arg1)); /* put str to std err */ if(arg0==1)return (getc(arg1)); /* char fetch */ if(arg0==2)return (putc(arg1,arg2)); /* char put */ if(arg0==3)return (readf(arg1)); /* sequential read */ if(arg0==4)return (writef(arg1)); /* sequential write */ if(arg0==5)return (openf(arg1,arg2,arg3)); /* open a file */ if(arg0==6)return (creatf(arg1,arg2)); /* create a file */ if(arg0==7)return (closf(arg1)); /* close a unit */ if(arg0==8)return (readr(arg1,arg2)); /* read random grp */ if(arg0==9)return (writer(arg1,arg2)); /* write random */ if(arg0==10)return (scndir(arg1)); /* scan dir for file name */ if(arg0==11)return (chdir(arg1)); /* change directory */ if(arg0==12)return (mkdir(arg1)); /* make new dir */ if(arg0==13)return (rmfil(arg1,arg2)); /* remove file-directory */ if(arg0==14)return (alloc()); /* get addr of free blk */ if(arg0==15)return (dalloc(arg1)); /* de-alloc a mem blk */ if(arg0==16)return (dirfn(arg1)); /* give addr of dir in mem */ if(arg0==17)dirio(wrfn); /* go system, save the dir */ else {inits();dirio(rdfn); puts("illegal system call >17: directory restored/n"); } while(1) /* command interpreter loop */ { inits(); /* re-initialize stk, i/o, hardware */ puts("$ "); /* prompt to user */ if((munit=getlin(linbuf))==0)continue; /* get command */ if(parslin(linbuf,munit)==0 /* parse into argc, argv */ continue; /* on parse error */ if((munit=openf(argv[0],sysinp,rdfn))==0) { if(workdir==svsdir){puts("open error/n");continue;} else { savedir=workdir; /* save the working dir */ workdir=sysdir; /* and look in the sys dir */ munit=openf(argv[0],sysinp,rdfn); workdir=savedir; if(munit==0){puts("open error/n");continue;} } } if(loadf(munit)==0)continue; /* and load the file */ closf(munit); /* close the loader unit */ usrprg(argc,argv); /* call the loaded user program */ closf(stdout); /* flush the output if any */ dirio(wrfn); /* and save the dir */ } } /* get the next line of input from the console */ /* all white space is replaced by nulls (0) for parsing */ #define backsp 8 getlin(buffa) char buffa[]; { int k; char c; k=0; while(k<maxlin) { c=inchar(); if(c==eol)break; if(c==backsp) { if(k){--k;outchar(c);} continue; } if(c<=' ')c=0; buffa[k++]=c; } buffa[k]=0; return k; } /* parse a line into argc, argv and also re-direct i/o */ parslin(str,nchar) char str[]; int nchar; { int pt,endarg; char lastc; pt=argc=0; argv[0]=&str[0]; while(1) { while(str[pt])++pt; /* move over argument */ while(str[pt]==0)++pt; /* and nulls */ if(pt>nchar)break; /* finished? */ if(str[pt]=='>') /* check for re-direction */ { if((stdout=creatf(&str[pt+1],sysout))==0) {puts("i/o redirecteion error/n");return 0;} } else if(str[pt]=='<') { if((stdin=openf(&str[pt+1],sysinp,rdfn))==0) {puts("i/o redirection error/n");return 0;} } else argv[++argc]=&str[pt]; ; return ++argc; } /* open a given file name for file i/o */ /* from the current directory */ /* rw is 'rdfn' for input, 'wrfn' for output and 'apfn' for append */ openf(name,buffer,rw) char name[],buffer[]; int rw; { int filno; if((filno=scndir(name))==0)return 0; /* find file name */ return (openit(filno,buffer,rw)); } /* lower level open operates from number entry of file in dir */ /* for example 1 would open the dir file itself */ /* the append function should only be used with null terminated */ /* files as it searches for this null char. */ openit(filno,buffer,rw) int filno; char buffer[]; int rw; { int i,k,grp; i=workdir; while(--filno)i=loptr[i]; /* down the dir list */ if(hiptr[i]<0)return 0; /* attempting to open dir? */ if((filno=findio())==0)return 0; /* any i/o units left? */ firgrp[filno]=hiptr[i]; /* pointer to first grp of file */ gbuffs[filno]=buffer; /* setup buffer location */ if(rw==rdfn) /* read? */ { grw[filno]=rdfn; lnkgrp[filno]=hiptr[i];/* read from this first group */ gptrs[filno]=bufsiz; /* initialize the pointer */ } /* DDJ page 44 */ else if(rw==wrfn) /* write ? */ { frefil(fiptr[i]); /* free up the old groups */ hiptr[i]=0; /* initially append null */ grw[filno]=wrfn; /* write */ lnkgrp[filno]=-i; /* by -, indicate a link to the dir! */ gptrs[filno]=0; /* initialize the pointer */ } else if(rw==apfn) /* append ? */ { /* get to the last group */ grp=hiptr[i]; if(glinks[grp]==0)lnkgrp[filno]=-i; else { while(glinks[glinks[grp]]!=0)grp=glinks[grp]; lnkgrp[filno]=grp; /* 2nd last grp */ grp=glinks[grp]; /* last grp */ } if(grpio(grp,buffer,rdfn)==0)return 0; /* read last grp */ frefil(grp); /* and give it up */ grw[filno]=wrfn; k=0; /* DDJ page 45 */ while(buffer[k]!=0)++k; /* go to the old eof */ gptrs[filno]=k; /* pointer now ready for append */ } return filno; } /* create a file */ creatf(name,buffa) char name[],buffa[]; { int unit,k,1,newfree; if((grpfree==0)|(freptr==0)|(name[0]==0))return 0; if(unit=openf(name,buffa,wrfn))return unit; /* in the dir? */ if((unit=openit(1,buffa,apfn))==0)return 0; /* no, open the dir */ k=workdir; /* and append the file */ while(loptr[k])k=loptr[k]; /* go down the dir list */ newfree=loptr[freptr]; /* get a new free pointer */ loptr[k]=freptr; /* and add to the directory */ loptr[freptr]=0; /* append a null */ hiptr[freptr]=0; /* and no groups */ freptr=newfree; /* up-date free pointer */ 1=0; /* errors after this point are fatal */ while(name[1]) /* append the name */ if(putc(name[1++],unit)==0) /* to the dir file */ createrr(k); if(putc(eol,unit)==0) createrr(k); closf(unit); /* and close the directory */ return (openf(name,buffa,wrfn)); /* openf should now work */ } /* fatal error routine from create function */ /* dont flush the dir buffer as there is an error somewhere */ createrr(k) int k; { int oldfree; oldfree=freptr; freptr=loptr[k]; loptr[k]=0; /* re-terminate the dir */ loptr[freptr]=oldfree; puts("fatal failure on file create/n"); system(17,0,0,0); /* and try to recover */ } /* close a given unit number */ closf(unit) int unit; { int k; k=1; /* default return value */ if(unit<minunit)return 0; /* trap illegal close */ if((grw[unit]==wrfn)&(gptrs[unit]!=0)) /* write required? */ k=writef(unit); grw[unit]=0; /* now free up this unit */ return k; } /* DDJ page 46 */ /* look for a spare unit number else return 0 */ findio() { int k; k=minunit; while(k<maxunits) {if(grw[k]==0)return k;++k;} return 0; } /* scan a directory for a matching line to the given one */ /* and return a number 1 to n, else zero if not found */ scndir(name) char name[]; { int linnum,munit,k,flg; char c; if(name[0]==0)return 0; if((munit=openit(1,sysinp,rdfn))==0)return 0; /* open dir for read */ linnum=0; while(1) { flg=1; k=0; ++linnum; while(1) { if((c=getc(munit))==0){closf(munit);return 0;} if(c==eol)break; if(c!=name[k++])flg=0; } if((name[k]==0)&flg){closf(munit);return linnum;} } } /* put an error message to the console */ puts(str) char str[]; { int j; j=0; while((outchar(str[j++]))!=0; } /* get a character from a given unit number */ getc(unit) int unit; { char c; if(unit==0)unit=stdin; /* standard in? - re-firect */ if(unit==0)return (inchar()); /* console port */ if(unit==1)return (incom()); /* communication port */ if(grw[unit]!=rdfn)return 0; /* open for read? */ if(gptrs{unit}==bufsiz) /* get pointer - empty? */ if(readf(unit)==0)return 0; c=*(gbuffs[unit]+gptrs[unit]); ++gptrs[unit]; return c; } /* DDJ page 47 */ /* sequential read of file */ readf(unit) int unit; { int nxtgrp; if(grw[unit]!=rdfn)return 0; gptrs[unit]=0; nxtgrp=lnkgrp[unit]; lnkgrp[unit]=glinks[nxtgrp]; /* update grp no. */ return (grupio(nxtgrp,gbuffs[unit],rdfn)); /* refill buffer */ } /* random read of file group, range 0 to N */ readr(unit,grpno) int unit,grpno; { int rdgrp; if(grw[unit]!=rdfn)return 0; rdgrp=firgrp[unit]; while(grpno--)rdgrp=glinks[rdgrp]; /* down the file grp list */ return (grupio(rdgrp,gbuffs[unit],rdfn)); } /* put a character to a given i/o unit */ putc(c,unit) char c; int unit; { if(unit==0)unit=stdout; /* standard out? - redirect */ if(unit==0)return (outchar(c)); /* console port */ if(unit==1)return (outcom(c)); /* communication port */ if(grw[unit]!=wrfn)return 0; /* write unit? */ if(gptrs[unit]==bufsiz) /* full buffer? */ if(writef(unit)==0)return 0; *(gbuffs[unit]+gptrs[unit])=c; ++gptrs[unit]; return c; } /* write sequential to given unit */ writef(unit) int unit; { int newgrp; if(grw[unit]!=wrfn)return 0; gptrs[unit]=0; newgrp=fregrp(); /* get a new group */ if(lnkgrp[unit]>0)glinks[lnkgrp[unit]]=newgrp; /* link */ else hiptr[-lnkgrp[unit]]=newgrp; /* special case: link to dir */ lnkgrp[unit]=newgrp; /* and ready for next call */ return (grupio(newgrp,gbuffs[unit],wrfn)); } /* random write of file group, range 0 to N */ writer(unit,grpno) int unit,grpno; { int wrgrp; if(grw[unit]!=wrfn)return 0; wrgrp=firgrp[unit]; while(grpno--)wrgrp=glinks[wrgrp]; /* down the file grp list */ return (grupio(wrgrp,gbuffs[unit],wrfn)); } /* free up a list of groups */ frefil(grp) int grp; { int fgrp; /* a pointer to the first free group */ if(grp==0)return 0; /* dont lose the free list */ fgrp=grpfree; /* a pointer to the first free group */ grpfree=grp; /* a point free list at the file */ while(glinks[grp])grp=glinks[grp]; /* go to end of file */ glinks[grp]=fgrp; /* and link on the old free list */ } /* get a free group */ /* null terminate */ fregrp() { int grp; grp=grpfree; /* find the next free group */ grpfree=glinks[grp]; /* update the free pointer */ glinks[grp]=0; /* and null terminate the returned group link */ return grp; } /* load a program, checking for oversize and for jump at start */ loadf(unit) int unit; { int grp,addr,blk; char ujump; grp=lnkgrp[unit]; /* get the first group */ addr=usrprg; /* load into the user area */ blk=addr>>9; /* and allocate mem as you go */ while(grp) { if(blk==maxblk){puts("program too large\n");return 0;} if(grupio(grp,addr,rdfn)==0){puts("load error\n");return 0;} addr=addr+bufsiz; fixblk(++blk); /* allocate the mem */ grp=glinks[grp]; } ujump=*usrprg; /* should be the jump byte if a program */ if(ujump!=-61){puts("not a program\n");return 0;} return 1; } /* DDJ page 51 */ /* save/restore the directory structure to/from disk */ dirio(rdwr) int rdwr; { int grp,addr; grp=dirone; addr=glinks; while(grp) { if(grupio(grp,addr,rdwr)==0)return 0; grp=glinks[grp]; addr=addr+bufsiz; } } /* change work directory */ chdir(name) char name[]; { int pt,n; if(name==0){workdir=userdir;return;} if((n=scndir(name))==0)return 0; pt=workdir; while(--n)pt=loptr[pt]; /* down the dir list */ if(hiptr[pt]>0)return 0; /* not a directory */ workdir=-hiptr[pt]; /* it is a dir, change */ } /* make a new directory */ mkdir(name) char name[]; { int pt,n,newfree; if(n=openf(name,sysinp,rdfn)) {closf(n);return 0;} /* name is in use ! */ if((n=creatf(name,sysinp))==0)return 0; /* cannot create */ closf(n); /* got the name entry, close it */ pt=workdir; while(loptr[pt])=loptr[pt]; /* name must be last on dir-list */ newfree=loptr[freptr]; /* get the new free pointer */ hiptr[pt]=-freptr; /* link on a call (- to indic dir) */ pt=freptr; freptr=newfree; /* update the freptr */ loptr[pt]=0; /* empty dir */ hiptr[pt]=fregrp(); /* qnd the directory file grp itself */ return (grupio(hiptr[pt],".\n",wrfn)); /* dir contains '.' only */ } /* i.e. itself */ /* remove a directory-file structure */ rmfil(name,flg) char name[]; int flg; { int n,i,preptr,pt,postptr; if((n=scndir(name))==0)return 0; /* in the dir? */ i=n; --i; if(i==0)return 0; /* dont allow rmfil(".",x) */ preptr=workdir; /* and go to the link before the entry */ while(--i)preptr=loptr[preptr]; pt=loptr[preptr]; /* the entry */ postptr=loptr[pt]; /* and the one after */ if((hiptr[pt]<0)&(flg!=1))return 0; /* remove dir? */ if(rmname(n)==0)return 0; /* now remove the n th. name */ loptr[preptr]=postptr; /* link around */ loptr[pt]=0; /* and terminate to restrain 'remove' */ remove(pt); return 1; } /* remove the n th. name from the work directory *. rmname(n) int n; { int obuf,ibuf,ounit,iunit,1,wrtflg; char c; wrtflg=obuf=iunit=ounit=0; while(1) /* but only used for one-pass flow control */ { if((ibuf=alloc())==0)return 0; if((obuf=alloc())==0)break; if((iunit=openit(1,ibuf,rdfn))==0)break; if((ounit=openit(1,obuf,wrfn))==0)break; l=1 wrtflg=1 /* writing flag */ while(c=getc(iunit)) /* DDJ page 53 */ { if(n==l)wrtflg=0; /* suppress this entry? */ if(wrtflg)putc(c,ounit); if(c==eol){++l;wrtflg=1;} } putc(0,ounit); wrtflg=1;break; } closf(iunit);closf(ounit);dalloc(ibuf);dalloc(obuf); return wrtflg; /* will be 0 on an error */ } /* recursive remove of dir-file structure */ remove(pt) int pt; { int newfree; while(pt) /* down the dir list */ { if(hiptr[pt]<0)remove((-hiptr[pt])); /* if a dir */ else frefil(hiptr[pt]); /* or if a file */ newfree=pt; /* now add this loptr.hiptr to free list */ pt=loptr[pt]; /* pt onto next in list */ loptr[newfree]=freptr; /* link on the old free list */ freptr=newfree; /* and update the free pointer */ } } /* return the addr of the next free top blk of mem */ alloc() { int blk; blk=maxblk; while(blk) if(blkfree(--blk))break; fixblk(blk); /* fix this block */ return (blk<<9); /* and return the addr */ } /* fix a block of mem for use, given the block no */ fixblk(blk) int blk; { int bits,words; words=blk>>4; bits=blk-(words<<4); bits=-(1+(1<<bits)); /* complement for mask */ memmap[words]=bits&memmap[words]; } /* is the given block number free ?: returns 1 if true, else 0 */ blkfree(blk) int blk; { int bits,words; words=blk>>4; bits=blk-(words<<4); return ((1<<bits)&(memmap[words])); } /* free up the given block corresponding to the given addr */ dalloc(addr) int addr; { int bits,words,blk; addr=32767&(addr>>1); /* take care to mask */ blk=addr>>8; /* and then calc the blk no. */ if(blk==0)return; /* trap */ words=blk>>4; bits=blk-(words<<4); memmap[words]=memmap[words]|(1<<bits); } /* return the location of a directory structure */ dirfn(arg) int arg; { if(arg==0)return glinks; if(arg==1)return loptr; if(arg==2)return hiptr; } inchar() { char c; c=conin(); /*the machine code char input */ if(c>=' ')outchar(c); /*if not a control char */ if(c==13)return outchar(eol); /* carr-ret to eol */ if(c==4)return 0; /* control-d ret null */ return c; } outchar(c) char c; { if(c==eol)conout(13); /* insert a carraige return if eol */ return (conout(c)); } #include shlibr.c /* end listing one DDJ page 56 */ /* this library is simply the routines ccgchar-cmpbcde from DDJ 48 */ /* initialize stack, i/o and hardware etc. */ inits() { int i; #asm mvi a,0c3h ;fix up the system call location at zero sta 0 lxi h,system shld 1 lxi h,system_4 pop b ;the local variable 'i' pop b ;and the return addr sphl push b ;the return addr push b ;and 'i' #endasm stdin=stdout=0; /* std in, out via console */ i=8; /* now book up all memory */ while(i)memmap[--i]=0; /* and free up user area */ i=maxblk; while(--i)dalloc(i<<9); /* leaves zero block not free */ i=0; while(++i<maxunits)grw[i]=0; loptr[0]=hiptr[0]=glinks[0]=0; /* trap errors */ } /* get/put a group to disk /* /* to/from a given dma address /* /* returns 1 if o.k., 0 if error */ #define sectrk 26 /* 26 by 128 byte sectors per track */ /* conversions in the next section */ /* assume a 512 byte bufsiz !!! /* grupio(group,addr,io) int group,addr,io; { int track,sector,memad; if(group==0)return 0; track=(group<<1)/13; sector=(group<<2)-track*26; /* 0 to 25 range not 1 to 26! */ /***** insert routines to read/write 4 sequential sectors *****/ } /* Save a specified number of blocks of memory into a specified file */ /* The blocks of memory are assumed to start at 2560 (0A00H) /* #define bufsiz 512 char buff[bufsiz]; main(argc,argv) int argc,argv[]; { int unit,ngrp,grp,addr; if(argc!=3){puterr("\nWrong no. of args");return;} if((unit=creatf(argv[1],buff))==0) {puterr("\nCannot open file");return;} if((ngrp=todec(argv[2]))==0){puterr("\nHow many blocks?");return;} addr=2560; /* first location saved */ while(ngrp--) { move(addr,buff); if(writef(unit)==0){puterr("n\Write error");return;} addr=addr+bufsiz; } closf(unit); puterr("n\Successful save"); } /* move a buffer in memory */ move(from,to) char from[],to[]; { int k; k=0; while(k<bufsiz) to[k]=from[k++]; } /* convert a string to an integer: return 0 on error */ /* routine straight from small-c compiler */ todec(str) char str[]; { int k,n,c; n=k=0; while(c=str[k++]) { c=c-'0'; if((c<0)|(c>9))return 0; n=10*n+c; } return n; } #include syslib.c End of program. This program 'rm' enables the removal of files. It is set up so as to be not able to remove directories. #include syslib.c main(argc,argv) int argc,argv[]; {while(--argc)rmfil(argv[argc],0);} End of program. /* Gives statistics of number of free dotted pairs and groups left */ /* If any arguments are given it will give the size of these files */ #include syslib.c main(argc,argv) int argc,argv[]; { int pt,n,i,glinks[],loptr[],hiptr[]; glinks=dirfn(0); loptr=dirfn(1); hiptr=dirfn(2); i=1; while(i<argc) /* for any given file names */ { if((n=scndir(argv[i]))==0)continue; pt=loptr[3]; /* the working dir ptr */ while(--n)pt=loptr[pt]; /* go to the files dotted pair */ pt=hiptr[pt]; /* a pointer to the file */ if(pt>0) { n=size(pt,glinks); if(n<0)puts(" corrupted file structure in "); else {outdec(n);puts(" groups in");} puts(argv[i++];puts("\n"); } } pt=hiptr[1]; n=size(pt,loptr); /* find the no. of free nodes */ if(n<0)puts(" free node list is corrupted\n"); else outdec(n);puts(" free nodes left\n"); pt=hiptr[2]; n=size(pt,glinks); /* find the no of free grps left */ if(n<0)puts("\n free group list is corrupted\n"); else outdec(n);puts(" free groups left\n"); } size(pt,array) int pt,array[]; { int n; n=0; while(pt) { pt=array[pt]; if(++n>32000){n=-1;break;} } return n; } puts(str) char str[]; { int k; k=0; while(putchar(str[k++1])); } outdec(num) int num; { int k,zs; char c; zs=0; k=10000; if(num<0){num=(-num);putchar('-');} while(k>=1) { c=num/k+'0'; if((c!='0')|(k==1)|(zs)) {zs=1;putchar(c);} num=num%k; k=k/10; } } /* library for small-c system programs */ #asm sys equ 0 #endasm /* some definitions */ #define rdfn 1 /* file read function */ #define wrfn 2 /* write function */ #define apfn 3 /* and append */ #define bufsiz 512 #define eol 10 puterr(str) char str[]; {sys(0,str,0,0);} getchar() {sys(1,0,0,0);} putchar(c) char c; {sys(2,c,0,0);} getc(unit) int unit; {sys(1,unit,0,0);} putc(c,unit) char c; int unit; {sys(2,c,unit,0);} readf(unit) int unit; {sys(3,unit,0,0);} writef(unit) int unit; {sys(4,unit,0,0);} openf(name,buff,fn) char name[],buff[]; int fn; {sys(5,name,buff,fn);} creatf(name,buff) char name[],buff[]; {sys(6,name,buff,0);} closf(unit) int unit; {sys(7,unit,0,0);} readr(unit,n) int unit,n; {sys(8,unit,n,0);} writer(unit,n) int unit,n; {sys(9,unit,n,0);} scndir(name) char name[]; {sys(10,name,0,0);} chdir(name) char name[]; {sys(11,name,0,0);} mkdir(name) char name[]; {sys(12,name,0,0);} rmfil(name,flg) char name[]; int flg; {sys(13,name,flg,0);} alloc() {sys(14,0,0,0);} dalloc(addr) int addr; {sys(15,addr,0,0);} dirfn(arg) int arg; {sys(16,arg,0,0);} gosys() {sys(17,0,0,0);} #asm ;fetch a single byte from the address in hl into hl The routines are as in DDJ 48 but only the routines 'ccgchar' to 'cmpbcde' #endasm % ls -l