! "Standard" Imp run time support library %option "-low-nons-nocheck-nodiag-nostack" %include "nmouse.inc-nolist" %systemroutine NEWLINES (%integer n) n = n-1 %and printsymbol(nl) %while n>0 %end %systemroutine SPACES (%integer n) n = n-1 %and printsymbol(' ') %while n>0 %end %systemroutine PRINTLINE (%string(255)s) printstring(s); printsymbol(nl) %end %systemroutine READLINE (%string(*)%name s) ! For symmetry with PRINT LINE, the terminating NL is skipped and ! not included in the string. Blank lines are not ignored, nor are ! leading and trailing spaces. %integer sym %bytename b b == length(s); b = 0 %cycle readsymbol(sym); %exitif sym=nl b = b+1; b[b] = sym %repeat %end %systemstring(8)%fn ITOH (%integer n) ! Convert integer to 8-digit hex string %integer i,k %string(8)s="" %for i = 28,-4,0 %cycle k = n>>i&15; k = k+7 %if k>9; s = s.tostring(k+'0') %repeat %result = s %end %systemintegerfn HTOI (%string(255)s) ! Convert hex string to integer %integer n=0,p=0,k %cycle p = p+1 %result = n %if p>length(s) k = charno(s,p); %continueif k<=' ' k = k-'0' %if k>9 %start k = k-32 %if k>='a'-'0' k = k-7 %if k-7>9 %finish %result = n %unless 0<=k<=15 n = n<<4+k %repeat %end %systemintegerfn STOI (%string(255)s) ! Convert decimal string to integer %integer i,k %integer sign=0, val=0 i = 0 %while i < length(s) %cycle i = i+1; k = charno(s,i) %continue %if k <= ' ' %if k = '-' %start sign = 1 %else %if '0' <= k <= '9' val = val<<3+val+val+k-'0' %else %signal 4, 1, k, "Non-numeric character" %finish %repeat %result = val %if sign = 0 %result = -val %end %systemstring(255)%fn ITOS (%integer v,p) ! Convert integer to decimal string %string(255)s %bytename l %routine printsymbol(%integer x) l = l+1; l[l] = x %end %routine spaces(%integer x) x = x-1 %and printsymbol(' ') %while x>0 %end %routine write(%integer n,p) %integer q,r %if p>0 %start p = \p; printsymbol(' ') %and p = p+1 %if n>=0 %finish p = -120 %if p<-120 q = n//10; r = {rem(n,10)} d1 %if q=0 %start p = p+1 %if n<0; spaces(-1-p); printsymbol('-') %if n<0 %else p = p+1 %if p<0; write(q,p) %finish printsymbol(|r|+'0') %end s = ""; l == length(s) write(v,p) %result = s %end %systemstring(255)%fn RTOS (%real r,%integer n,m) %constreal pmax = 2147483647.0 %real y,z %integer i=0,l,count=0,sign=' ' %string(255)result = "" sign = '-' %if r < 0 m = 80 %if m>80 n = 254-m %if 254-m>255 y = |r|+0.5/10.0\m; !modulus, rounded %if y > pmax %start count = count+1 %and y = y/10.0 %until y < 10.0 %finish z = 1.0 %cycle i = i+1; z = z*10.0 %repeat %until z > y l = n-i result = result." " %and l = l-1 %while l>0 result = result.tostring(sign) %unless sign = ' ' %and n <= 0 %cycle z = z/10.0 l = int pt(y/z) y = y-l*z result = result.tostring(l+'0') i = i-1 %exit %if i+m <= 0 result = result."." %if i = 0 %repeat result = result."@".itos(count,0) %if count # 0 %result = result %end %systemstring(255)%fn RTOF (%real x, %integer n) %real y,round %integer count=-99,sign=0 %string(255) result="" %if x # 0 %start x = -x %and sign = 1 %if x < 0 !Adjust X so that 1.0 <= rounded(X) < 10.0 count = 0; round = 0.5\n y = 1.0-round %if x < y %start; !ie rounded(X) < 1.0 count = count-1 %and x = x*10.0 %until x >= y %finish %else %start y = 10.0-round %while x >= y %cycle; !ie rounded(X) > 10.0 count = count+1; x = x/10.0 %repeat %finish x = -x %if sign # 0 %finish result = rtos(x,1,n) result = result."@".itos(count,0) %result = result %end %systemrealfn STOR (%string(255)Input) %integer Sign = 0, Sym, Pos = 1 %real Value, Exp %routine Next Pos = Pos + 1 %if Pos > Length (Input) %start Sym = 0 %else Sym = Char No (Input, Pos) %finish %end Sym = Char No (Input, Pos) %if Sym = '-' %start Sign = 1 Next %finish Value = 0 %if Sym # '.' %start %signal 6, 5, Pos %unless '0' <= Sym <= '9' %cycle Value = Value*10.0 + (Sym - '0') Next %repeat %until %not '0' <= Sym <= '9' %finish %if Sym = '.' %start Exp = 10.0 %cycle Next %exit %unless '0' <= Sym <= '9' Value = Value + (Sym - '0')/Exp Exp = Exp * 10.0 %repeat %finish %if Sym = '@' %start Sym = SToI (Sub String (Input, Pos + 1, Length (Input))) Value = Value * 10.0\Sym %finish Value = -Value %if Sign # 0 %result = Value %end %systemrealfn FTOR (%string(255)s) %result = stor(s) %end %systemintegerfn READINTEGER %alias "READ" ! Read a decimal integer. The radix may be changed using '_' as customary. %integer i,k,sign,ten=10,max='9' %cycle k = next symbol %exit %if k > ' ' skip symbol %repeat sign = 0 %if k = '-' %start sign = 1 skip symbol; k = next symbol %finish %cycle %signal 4,1,k,"READ: Non-numeric character" %unless '0'<=k<=max i = k-'0' %cycle skip symbol k = next symbol k = k-32 %if k>='a' %if k>'9' %start %exitif k<'A' k = k-7 %finish %exit %unless '0' <= k <= max i = i*ten-'0'+k %repeat %exitunless k='_'-7 ten = i; max = '0'+ten-1 skipsymbol; k = nextsymbol k = k-32 %if k>='a' %if k>'9' %start k = -1 %if k<'A' k = k-7 %finish %repeat i = -i %if sign # 0 %result = i %end %systemrealfn READREAL %integer sign=0,sym %real value,exp %cycle sym = nextsymbol %exit %if sym > ' ' skipsymbol %repeat %if sym = '-' %start sign = 1 skip symbol; sym = nextsymbol %finish value = 0 %if sym # '.' %start %signal 4,1,sym,"READ: Non-numeric character" %unless '0' <= sym <= '9' %cycle value = value*10.0+(sym-'0') skip symbol; sym = nextsymbol %repeat %until %not '0' <= sym <= '9' %finish %if sym = '.' %start exp = 10.0 %cycle skip symbol; sym = nextsymbol %exit %unless '0' <= sym <= '9' value = value+(sym-'0')/exp exp = exp*10.0 %repeat %finish %if sym = '@' %start skipsymbol sym = readinteger value = value*10.0\sym %finish value = -value %if sign # 0 %result = value %end %systemstring(255)%fn READSTRING ! Read a sequence of non-control characters (characters > ' '), ! skipping any leading control characters. But if a leading quote ! (single or double) is found, proceed in the obvious way. %string(255)s %integer term=-1,sym %bytename b b == length(s); b = 0 readsymbol(sym) %until sym>' ' term = sym %and readsymbol(sym) %if sym='"' %or sym='''' %cycle %if sym=term %start %exitunless nextsymbol=term skipsymbol %finish b = b+1; b[b] = sym sym = nextsymbol; %exitif term<0 %and sym<=' ' skipsymbol %repeat %result = s %end %systemroutine WRITE (%integer n,p) printstring(itos(n,p)) %end %systemroutine PRINT (%real x, %integer n,m) printstring(rtos(x,n,m)) %end %systemroutine PRINTFL (%real x, %integer n) printstring(rtof(x,n)) %end %systemroutine PHEX1 (%integer x) x = x&15; x = x+7 %if x>9; printsymbol(x+'0') %end %systemroutine PHEX2 (%integer x) phex1(x>>4); phex1(x) %end %systemroutine PHEX4 (%integer x) phex2(x>>8); phex2(x) %end %systemroutine PHEX (%integer x) phex4(x>>16); phex4(x) %end %systemintegerfn RHEX %integer n=0,s %onevent 4 %start %signal 4,1,s,"RHEX: Non-numeric character" %finish %cycle s = nextsymbol; %exitif s>' ' skipsymbol %repeat s = s&95 %if s>='a' %signal 4 %unless '0'<=s<='9' %or 'A'<=s<='F' %while '0'<=s<='9' %or 'A'<=s<='F' %cycle s = s-'0'; s = s-7 %if s>9 n = n<<4+s; skipsymbol; s = nextsymbol s = s&95 %if s>='a' %repeat %result = n %end ! String manipulation %systemroutine TOUPPER (%string(*)%name s) %bytename b %integer i b == length(s); i = b %while i>0 %cycle i = i-1; b == b[1] b = b&95 %if 'a'<=b<='z' %repeat %end %systemroutine TOLOWER (%string(*)%name s) %bytename b %integer i b == length(s); i = b %while i>0 %cycle i = i-1; b == b[1] b = b!32 %if 'A'<=b<='Z' %repeat %end %systemroutine TOMIXED (%string(*)%name s) %bytename b %integer i,j=0 b == length(s); i = b %while i>0 %cycle i = i-1; b == b[1] %if 'A'<=b&95<='Z' %then b = b&95!j %and j = 32 %else j = 0 %repeat %end %systempredicate RESOLVES (%string(*)%name var,match,fore,aft) !!Resolve the string specified by VAR into FORE and AFT split by MATCH !![FORE and/or AFT absent is conventionally represented by an address !! of zero] %integer i %option "-noline" {not to perturb pred result (compiler neglects to retest)} %integerfn resol(%string(*)%name var,match) !Return index position of first occurrence of MATCH within VAR %label yes,no *clr.l d0 *clr.w d1 *move.b (a1)+,d1 {length(match) *beq yes {match="" -> *clr.w d2 *move.b (a0)+,d2 {length(var) *sub.b d1,d2 *bcs no {length(match)>length(var) -> {*bug: was bmi *subq.w #1,d1 loop1: *lea 0(a0,d0),a2 *move.l a1,a3 *move d1,d3 loop2: *cmpm.b (a2)+,(a3)+ *dbne d3,loop2 {*bug?was dbeq *beq yes *addq.w #1,d0 *dbra d2,loop1 no: *moveq #-1,d0 yes:*addq.l #1,d0 !** (to be) re-coded for efficiency ** ! %integer i=0,j,l ! l = length(match) ! %cycle ! %result = 0 %if i > length(var)-l ! i = i+1 ! j = 0 ! %cycle ! %result = i %if j = l ! j = j+1 ! %repeat %until charno(var,i+j-1) # charno(match,j) ! %repeat %end %routine assign(%string(*)%name dest, %integer from,to) !! **NB use of TOSTRING is compiled in-line ** !! **OK when DEST is also source ** dest = "" %while from <= to %cycle dest = dest.tostring(charno(var,from)); from = from+1 %repeat %end %routine do aft assign(aft,i+length(match),length(var)) %unless aft==nil %end i = resol(var,match) %false %if i = 0 %if fore ## nil %start %if fore ## var %start assign(fore,1,i-1) do aft %finish %else %start do aft length(var) = i-1 %finish %finish %else do aft %true %end ! Bulk move %systemroutine MOVE (%integer bytes,%name from,to) %label finished,bytewise,trylong *move.l a0,d1; *move.l a1,d2 *sub.l d1,d2; *and.w #1,d2; *bne bytewise {buffers misaligned -> *move.l d0,d2; *ble finished {non-positive amount => *and.w #1,d1; *beq trylong {buffers word-aligned -> *move.b (a0)+,(a1)+; *subq.l #1,d0 {align them trylong: *lsr.l #2,d2; *beq bytewise {less than 4 bytes to go -> *subq.l #1,d2; *swap d2 longouter: *swap d2 longinner: *move.l (a0)+,(a1)+; *dbra d2,longinner *swap d2; *dbra d2,longouter *and.l #3,d0 {copy remaining 0:3 bytes bytewise: *subq.l #1,d0; *bmi finished; *swap d0 byteouter: *swap d0 byteinner: *move.b (a0)+,(a1)+; *dbra d0,byteinner *swap d0; *dbra d0,byteouter finished: %end %systemroutinespec file op (%integer c,%string(*)%name f,%name x) %systemrecord(fcb fm)%mapspec fcb open(%integer c,%string(*)%name f,%name x) %systemroutinespec fcb close(%record(fcb fm)%name x) %systemroutinespec fcb abort(%record(fcb fm)%name x) %systemintegerfn FCB size (%record(fcb fm)%name x) ! Returns the size of the file (input or output). %result = 0 %if x==nil %result = x_fl-x_fs %end %systemintegerfn FCB pos (%record(fcb fm)%name x) ! Returns the current position in the file (input or output). %result = 0 %if x==nil %result = x_p-x_fs %end %externalroutine LOGOUT (%string(255)fs) standardise filename(fs) file op(foplogout,fs,nil) %end %externalroutine LOGIN (%string(255)fsu,p) standardise filename(fsu) file op(foplogin,fsu,p) %end %externalroutine QUOTE (%string(255)fs,p) standardise filename(fs) file op(fopquote,fs,p) %end %externalroutine PASSWORD (%string(255)fs,p) standardise filename(fs) file op(foppass,fs,p) %end %externalrecord(fcb fm)%map FILE OPEN INPUT (%string(255)f) standardise filename(f) %result == fcb open(fopopeni,f,nil) %end %externalrecord(fcb fm)%map FILE OPEN OUTPUT (%string(255)f) standardise filename(f) %result == fcb open(fopopeno,f,nil) %end %externalrecord(fcb fm)%map FILE OPEN MODIFY (%string(255)f) standardise filename(f) %result == fcb open(fopopenm,f,nil) %end %externalrecord(fcb fm)%map FILE OPEN APPEND (%string(255)f) standardise filename(f) %result == fcb open(fopopena,f,nil) %end %externalroutine OPENINPUT (%integer s,%string(255)f) %record(fcb fm)%name fcb selectinput(s) fcb == file open input(f) fcb_next == poa_in(s) poa_in(s) == fcb poa_curin == fcb %end %externalroutine OPENOUTPUT (%integer s,%string(255)f) %record(fcb fm)%name fcb selectoutput(s) fcb == file open output(f) fcb_next == poa_out(s) poa_out(s) == fcb poa_curout == fcb %end %externalroutine OPENMODIFY (%integer s,%string(255)f) %record(fcb fm)%name fcb selectoutput(s) fcb == file open modify(f) fcb_next == poa_out(s) poa_out(s) == fcb poa_curout == fcb %end %externalroutine OPENAPPEND (%integer s,%string(255)f) %record(fcb fm)%name fcb selectoutput(s) fcb == file open append(f) fcb_next == poa_out(s) poa_out(s) == fcb poa_curout == fcb %end %externalroutine CREDIR (%string(255)f) standardise filename(f) file op(fopcredir,f,nil) %end %externalroutine DELETE (%string(255)f) standardise filename(f) file op(fopdelete,f,nil) %end %externalroutine NINFO (%string(255)f,%string(*)%name info) standardise filename(f) file op(fopinfo,f,info) %end %externalroutine RENAME (%string(255)old,new) standardise filename(old) standardise filename(new) file op(foprename,old,new) %end %externalroutine COPY (%string(255)from,to) standardise filename(from) standardise filename(to) file op(fopcopy,from,to) %end %externalroutine PERMIT (%string(255)f,p) standardise filename(f) file op(foppermit,f,p) %end %externalroutine CHANGE DATE (%string(255)f,d) standardise filename(f) file op(fopstamp,f,d) %end %externalstring(255)%fn GET DATE AND TIME (%string(255)fs) %string(255)d standardise filename(fs) file op(foptime,fs,d) %result = d %end %externalstring(255)%fn DATETIME %result = get date and time(".") %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 %systemintegerfn INSTREAM %result = poa_instream %end %systemintegerfn OUTSTREAM %result = poa_outstream %end %externalintegerfn INPUT FILE POSITION %result = fcb pos(poa_curin) %end %externalintegerfn OUTPUT FILE POSITION %result = fcb pos(poa_curout) %end %externalintegerfn INPUT FILE SIZE %result = fcb size(poa_curin) %end %externalintegerfn OUTPUT FILE SIZE %result = fcb size(poa_curout) %end %systemroutine 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(fcb fm)%name cb == file open input(f) %integer n = fcb size(cb) fcb close(cb) %result = n %end %externalpredicate exists(%string(255)f) %on 3 %start %false %finish fcb close(file open input(f)) %true %end %record(*)%map lock(%record(*)%name r) %result == nil %if r==nil %result == record(addr(r)!16_80000000) %end %record(*)%map unlock(%record(*)%name r) %result == nil %if r==nil %result == record(addr(r)&16_7fffffff) %end %predicate locked(%record(fcb fm)%name cb) %trueif cb==nil %trueif addr(cb_next)<0 %false %end %systemroutine lock all streams %integer i %record(fcb fm)%name cb %for i = 0,1,7 %cycle cb == poa_in(i) cb_next == lock(cb_next) %unless cb==nil %repeat %for i = 0,1,7 %cycle cb == poa_out(i) cb_next == lock(cb_next) %unless cb==nil %repeat %end %systemroutine unlock all streams %integer i %record(fcb fm)%name cb %for i = 0,1,7 %cycle cb == poa_in(i) cb_next == lock(cb_next) %unless cb==nil %repeat %for i = 0,1,7 %cycle cb == poa_out(i) cb_next == lock(cb_next) %unless cb==nil %repeat %end %externalroutine close all streams %integer i %record(fcb fm)%name cb poa_curin == nil %for i = 0,1,7 %cycle %cycle cb == poa_in(i); %exitif locked(cb); poa_in(i) == cb_next fcbclose(cb) %repeat %repeat selectinput(0) %for i = 7,-1,0 %cycle %cycle cb == poa_out(i); %exitif locked(cb); poa_out(i) == cb_next %if event_event!event_sub=0 %then fcbclose(cb) %else fcbabort(cb) %repeat %repeat selectoutput(0) %end