! File NMOUSE:IMPLIB ! Imp runtime library ! plus odds and sods %option "-low-nons-nocheck-nodiag-nostack" %include "mouse.inc" %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 %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 ! I/O %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 x_fl = x_p %if x_p>x_fl %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 %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 %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 %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 %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 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)p) %string(255)fs="." standardise filename(fs) file op(fopquote,fs,p) %end %externalroutine PASSWORD (%string(255)p) %string(255)fs="." standardise filename(fs) file op(foppass,fs,p) %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 %externalstring(255)%fn FINFO (%string(255)f,%integer n) %string(255)info f = "." %if f="" standardise filename(f) f = f."," f = f.tostring(n>>4+'0') f = f.tostring(n&15+'0') file op(fopoldfinfo,f,info) %result = info %end %externalstring(255)%fn NINFO (%string(255)f) %string(255)info standardise filename(f) file op(fopinfo,f,info) %result = 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 DATETIME %string(255)d = "." standardise filename(d) file op(foptime,d,d) %result = d %end %externalroutine FILESTORE CONTROL (%string(255)p) %string(255)fs = "." ! NB: ! [ new owner ! ^ new quota ! ]1 kill uno ! ]2 kill xno ! ]3 kill port ! ]4 set diag ! ]5 set open state (0 none, 3 syspass, 7 all) ! ]6 set syspass ! ]7 reboot ! ]8 add bad block ! ]9 set date and time ! ]: lpzap standardise filename(fs) file op(fopspecial,fs,p) %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 %constinteger base {1/1/80} = 29161 %externalstring(19)%fn DECODE DATE AND TIME (%integer code) %integer d,m,y,hh,mm,ss %string(19)r="dd/mm/yy hh.mm.ss" %bytename b %routine p2(%integer n,%bytename b) b[1] = rem(n,10)+'0' b = rem(n//10,10)+'0' %end d = (code//(24*60*60)+base)<<2-1 y = d//1461+1 d = ((rem(d,1461)+4)>>2)*5-3 m = d//153-9 %if m<=0 %start m = m+12; y = y-1 %finish d = (rem(d,153)+5)//5 b == charno(r,1) p2(d,b; m,b[3]; y,b[6]) ss = rem(code,60); code = code//60 mm = rem(code,60); hh = rem(code//60,24) b == b[10] p2(hh,b; mm,b[3]; ss,b[6]) %result = r %end %externalintegerfn ENCODE DATE AND TIME (%string(255)s) %integer d=0,m=0,y=0,hh=0,mm=0,ss=0 %bytename b,end %integerfn num %integer n=0 %result = n %if b==end b == b[1] %cycle %result = n %if b==end %if b=' ' %start %result = n %unless n=0 %else %result = n %unless '0'<=b<='9' n = n*10+b-'0' %finish b == b[1] %repeat %end b == length(s); end == b[b+1] d = num; m = num; y = num; hh = num; mm = num; ss = num m = m - 3 m = m + 12 %and y = y - 1 %if m < 0 %result = (((((y*1461)>>2+(m*153+2)//5+d-base))*24+hh)*60+mm)*60+ss %end %externalstring(255)%fn current user %string(255)s="current_user" %result = "" %unless translated logical name(s) %result = s %end %externalstring(255)%fn current filestore %string(255)s="current_filestore" %result = "" %unless translated logical name(s) %result = s %end %externalstring(255)%fn current directory %string(255)s="." %bytename l == length(s) %result = "" %unless translated logical name(s) l = l+1 %and l[l] = ':' %if ']'#l[l]#':' %result = s %end %externalroutine set directory(%string(255)s) standardise filename(s) define logical name(".",s) %end %recordformat finfof(%string(23)name,%string(5)perms,%string(9)date,time, %integer blocks,extents) %externalroutine unpack finfo(%string(127)s,%record(finfof)%name r) %integer pos=1 %routine scan pos = pos+1 %while pos<=length(s) %and charno(s,pos)=' ' %end %integerfn d %integer n=0,k scan %cycle %result = n %if pos>length(s); pos = pos+1; k = charno(s,pos-1)-'0' %result = n %if k<0 %or k>9; n = n*10+k %repeat %end %routine w(%string(*)%name t,%integer max) %integer k scan; t = "" %cycle %returnif pos>length(s) %or max<=0 k = charno(s,pos); pos = pos+1; max = max-1 %returnif k=' ' t = t.tostring(k) %repeat %end r = 0 w(r_name,23); w(r_perms,5); w(r_date,9); w(r_time,9) r_blocks = d; r_extents = d %end %externalintegerfn wildness(%string(*)%name s) %integer k,i,w=0 %for i=1,1,length(s) %cycle k = charno(s,i); w = w+1 %if k='*' %or k='%' %repeat %result = w %end %externalpredicate Matches(%string (*) %name s, p) ! S=Subject, P=Pattern. Pattern is the one with the stars in it. %integer slen = 0, plen = 0 %predicate m (%integer spos,ppos) %integer psym = 0,ssym = 0 %cycle %if ppos=plen %start %true %if spos=slen %false %finish ppos = ppos+1; psym = charno(p,ppos) %exitif psym='*' %falseif spos=slen spos = spos+1; ssym = charno(s,spos) psym = ssym %if ssym!32=psym!32 %and 'a'<=psym!32<='z' %unless ssym=psym %start %falseunless psym='%' %finish %repeat %cycle %trueif m(spos,ppos) %exitif spos=slen spos = spos+1; ssym = charno(s,spos) %repeat %false %end slen = length(s) plen = length(p) %true %if m(0,0) %false %end %externalpredicate Translate Matches(%string (*) %name s, p, o) ! S=Subject, P=Pattern, O=Object. ! Replace the wild card markers in O with the parts of S which ! correspond to the wild card markers in S. %bytename slen,plen,olen %integer i %routine inject(%string(255)s) %string(255)fore,aft %for i = olen,-1,1 %cycle %if olen[i]='*' %start fore = substring(o,1,i-1) aft = substring(o,i+1,olen) o = fore.s.aft %return %finish %repeat o = o.s %end %predicate m(%integer spos,ppos) %integer psym = 0,ssym = 0 %string(255)match %cycle %if ppos=plen %start %true %if spos=slen %false %finish ppos = ppos+1; psym = charno(p,ppos) %exitif psym='*' %falseif spos=slen spos = spos+1; ssym = charno(s,spos) psym = ssym %if ssym!32=psym!32 %and 'a'<=psym!32<='z' %unless ssym=psym %start %falseunless psym='%' %for i = 1,1,olen %cycle %unless '%'#olen[i]#'*' %start olen[i] = ssym; i = 0; %exit %finish %repeat %unless i=0 %start olen = olen+1; olen[olen] = ssym %finish %finish %repeat match = "" %cycle inject(match) %andtrueif m(spos,ppos) %exitif spos=slen spos = spos+1; ssym = charno(s,spos) match = match.tostring(ssym) %repeat %false %end slen == length(s) plen == length(p) olen == length(o) %trueif m(0,0); %false %end