sub: do; /* modified 7/26/79 to work with cpm 2.0, module number not zero */ declare wboot literally '0000h', /* warm start entry point */ bdos literally '0005h', /* jmp bdos */ dfcba literally '005ch', /* default fcb address */ dbuff literally '0080h'; /* default buffer address */ declare jump byte data(0c3h); /* c3 = jmp */ declare jadr address data(.submit); /* jmp to submit is placed at the beginning of the module */ boot: procedure external; /* system reboot */ end boot; mon1: procedure(f,a) external; declare f byte, a address; /* bdos interface, no returned value */ end mon1; mon2: procedure(f,a) byte external; declare f byte, a address; /* bdos interface, return byte value */ end mon2; declare copyright(*) byte data (' copyright(c) 1977, digital research '); 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(0,'$$$ SUB',0,0,0), drec byte at(.dfcb(32)), /* current record */ buff(128) byte at(dbuff), /* default buffer */ sfcb(33) byte at(dfcba); /* default fcb */ submit: procedure; /* t h e c p / m 's u b m i t' f u n c t i o n copyright (c) 1976, 1977, 1978 digital research box 579 pacific grove, ca. 93950 */ declare lit literally 'literally', dcl lit 'declare', proc lit 'procedure', addr lit 'address', ctll lit '0ch', 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'; print: procedure(a); declare a address; /* print the string starting at address a until the next dollar sign is encountered */ call mon1(9,a); end print; declare dcnt byte; open: procedure(fcb); declare fcb address; dcnt = mon2(15,fcb); end open; close: procedure(fcb); declare fcb address; dcnt = mon2(16,fcb); end close; delete: procedure(fcb); declare fcb address; call mon1(19,fcb); end delete; diskread: procedure(fcb) byte; declare fcb address; return mon2(20,fcb); end diskread; diskwrite: procedure(fcb) byte; declare fcb address; return mon2(21,fcb); end diskwrite; make: procedure(fcb); declare fcb address; dcnt = mon2(22,fcb); end make; 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; declare oldsp address; /* calling program's stack pointer */ error: procedure(a); declare a address; call print(.(cr,lf,'$')); call print(.('Error On Line $')); call print(.ln1); call print(a); stackptr = oldsp; /* return to ccp */ end error; declare sstring(128) byte, /* substitute string */ sbp byte; /* source buffer pointer (0-128) */ setup: procedure; /* 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 */ call open(.sfcb(0)); if dcnt = 255 then call error(.('No ''SUB'' File Present$')); /* otherwise file is open - read subsequent data */ sbp = 128; /* causes read below */ end setup; getsource: procedure byte; /* read the next source character */ declare b byte; if sbp > 127 then do; if diskread(.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 diskwrite(.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(.dfcb); drec = 0; /* zero the next record to write */ call make(.dfcb); if dcnt = 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; call close(.dfcb); if dcnt = 255 then call error(.('Cannot Close, Read/Only?$')); end makefile; /* enter here from the ccp with the fcb set */ declare stack(10) address; /* working stack */ oldsp = stackptr; stackptr = .stack(length(stack)); call setup; call fillrbuff; call makefile; call boot; /* reboot causes commands to be executed */ end submit; end;