Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

294 lines
8.3 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;