$title ('MP/M 1.1 Submit') submit: do; $include (copyrt.lit) /* Revised: 19 Jan 80 by Thomas Rolander */ declare start label; declare jmp$to$start structure ( jmp$instr byte, jmp$location address ) data ( 0C3H, .start-3); 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; mon2a: procedure (func,info) address external; declare func byte; declare info address; end mon2a; declare fcb (1) byte external; declare fcb16 (1) byte external; declare tbuff (1) byte external; /************************************** * * * B D O S Externals * * * **************************************/ print$console$buffer: procedure (buffer$address); declare buffer$address address; call mon1 (9,buffer$address); end print$console$buffer; open$file: procedure (fcb$address) byte; declare fcb$address address; return mon2 (15,fcb$address); end open$file; close$file: procedure (fcb$address) byte; declare fcb$address address; return mon2 (16,fcb$address); end close$file; delete$file: procedure (fcb$address); declare fcb$address address; call mon1 (19,fcb$address); end delete$file; read$record: procedure (fcb$address) byte; declare fcb$address address; return mon2 (20,fcb$address); end read$record; write$record: procedure (fcb$address) byte; declare fcb$address address; return mon2 (21,fcb$address); end write$record; create$file: procedure (fcb$address) byte; declare fcb$address address; return mon2 (22,fcb$address); end create$file; /************************************** * * * X D O S Externals * * * **************************************/ terminate: procedure; call mon1 (143,0); end terminate; get$console$number: procedure byte; return mon2 (153,0); end get$console$number; system$data$adr: procedure address; return mon2a (154,0); end system$data$adr; declare copyright(*) byte data (' Copyright(c) 1979, Digital Research '); declare subflgadr address; declare subflg based subflgadr (1) byte; declare ln(5) byte initial('001 $'), ln1 byte at(.ln(0)), ln2 byte at(.ln(1)), ln3 byte at(.ln(2)), dfcb(33) byte initial(1,'$$$ ','SUB',0), console byte at(.dfcb(2)), /* current console number */ drec byte at(.dfcb(32)), /* current record */ buff(128) byte at(.tbuff), /* default buffer */ sfcb(33) byte at(.fcb); /* default fcb */ /* t h e m p / m 's u b m i t' f u n c t i o n */ declare lit literally 'literally', dcl lit 'declare', proc lit 'procedure', addr lit 'address', lca lit '110$0001b', /* lower case a */ lcz lit '111$1010b', /* lower case z */ endfile lit '1ah'; /* cp/m end of file */ declare true literally '1', false literally '0', forever literally 'while true', cr literally '13', lf literally '10', what literally '63'; move: procedure(s,d,n); declare (s,d) address, n byte; declare a based s byte, b based d byte; do while (n := n - 1) <> 255; b = a; s = s + 1; d = d + 1; end; end move; error: procedure(a); declare a address; call print$console$buffer(.(cr,lf,'$')); call print$console$buffer(.('error on line $')); call print$console$buffer(.ln1); call print$console$buffer(a); call terminate; end error; declare sstring(128) byte, /* substitute string */ sbp byte; /* source buffer pointer (0-128) */ setup: procedure; subflgadr = system$data$adr + 128; console = get$console$number + '0'; /* move buffer to substitute string */ call move(.buff(1),.sstring(0),127); sstring(buff(0))=0; /* mark end of string */ call move(.('SUB'),.sfcb(9),3); /* set file type to sub */ if open$file(.sfcb(0)) = 255 then call error(.('no ''SUB'' file present$')); /* otherwise file is open - read subsequent data */ sbp = 128; /* causes read below */ sfcb(32) = 0; /* nr = 0 for sub file to read */ end setup; getsource: procedure byte; /* read the next source character */ declare b byte; if sbp > 127 then do; if read$record(.sfcb(0)) <> 0 then return endfile; sbp = 0; end; if (b := buff((sbp:=sbp+1)-1)) = cr then do; /* increment line */ if (ln3 := ln3 + 1) > '9' then do; ln3 = '0'; if (ln2 := ln2 + 1) > '9' then do; ln2 = '0'; ln1 = ln1 + 1; end; end; end; /* translate to upper case */ if (b-61h) < 26 then /* lower case alpha */ b = b and 5fh; /* change to upper case */ return b; end getsource; writebuff: procedure; /* write the contents of the buffer to disk */ if write$record(.dfcb) <> 0 then /* error */ call error(.('disk write error$')); end writebuff; declare rbuff(2048) byte, /* jcl buffer */ rbp address, /* jcl buffer pointer */ rlen byte; /* length of current command */ fillrbuff: procedure; declare (s,ssbp) byte; /* sub string buffer pointer */ notend: procedure byte; /* look at next character in sstring, return true if not at the end of the string - char passed back in 's' */ if not ((s := sstring(ssbp)) = ' ' or s = 0) then do; ssbp = ssbp + 1; return true; end; return false; end notend; deblankparm: procedure; /* clear to next non blank substitute string */ do while sstring(ssbp) = ' '; ssbp = ssbp + 1; end; end deblankparm; putrbuff: procedure(b); declare b byte; if (rbp := rbp + 1) > last(rbuff) then call error(.('command buffer overflow$')); rbuff(rbp) = b; /* len: c1 ... c125 :00:$ = 128 chars */ if (rlen := rlen + 1) > 125 then call error(.('command too long$')); end putrbuff; declare (reading,b) byte; /* fill the jcl buffer */ rbuff(0),rbp = 0; reading = true; do while reading; rlen = 0; /* reset command length */ do while (b:=getsource) <> endfile and b <> cr; if b <> lf then do; if b = '$' then /* copy substitute string */ do; if (b:=getsource) = '$' then /* $$ replaced by $ */ call putrbuff(b); else if (b := b - '0') > 9 then call error(.('parameter error$')); else do; /* find string 'b' in sstring */ ssbp = 0; call deblankparm; /* ready to scan sstring */ do while b <> 0; b = b - 1; /* clear next parameter */ do while notend; end; call deblankparm; end; /* ready to copy substitute string from position ssbp */ do while notend; call putrbuff(s); end; end; end; else /* not a '$' */ if b = '^' then /* control character */ do; /* must be ^a ... ^z */ if (b:=getsource - 'A') > 25 then call error(.( 'invalid control character$')); else call putrbuff(b+1); end; else /* not $ or ^ */ call putrbuff(b); end; end; /* of line or input file - compute length */ reading = b = cr; call putrbuff(rlen); /* store length */ end; /* entire file has been read and processed */ end fillrbuff; makefile: procedure; /* write resulting command file */ declare i byte; getrbuff: procedure byte; return rbuff(rbp := rbp - 1); end getrbuff; call delete$file(.dfcb); drec = 0; /* zero the next record to write */ if create$file(.dfcb) = 255 then call error(.('directory full$')); do while (i := getrbuff) <> 0; /* copy i characters to buffer */ /* 00 $ at end of line gives 1.3 & 1.4 compatibility */ buff(0) = i; buff(i+1) = 00; buff(i+2) = '$'; do while i > 0; buff(i) = getrbuff; i=i-1; end; /* buffer filled to $ */ call writebuff; end; if close$file(.dfcb) = 255 then call error(.('close error$')); else subflg(get$console$number) = true; end makefile; declare last$dseg$byte byte initial (0); start: do; call setup; call fillrbuff; call makefile; call terminate; end; end submit;