%option "-low" %include "nmouse.inc" %include "io.inc" %systempredicatespec load object(%record(*)%name a,b) %systemrecord(scb fm)%map NEW SCB (%string(*)%name filename) %record(scb fm)%name scb %integername p %integer n scb == record(heapget(sizeof(scb)-255+length(filename))) p == integer(addr(scb)); n = sizeof(scb)-256 %cycle p = 0; p == p[1]; n = n-4 %repeatuntil n=0 scb_filename = filename %result == scb %end %systemroutine SCB operation (%registerrecord(scb fm)%name scb, %integer code,p1,p2,%name b) *move.l a4,-(sp) *move.l scb_soppc,a2 *move.l scb_gla,a4 *jsr (a2) *move.l (sp)+,a4 %end !%constinteger - ! sop close = 0, ! sop abort = 1, ! sop flush = 2, ! sop refresh = 3, ! sop write = 4, ! sop read = 5 %systemroutine FILE CLOSE (%record(scb fm)%name x) ! Close file normally (input or output) scb operation(x,sopclose,0,0,nil) %end %systemroutine FILE ABORT (%record(scb fm)%name x) ! Close file abnormally (input or output, but for input it ! does the same as FILE CLOSE). scb operation(x,sopabort,0,0,nil) %end %systemroutine FILE FLUSH (%record(scb fm)%name x, %integer ch) ! Write contents of file buffer (X_P-X_BS bytes at X_BS) to file ! at position X_BS-X_FS in file. ! Maintain high water mark (set X_FL to X_P if X_P>X_FL). ! If X_P=X_L, advance the buffer through the file (normally by ! leaving X_BS and X_BL alone and subtracting X_BL-X_BS from ! X_FS and X_FL. Return with X_L=X_BL. ! Normally return with X_P=X_BS, but if CH>=0, in the case of ! non-buffered devices (in which case X_BS=X_BL), write the one ! byte CH to the device, in the case of buffered devices, add CH ! to the buffer (and return with X_P=X_BS+1). scb operation(x,sopflush,ch,0,nil) %end %systemroutine FILE REFRESH (%record(scb fm)%name x) ! Fill the file buffer by reading X_BL-X_BS bytes (less if near ! end of file) from such a position in the file that byte X_P-X_FS ! of the file will be in the buffer. This will usually involve ! updating X_FS and X_FL and X_P (but always return such that ! X_P-X_FS before is the same as X_P-X_FS after, i.e. X_P-X_FS ! denotes the current position in the file, we do not automatically ! return with X_P=X_BS, although this will normally be the case). ! Normally return with X_L=X_BL (unless near the end of file). scb operation(x,soprefresh,0,0,nil) %end %systemroutine FILE WRITE - (%record(scb fm)%name x,%integer position,amount,%name b) ! Ignoring the buffer pointers in the SCB, write AMOUNT bytes to ! the file at POSITION in the file, from user buffer B. ! Use current position indicated in SCB if POSITION<0. position = x_p-x_fs %if position<0 scb operation(x,sopwrite,position,amount,b) %end %systemroutine FILE READ - (%record(scb fm)%name x,%integer position,amount,%name b) ! Ignoring the buffer pointers in the SCB, read AMOUNT bytes from ! place POSITION in the file, to user buffer B. ! Use current position indicated in SCB if POSITION<0. position = x_p-x_fs %if position<0 scb operation(x,sopread,position,amount,b) %end %systemintegerfn FILE LENGTH (%record(scb fm)%name x) ! Valid both for input and output files. %result = x_fl-x_fs %end %predicate dynamically loaded (%string(255)s,%integername pc,gla) %constinteger extbit=16_4000,external=16_2000,jmp=16_4ef9 %record(fe02 indir fm)indir %record(fe02 object fm)object indir = 0 object = 0 object_flags = extbit+external object_name = s %falseunless load object(object,indir) %if indir_op1=jmp %start gla = 0; pc = indir_opd1 %true %finish %if indir_op2=jmp %start gla = indir_opd1; pc = indir_opd2 %true %finish %false %end %routine standardise filename(%string(*)%name s) %integer pc,gla %if dynamically loaded("standardisefilename",pc,gla) %start *move.l s,a0 *move.l pc,a1 *move.l gla,a2 *move.l a4,-(sp) *move.l a2,a4 *jsr (a1) *move.l (sp)+,a4 %finishelsesignal 3,3,,s %end %record(scbfm)%map FILE operation (%integer code,%string(*)%name file,%name x) ! Perform direct file system operation not involving SCBs. %string(255)dev,full %bytename d %integer pc,gla,len %record(scbfm)%map call it(%integer a,%name b,c) *move.l a4,-(sp) *move.l gla,a4 *move.l pc,a2 *jsr (a2) *move.l (sp)+,a4 %end full = file standardise filename(full) {-> :x:y:z} dev = full d == length(dev) dev = "fop_".substring(dev,2,d) {-> fop_x:y:z} len = 4 %cycle d = len %if d[len+1]=':' len = len+1 %repeatuntil len>=d {-> fop_x} %result == call it(code,full,x) %if dynamically loaded(dev,pc,gla) dev = "Cannot access file ".file %signal 3,3,,dev %end %routine fop (%integer code,%string(*)%name file,%name x) %record(scbfm)%name unused unused == file operation(code,file,x) %end !%constinteger - ! fop logout = 0, ! fop login = 1, ! fop quote = 2, ! fop pass = 3, ! fop openi = 4, ! fop openo = 5, ! fop openm = 6, ! fop opena = 7 {not used}, ! fop credir = 8, ! fop delete = 9, ! fop info = 10, ! fop rename = 11, ! fop copy = 12, ! fop permit = 13, ! fop stamp = 14, ! fop time = 15, ! fop special = 16, ! fop oldfinfo= 17 %externalroutine FILE LOGOUT (%string(255)fs) fop(foplogout,fs,nil) %end %externalroutine FILE LOGIN (%string(255)fsu,p) fop(foplogin,fsu,p) %end %externalroutine FILE QUOTE PASSWORD (%string(255)fs,p) fop(fopquote,fs,p) %end %externalroutine FILE CHANGE PASSWORD (%string(255)fs,p) fop(foppass,fs,p) %end %externalrecord(scb fm)%map FILE OPEN INPUT (%string(255)f) %record(scbfm)%name x %integer i standardise filename(f) %result == file operation(fopopeni,f,nil) %end %externalrecord(scb fm)%map FILE OPEN OUTPUT (%string(255)f) %result == file operation(fopopeno,f,nil) %end %externalrecord(scb fm)%map FILE OPEN MODIFY (%string(255)f) %result == file operation(fopopenm,f,nil) %end %externalrecord(scb fm)%map FILE OPEN APPEND (%string(255)f) %record(scbfm)%name x %integer size,offset,pos x == file open modify(f) size = x_fl-x_fs {size of file offset = rem(size,x_bl-x_bs) {amount used in last block pos = size-offset {start of last block x_fs = x_fs-pos; x_fl = x_fl-pos {seek to last block x_p = x_fl; x_l = x_bl {to past last byte file refresh(x) %unless x_p=x_bs {read partial block x_p = x_fl; x_l = x_bl %result == x %end %externalroutine FILE CREATE DIRECTORY (%string(255)f) fop(fopcredir,f,nil) %end %externalroutine FILE DELETE (%string(255)f) fop(fopdelete,f,nil) %end %externalroutine FILE INFO (%string(255)f,%string(*)%name info) fop(fopinfo,f,info) %end %externalroutine FILE RENAME (%string(255)old,new) standardise filename(new) fop(foprename,old,new) %end %externalroutine FILE COPY (%string(255)old,new) standardise filename(new) fop(fopcopy,old,new) %end %externalroutine FILE PERMIT (%string(255)f,p) fop(foppermit,f,p) %end %externalroutine FILE CHANGE DATE (%string(255)f,d) fop(fopstamp,f,d) %end %externalroutine FILE GET DATE (%string(255)fs,%string(*)%name d) ! This one asks the file system what time it thinks it is. fop(foptime,fs,d) %end %recordformat fs fm(%integer send,recmax,rec,%bytename sendbuf,recbuf) %externalroutine FILE SPECIAL (%string(255)fs,%record(fs fm)%name r) ! This one is intended to cover special cases, such as admin functions. ! It involves sending SEND bytes from SENDBUF and receiving back up to ! RECMAX bytes into RECBUF, noting in REC the actual number of bytes returned. fop(fopspecial,fs,r) %end %externalroutine FILE OLDFINFO (%string(255)f,%string(*)%name info) fop(fopoldfinfo,f,info) %end %externalstring(255)%fn DATETIME %string(255)fs,dt fs = "."; dt = "" file get date(fs,dt) %result = dt %end %externalstring(255)%fn DATE %string(255)dt = datetime %bytename b == length(dt) b = b-1 %while b>0 %and b[b]#' ' b = b-1 %while b>0 %and b[b]=' ' %result = dt %end %externalstring(255)%fn TIME %string(255)dt = datetime %bytename b == length(dt) %integer p = b p = p-1 %while p>0 %and b[p]#' ' dt = substring(dt,p+1,b) %result = dt %end %routine stream check(%integer s) %signal 6,1,s,"Stream number out of range" %unless s&7=s %end %externalroutine OPENINPUT (%integer s,%string(255)f) %record(scb fm)%name scb streamcheck(s) selectinput(s) {back-compat} scb == file open input(f) scb_next == poa_in(s) poa_in(s) == scb poa_curin == scb %if poa_instream=s %end %externalroutine OPENOUTPUT (%integer s,%string(255)f) %record(scb fm)%name scb streamcheck(s) selectoutput(s) scb == file open output(f) scb_next == poa_out(s) poa_out(s) == scb poa_curout == scb %if poa_outstream=s %end %externalroutine OPENMODIFY (%integer s,%string(255)f) %record(scb fm)%name scb streamcheck(s) selectoutput(s) scb == file open modify(f) scb_next == poa_out(s) poa_out(s) == scb poa_curout == scb %if poa_outstream=s %end %externalroutine OPENAPPEND (%integer s,%string(255)f) %record(scb fm)%name scb streamcheck(s) selectoutput(s) scb == file open append(f) scb_next == poa_out(s) poa_out(s) == scb poa_curout == scb %if poa_outstream=s %end %systemintegerfn INPUT FILE POSITION %result = 0 %if poa_curin==nil %result = poa_curin_p-poa_curin_fs %end %systemintegerfn OUTPUT FILE POSITION %result = 0 %if poa_curout==nil %result = poa_curout_p-poa_curout_fs %end %systemintegerfn INPUT FILE LENGTH %result = 0 %if poa_curin==nil %result = poa_curin_fl-poa_curin_fs %end %systemintegerfn OUTPUT FILE LENGTH %result = 0 %if poa_curout==nil %result = poa_curout_fl-poa_curout_fs %end %systemroutine SET INPUT (%integer byte) %returnif poa_curin==nil poa_curin_p = poa_curin_fs+byte poa_curin_l = poa_curin_p %unless poa_curin_bs<=poa_curin_p<=poa_curin_l %end %systemroutine SET OUTPUT (%integer byte) %returnif poa_curout==nil %unless poa_curout_bs <= poa_curout_fs+byte <= poa_curout_bl %start file flush(poa_curout,-1) poa_curout_p = poa_curout_fs+byte poa_curout_l = poa_curout_p file refresh(poa_curout) %finish poa_curout_p = poa_curout_fs+byte poa_curout_l = poa_curout_bl %end %systemroutine RESET INPUT setinput(0) %end %systemroutine RESET OUTPUT setoutput(0) %end %systemintegerfn instream %result = poa_instream %end %systemintegerfn outstream %result = poa_outstream %end %systemroutine CLOSE INPUT %record(scbfm)%name cb cb == poa_curin %returnif cb==nil poa_curin == cb_next; %returnif cb==poa_curin poa_in(instream) == poa_curin scb operation(cb,sopclose,0,0,nil) %end %systemroutine ABORT OUTPUT %record(scbfm)%name cb cb == poa_curout %returnif cb==nil poa_curout == cb_next; %returnif cb==poa_curout poa_out(outstream) == poa_curout file flush(cb,-1) scb operation(cb,sopabort,0,0,nil) %end %systemroutine CLOSE OUTPUT %record(scbfm)%name cb cb == poa_curout %returnif cb==nil poa_curout == cb_next; %returnif cb==poa_curout poa_out(outstream) == poa_curout file flush(cb,-1) scb operation(cb,sopclose,0,0,nil) %end %externalroutine PROMPT (%string(255)s) %returnif poa_curin==nil %returnif poa_curin_prompt==nil poa_curin_prompt = s %end %systemstring(255)%fn INFILENAME %result = ":N" %if poa_curin==nil %result = poa_curin_filename %end %systemstring(255)%fn OUTFILENAME %result = ":N" %if poa_curout==nil %result = poa_curout_filename %end %externalintegerfn filesize(%string(255)f) %record(scb fm)%name cb == file open input(f) %integer n = cb_fl-cb_fs file close(cb) %result = n %end %externalpredicate exists(%string(255)f) %on 3 %start %false %finish file close(file open input(f)) %true %end