%begin; !APM IMP Library !** NB must not contain owns !** Value of string FNAME must be name of MOB file !** Some string value parameters masquerading as names ! !IMP PRIM+PERM procedures are dealt with in one of four ways: ! . never called -- in-line code generated (eg store-mapping) ! . included in APM system and called via extracode call vector, ! (eg floating point routines) ! . compiled into program as procedures (eg array access) ! . included in this library which is pre-loaded and referenced ! by external call mechanism (except for CONNECT and EXTLOAD ! which are inserted into the extracode call vector when loaded) ! @16_1114 %routine signal(%integer code) @16_1198 %routine phex(%integer x) %recordformat DICT(%integer a,b,c,d) @16_3FAC %integer cliparamad @16_3FC0 %record(dict) FILDICT @16_3FD0 %record(dict) EXTDICT @16_3FE0 %record(dict) SYSDICT @16_117C %integerfn DEFNAME(%string(255)s,%record(dict)%name d, %integer size) @16_1180 %integerfn REFNAME(%string(255)s,%record(dict)%name d) @16_1184 %routine TRANSNAME(%integer ref,%string(255)%name s) @16_1110 %integerfn FCOMMR(%integer c,%string(255)p, %bytename b,%integer max) @16_1100 %routine ETHERWRITE(%integer port,%bytename buf, %integer size) @16_1104 %integerfn ETHERREAD(%integer port,%bytename buf, %integer max) ! !!!!!!!!!!!!!!!!! Floating-point input/output !!!!!!!!!!!!!!!!!!!!!!! %externalroutine FREAD %alias "read"(%name v) !Called only for reals %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 %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 read(sym) value = value*10.0^sym %finish value = -value %if sign # 0 ! v = value *move v,a0 *move value,(a0) %end; !fread %externalroutine READREAL(%realname v) fread(v) %end %externalroutine PRINT(%real x, %integer n,m) %constreal pmax = 2147483647.0 %real y,z %integer i=0,l,count=0,sign sign = ' ' sign = '-' %if x < 0 y = |x|+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 spaces(n-i) printsymbol(sign) %unless sign = ' ' %and n <= 0 %cycle z = z/10.0 l = int pt(y/z) y = y-l*z printsymbol(l+'0') i = i-1 %exit %if i+m <= 0 print symbol('.') %if i = 0 %repeat printsymbol('@') %and write(count,0) %if count # 0 %end; !print %externalroutine PRINTFL(%real x, %integer n) %real y,round %integer count=-99,sign=0 %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 print(x,1,n) printsymbol('@') write(count,0) %end; !printfl %externalintegerfn int(%real r) %result = intpt(r+0.5) %end %externalrealfn fraction(%real r) %result = fracpt(r) %if r>=0 %result = -fracpt(-r) %end %externalintegerfn round(%real r) %result = int(r) %end %externalintegerfn trunc(%real r) %result = intpt(r) %if r>=0 %result = -intpt(-r) %end !!!!!!!!!!!!!!!!!!!! Stream control !!!!!!!!!!!!!!!!!!!!!!!! %constinteger iocbsize=16, iocbshift=4 %constinteger icb0=16_35ce, ocb0=16_360e @16_35c6 %integer icb @16_35ca %integer ocb %externalintegerfn INSTREAM %result = (icb-icb0)>>iocbshift %end %externalintegerfn OUTSTREAM %result = (ocb-ocb0)>>iocbshift %end !!!!!!!!!!!!!!!!!!!! String procedures !!!!!!!!!!!!!!!!!!!!!!!! %externalstring(255)%fn SUBSTRING(%string(255) s, %integer from,to) %string(255) t t = "" %while from <= to %cycle t = t.tostring(charno(s,from)); from = from+1 %repeat %result = t %end %externalintegerfn INDEX(%string(*)%name var,match) !Return index position of first occurrence of match within string !** to be re-coded for efficiency ** %integer i=0,j,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 %predicate RESOLVE(%string(*)%name var,match,fore,aft) %integer i %routine do aft aft = substring(var,i+length(match),length(var)) %if addr(aft) # 0 %end i = index(var,match) %false %if i = 0 %if addr(fore) # 0 %start %if addr(fore) # addr(var) %start fore = substring(var,1,i-1) do aft %finish %else %start do aft length(var) = i-1 %finish %finish %else do aft %true %end %external%string(127)%fn ITOS(%integer v,p) %integer vv,q,pos %byteintegerarray store(0:127) vv = v; vv = -vv %if vv > 0 pos = 127 %while vv <= -10 %cycle q = vv//10 store(pos) = q*10-vv+'0'; pos = pos-1 vv = q %repeat store(pos) = '0'-vv %if p <= 0 %start p = 128+p %else p = 128-p p = pos %if p > pos p = p-1 %finish pos = pos-1 %and store(pos) = '-' %if v < 0 %while pos > p %and pos > 1 %cycle pos = pos-1; store(pos) = ' ' %repeat pos = pos-1; store(pos) = 127-pos %result = string(addr(store(pos))) %end %external%integer%fn STOI(%string(255) S) %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 3, 1, k %finish %repeat %result = val %if sign = 0 %result = -val %end %externalroutinespec PRINT LINE(%string(255) s) %externalroutine PRINT LINE *JSR printstring newline %end %externalroutine READ LINE(%string(255)%name s) %integer k s = "" %cycle read symbol(k) %return %if k < ' ' s = s.tostring(k) %repeat %end %externalroutine READ STRING(%string(*)%name s) %integer k readsymbol(k) %until k>' ' s = "" %cycle s = s.tostring(k) k = nextsymbol; %returnif k<=' ' skipsymbol %repeat %end %externalstring(31)%fn DATETIME %string(31)s length(s) = fcommr('G'<<8,"",charno(s,1),31) %result = s %end %externalstring(8)%fn DATE; !** No owns !%string(31)s ! s = datetime; length(s) = 8; %result = s *BSR DATETIME; !ad -> A0 *MOVE.B #8,(A0); !alter length %end %externalstring(5)%fn TIME; !** No owns !%string(31)s !%integer p ! s = datetime; p = addr(s)+length(s)-5 ! byteinteger(p) = 5; %result = string(p) *BSR DATETIME *LEA 10(A0),A0; *MOVE.B #5,(A0); !adjust start & length %end !!!!!!!!!!!!!!!!!!!!!!! Parameter processing !!!!!!!!!!!!!!!!!!!!!!!!!! %externalstring(255)%fn CLIPARAM !Gives effect of VAX/VMS function for obtaining command parameters %string(255) s ! %if cliparamad>0 %start s = string(cliparamad) %result = "" %if shortinteger(cliparamad)=511 %result = s %unless s="" ! %finish skip symbol %while nextsymbol = ' ' read line(s) %result = s %end !!!!!!!!!!!!!!!!!!!!!! File connection !!!!!!!!!!!!!!!!!!!!!!!!! %recordformat CONNINFO(%integer memstart,fstart,flim,memlim) %externalroutine CONNECT(%string(255)%name f,%record(conninfo)%name d) !Read in the file F to space allocated on the heap ! Allocate a total of D_FSTART + fsize + D_MEMLIM bytes ! and align file to D_FSTART within this space; ! D_MEMSTART := start of space; D_FSTART := D_FSTART+D_MEMSTART ! D_FLIM := D_FSTART+fsize; D_MEMLIM := D_MEMLIM+D_FLIM @16_35C4 %short uno @16_372C %byte cylock @16_372D %byte fsport %integer i,j,xno,len,blocks,pos,fsize,fpos,original %string(255) fscomm %routine lock cylock = cylock+1 %end %routine unlock %returnif cylock=0 cylock = cylock-1 cylock = 0 %and %signal 0,1 %if cylock=128 %end %routine GET(%integername v) !Extract numeric info from FSCOMM %integer k v = 0 %cycle i = i+1; k = charno(fscomm,i) i = i-1 %if k < ' ' k = k-'0' %return %if k < 0 v = v<<4+k %repeat %end %routine READ FILE(%integer ok) %integer j %unless fsize=0 %start %if fpos#0 %start j = fsize-4 %while j>=0 %cycle j = j-4; integer(pos) = integer(fpos) pos = pos+4; fpos = fpos+4 %repeat j = j+4-1 %while j>=0 %cycle j = j-1; byteinteger(pos) = byteinteger(fpos) pos = pos+1; fpos = fpos+1 %repeat %else %cycle j = 512; j = fsize %if fsize0 %and integer(j)>0 %start; !File already in store fpos = integer(j); fsize = integer(j+4)-fpos fpos = 0 %if fsize<=0 %finish %if fpos=0 %start; !Read file from filestore lock fscomm = "Z".tostring(uno+'0').f.tostring(nl) etherwrite(fsport,charno(fscomm,1),length(fscomm)) len = etherread(fsport,charno(fscomm,1),255);!Read response %if charno(fscomm,1) = '-' %start unlock event_extra = charno(fscomm,2)-'0' charno(fscomm,2) = len-2 event_message = string(addr(charno(fscomm,2))) signal(16_39) %finish i = 0 get(blocks); get(fsize) fsize = blocks<<9-fsize; !size of file in bytes %finish %finish %else fsize = 0 !Allocate space *MOVE D6,pos; *MOVE A7,j; !**Heap -><- Stack ** %if pos+fsize+d_fstart+d_memlim >= j %start; !no space read file(0) event_message = "*No space to connect ".f signal(16_49) %finish pos = pos-256; !HP displaced by 256 d_memstart = pos pos = pos+d_fstart; d_fstart = pos read file(1) d_flim = pos pos = pos+d_memlim; d_memlim = pos pos = (pos+259)&(\3); !aligned *MOVE pos,D6 %end %externalroutine CONNECT FILE(%string(255) f, %integer mode, %integername start,len) %record(conninfo) r r = 0; connect(f,r); start = r_fstart; len = r_flim-start %end !!!!!!!!!!!!!!!!!!!!!!! External loading !!!!!!!!!!!!!!!!!!!!!!!!!!!!! %routine EXTLOAD *MOVE 4(A7),A3; !**allow for LINK** %integer lmax=-1, errors=0 {%integer level=0 %record(conninfo)%array LOADED(0:63) %string(255) fid %routine LOAD(%integer p,a) %integer i,q,r,e,b,fref,idref %record(conninfo)%name L {%integer count=0 {spaces(level) %while shortinteger(p) # 0 %cycle; !For each ref {printstring(string(p)) idref = refname(string(p),extdict); !lookup in ext dict %if idref <= 0 %start printstring("*Unknown external: ".string(p)); newline errors = errors+1 %finish %else %start fref = integer(idref) i = -1 %cycle i = i+1; l == loaded(i) %if i > lmax %start; !first use of this file lmax = i; l = 0; !new cell {printstring("=>") { %if integer(fref) <= 0 %start; !not permanently loaded transname(fref,fid); !recover name of file {printstring(fid); newline connect(fid,l); !read it in l_memstart = fref {%for i = 0,1,lmax %cycle { space; phex(loaded(i)_memstart) { newline %if i&7 = 7 {%repeat {newline i = l_flim-2 i = i+shortinteger(i); !entry point b = l_flim-6-shortinteger(i+6)<<1; !start of owns l_flim = b %if i+60 < b %start; !ext specs present {level = level+2; newline load(i+40,b) {level = level-2; spaces(level) %finish %finish %else %start { l_fstart = integer(fref); l_memstart = fref { %finish %finish %repeat %until l_memstart = fref q = l_fstart+2; !start of externals e = 0 %while byteinteger(q) < 12 %cycle; !find & set Q to end e = q %if string(q) = string(p) q = q+20 %repeat %if e = 0 %start printstring("*".string(p)." no longer valid"); newline %stop %finish %if integer(p+12) # integer(e+12) %start %if (integer(p+12)!!integer(e+12))&4#0 %start printstring("*Class mismatch for ".string(p)); newline %stop %finish ! printstring("*Type mismatch for ".string(p)); newline ! %stop %finish r = integer(p+16)+a; !disp of ref + A6 %if integer(p+12)&4 # 0 %start; !procedure shortinteger(r) = 16_2C7C; !MOVE.L #xxxxxxxx,A6 integer(r+2) = l_flim; !start of owns shortinteger(r+6) = 16_4EF9; !JMP xxxxxxxx integer(r+8) = q+integer(e+16); !entry-point %finish %else %start integer(r) = l_flim+integer(e+16) {phex(integer(r)) %finish %finish p = p+20 {%if shortinteger(p) # 0 %start { printsymbol(','); count = count+1 { newline %and spaces(level) %and count = 0 %if count = 6 {%finish %repeat {newline %end *MOVE A3,D0; *ADDQ #4,D0 *MOVE A6,D1 *BSR load %stop %if errors # 0 %end !Parameter records: %recordformat INFO(%string(255) name, %integer addr,%short size,flags, %record(info)%name link) !Base record %recordformat PAMINFO(%byte groupsep,keyflag, %short allflags, %record(info)%name chain) %external%record(paminfo)%map PAM %record(paminfo)%name p %predicate ok(%record(info)%name p) %integer q *move d6,q %while p ## nil %cycle %false %unless 16_800000 < addr(p) < q %and addr(p)&1 = 0 p == p_link %repeat %true %end p == record(refname("PAM_INFO",sysdict)) %if addr(p) <= 0 %start p == record(defname("PAM_INFO",sysdict,sizeof(p))) p_chain == nil; p_allflags = 0 p_groupsep = '/'; p_keyflag = '-' %finish p_chain == nil %and p_allflags = 0 %if %not ok(p_chain) %result == p %end !Branch table entry displacement addresses: %constinteger connted=16_11BA, loadted=16_11BE, resolted=16_11B6 %conststring(19)FNAME="I:LIB.MOB" @16_3ff0 %integer freebot %integer i,j !Insert CONNECT, EXTLOAD & RESOLVE j = shortinteger(connted)+connted+2 *lea connect,a0 *move.l a0,i integer(j) = i j = shortinteger(loadted)+loadted+2 *lea extload,a0 *move.l a0,i integer(j) = i j = shortinteger(resolted)+resolted+2 *lea resolve,a0 *move.l a0,i integer(j) = i !Install entry-points j = refname(fname,fildict) printstring(fname." not in dict!") %and %stop %if j <= 0 i = integer(j)+2 %while 1<=byteinteger(i)<=11 %cycle integer(defname(string(i),extdict,8)) = j i = i+20 %repeat !Lock file in store freebot = integer(j+4)+4 printstring("IMPLIB loaded"); printsymbol(nl) %endofprogram