$title ('MP/M II V2.0 Submit') submit: do; $include (copyrt.lit) /* Revised: 14 Sept 81 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 maxb address external; 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; set$DMA: procedure (DMA$address); declare DMA$address address; call mon1 (26,DMA$address); end set$DMA; getuser: procedure byte; return mon2 (32,0ffh); end getuser; read$random: procedure (fcb$address); declare fcb$address address; call mon1 (33,fcb$address); end read$random; compute$file$size: procedure (fcb$address); declare fcb$address address; call mon1 (35,fcb$address); end compute$file$size; /************************************** * * * X D O S Externals * * * **************************************/ terminate: procedure; call mon1 (143,0); end terminate; parse$filename: procedure (pfcb$address) address; declare pfcb$address address; return mon2a (152,pfcb$address); end parse$filename; 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) 1981, Digital Research '); declare subflgadr address; declare subflg based subflgadr (1) byte; declare tmpfiledradr address; declare tmpfiledr based tmpfiledradr byte; declare include$level byte initial (0), cur$console byte, pfcb structure ( ASCII$string address, FCB$address address ) initial ( .a$buff, .a$sfcb ), 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 */ a$buff(128) byte at(.tbuff), /* default buffer */ a$sfcb(33) byte at(.fcb); /* default fcb */ declare (sfcb$adr,buff$adr,sstring$adr,sbp$adr) address, sfcb based sfcb$adr (33) byte, buff based buff$adr (128) byte, sstring based sstring$adr (128) byte, sbp based sbp$adr byte; declare source (4) structure ( sfcb (36) byte, buff (128) byte, sstring (128) byte, sbp byte ); /* 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$adr: procedure; sfcb$adr = .source(include$level).sfcb; buff$adr = .source(include$level).buff; sstring$adr = .source(include$level).sstring; sbp$adr = .source(include$level).sbp; call set$DMA (.buff); end setup$adr; setup: procedure; call setup$adr; call move (.a$sfcb,.sfcb,33); call move (.a$buff,.buff,128); subflgadr = system$data$adr + 128; cur$console = get$console$number; console = cur$console + '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; do forever; do while sbp > 127; if read$record (.sfcb) <> 0 then do; if include$level = 0 then return endfile; include$level = include$level - 1; call setup$adr; end; else 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 *| */ if (b <> endfile) or ((b = endfile) and (include$level = 0)) then return b; else do; include$level = include$level - 1; call setup$adr; end; end; 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(1) byte at (.minimum$buffer), /* 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) > (maxb-.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,fptr) byte; /* fill the jcl buffer */ rbuff(0) = 0ffh; 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 do; if (b and 0101$1111b) = 'I' then do; /* process include */ if (include$level:=include$level+1) = 4 then call error (.( 'Exceeding 4 include levels$')); do while (b:=getsource) <> ' '; end; fptr = 0; b = getsource; do while (b <> ' ') and (b <> cr ); a$buff(fptr) = b; if (fptr:=fptr+1) > 127 then call error (.( 'Include filename too long$')); b = getsource; end; a$buff(fptr) = '$'; call print$console$buffer (.(cr,lf,'$')); call print$console$buffer (.('Include $')); call print$console$buffer (.a$buff); a$buff(fptr) = cr; if parse$filename (.pfcb) = 0ffffh then call error (.( 'Bad include filename$')); if (a$buff(fptr):=b) <> cr then do; fptr = fptr + 1; b = getsource; do while b <> cr; if b = '$' then do; b = getsource; if b <> '$' then do; if (b := b - '0') > 9 then call error (.('parameter error$')); sstringadr = .source(include$level-1).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; a$buff(fptr) = s; fptr = fptr + 1; end; fptr = fptr - 1; sstringadr = .source(include$level).sstring; end; else do; a$buff(fptr) = b; end; end; else do; a$buff(fptr) = b; end; if (fptr:=fptr+1) > 127 then call error (.( 'Include substring too long$')); b = getsource; end; end; a$buff(0) = fptr - 1; call setup; end; else do; 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; end; end; else /* not a '$' */ do; 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; 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; tmpfiledradr = system$data$adr + 196; dfcb(0) = tmpfiledr; 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) <> 0ffh; /* 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(cur$console) = (getuser or 1111$0000b); end makefile; declare minimum$buffer (1024) byte; declare last$dseg$byte byte initial (0); start: do; call setup; call fillrbuff; call makefile; call terminate; end; end submit;