$title ('MP/M-86 2.0 Spool Program') $compact spool: do; $include(copyrt.lit) $include(vaxcmd.lit) $include(comlit.lit) dcl mpm$product lit '11h'; mon1: procedure (func,info) external; declare func byte; declare info address; end mon1; mon2: procedure (func,info) byte external; declare func byte; declare info address; end mon2; mon3: procedure (func,info) address external; declare func byte; declare info address; end mon3; declare fcb (1) byte external; declare buff (1) byte external; read$console: procedure byte; return mon2 (1,0); end read$console; print$console$buffer: procedure (buff$adr); declare buff$adr address; call mon1 (9,buff$adr); end print$console$buffer; check$console$status: procedure byte; return mon2 (11,0); end check$console$status; version: procedure address; return mon3(12,0); end version; open: procedure (fcb$adr) byte public; declare fcb$adr address; return mon2 (15,fcb$adr); end open; readbf: procedure (fcb$adr) byte public; declare fcb$adr address; return mon2 (20,fcb$adr); end readbf; set$dma: procedure (dma$adr) public; declare dma$adr address; call mon1 (26,dma$adr); end set$dma; free$drives: procedure; call mon1 (39,0ffffh); end free$drives; lo: procedure (char) public; declare char byte; call mon1 (5,char); end lo; system$reset: procedure; call mon1 (0,0); end system$reset; crlf: procedure; call print$console$buffer(.(0ah,0dh,'$')); end crlf; /* CP/M, XDOS function numbers */ declare set$dma$base lit '51', get$max$mem lit '53', alloc$mem lit '55', free$mem lit '57', open$queue lit '135', read$queue lit '137', cond$read$queue lit '138', write$queue lit '139', detach lit '147', parse$fname lit '152', attach$list lit '158', detach$list lit '159'; declare control$z literally '1AH'; declare (char,column,itab,jtab,i) byte; declare bufpointer pointer; /* base this structure */ declare bufptr structure ( /* where memory has been */ offset word, segment word ) at (@bufpointer); /* allocated */ declare buffer based bufpointer (128) byte; list$buf: procedure (sector) byte; declare i byte, sector word; do i = 0 to 127; if (char := buffer(i + sector)) = control$z then return true; itab = (char = 09H) and (7 - (column and 7)); if char = 09H then char = ' '; do jtab = 0 to itab; if char >= ' ' then column = column + 1; if char = 0AH then column = 0; call lo(char); if check$console$status then do; i = read$console; /* under MP/M-80 forced a dispatch */ call system$reset; /* when console detached, causes problems */ end; /* under MP/M-86 when detached ?? */ /* leave in for test site since there is */ /* no abort code and/or stop spooler */ end; end; return false; end list$buf; declare (nmbufs,actbuf) address; copy$file: procedure; declare ok byte; declare i word; /* for signed compare below */ do forever; actbuf = 0; ok = true; do while ok; call set$dma (bufptr.offset + actbuf * 128); if (ok := (readbf (.fcb) = 0)) then do; ok = ((actbuf := actbuf+1) < nmbufs); end; else do; if actbuf = 0 then return; end; end; do i = 1 to actbuf; if list$buf((i - 1) * 128) then return; end; end; end copy$file; declare local$buffer (512) byte; /* used if unsuccessful mem allocation */ declare pcb structure ( field$adr address, fcb$adr address) initial (0,.fcb); declare (ret,ret2) byte; declare nxt$chr$adr address; declare reserved$for$disk (3) byte; declare mcb structure ( base word, length word, ext byte) initial (0,0fffh,0); /* alloc 64k max */ declare uqcb literally 'structure ( q$id word, bufadr word, name (8) byte)'; declare mode1 lit '6'; /* offset in fcb for r/o attribute */ plmstart: procedure public; if high(version) <> mpmproduct then do; call print$console$buffer(.('Requires MP/M-86',0dh,0ah,'$')); call system$reset; end; nxt$chr$adr = .buff(0); /* make sure files exit */ do while (nxt$chr$adr <> 0); pcb.field$adr = nxt$chr$adr + 1; nxt$chr$adr = mon3 (parse$fname,.pcb); fcb(mode1) = fcb(mode1) or 080h; /* open files in read only mode */ if nxt$chr$adr = 0FFFFH then do; call print$console$buffer(.(0dh,0ah,'Illegal File Name',0dh,0ah,'$')); call system$reset; end; else if open (.fcb) = 0FFH then do; call print$console$buffer (.(0dh,0ah,'Can''t Open File = $')); fcb(12) = '$'; call print$console$buffer(.fcb(1)); call crlf; call system$reset; end; end; /* of while */ if ret = mon2(get$max$mem,.mcb) and mcb.length >= (size(local$buffer) / 16) + 8 then do; /* successful memory allocation and bigger than local buf */ if (nmbufs := shr (mcb.length,3)) > 512 then /* larger than 64K ? */ do; nmbufs = 512; mcb.base = mcb.base + 01000h; mcb.length = mcb.length - 01000h; mcb.ext = 0; call mon1(free$mem,.mcb); /* return extra memory past 64K */ end; call mon1(set$dma$base,mcb.base); bufptr.segment = mcb.base; bufptr.offset = 0; end; else /* not enough external memory: */ do; /* use buffer internal to program */ bufpointer = @local$buffer; nmbufs = size(local$buffer) / 128; end; call print$console$buffer(.( 'MP/M-86 V2.0 Spooler', 0dh, 0ah, '- Enter STOPSPLR to abort the spooler', 0dh, 0ah, '- Enter ATTACH SPOOL to re-attach console to spooler', 0dh, 0ah, '*** Spooler Detaching From Console ***$')); call mon1(detach,0); nxt$chr$adr = .buff(0); do while (nxt$chr$adr <> 0) and (nxt$chr$adr <> 0FFFFH); pcb.field$adr = nxt$chr$adr + 1; nxt$chr$adr = mon3 (parse$fname,.pcb); if nxt$chr$adr <> 0FFFFH then do; fcb(mode1) = fcb(mode1) or 080h; /* open files in read only mode */ if open (.fcb) <> 0FFH then do; fcb(32) = 0; call mon1(attach$list,0); call copy$file; call mon1(detach$list,0); call free$drives; end; end; end; /* of while */ call system$reset; end plmstart; end spool;