mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-25 17:34:06 +00:00
838 lines
23 KiB
Plaintext
838 lines
23 KiB
Plaintext
$title ('GENDEF - Library Generator for DISKDEF')
|
||
gd:
|
||
do;
|
||
|
||
/* l i b r a r y g e n e r a t o r f o r D I S K D E F */
|
||
|
||
$include(copyrt.lit)
|
||
|
||
/* Generation Procedure on VAX
|
||
|
||
asm86 scd.a86
|
||
plm86 gendef.plm debug xref optimize(3) date(10/5/81) pagewidth(100)
|
||
plm86 gscan.plm debug xref optimize(3) date(10/5/81) pagewidth(100)
|
||
plm86 emit.plm debug xref optimize(3) date(10/5/81) pagewidth(100)
|
||
plm86 token.plm debug xref optimize(3) date(10/5/81) pagewidth(100)
|
||
link86 scd.obj,gendef.obj,gscan.obj,emit.obj,token.obj -
|
||
to gendef.lnk
|
||
loc86 gendef.mod od(sm(code,dats,data,stack,const)) -
|
||
ad(sm(code(0h))) ss(stack(+32))
|
||
h86 gendef
|
||
|
||
Then on a micro
|
||
|
||
vax gendef $fans
|
||
gencmd gendef data[b17c]
|
||
|
||
notes:
|
||
b17c is derived from module map in the GENDEF.MP2 file generated
|
||
by LOC86. The 'CONST segment' is located last to force hex
|
||
generation. Stack is extended to insure against interrupts on
|
||
MP/M-86.
|
||
|
||
*/
|
||
|
||
|
||
$include (:f1:glit.plb)
|
||
|
||
declare
|
||
true lit '1',
|
||
false lit '0',
|
||
forever lit 'while true',
|
||
cr lit '0dh',
|
||
tab lit '09h';
|
||
|
||
/* global procedures */
|
||
|
||
boot: procedure external;
|
||
end boot;
|
||
|
||
printchar: procedure(c) external;
|
||
declare c byte;
|
||
end printchar;
|
||
|
||
print: procedure(a) external;
|
||
declare a address;
|
||
end print;
|
||
|
||
crlf: procedure external;
|
||
end crlf;
|
||
|
||
abort: procedure(msg) external;
|
||
declare msg address;
|
||
end abort;
|
||
|
||
scan: procedure external;
|
||
end scan;
|
||
|
||
scan$ini: procedure external;
|
||
end scan$ini;
|
||
|
||
setup: procedure external;
|
||
/* set up the input file on each pass */
|
||
end setup;
|
||
|
||
putline: procedure external;
|
||
end putline;
|
||
|
||
writerrs: procedure external;
|
||
end writerrs;
|
||
|
||
errptr: procedure(msg) external;
|
||
declare msg address;
|
||
end errptr;
|
||
|
||
/* code emitters */
|
||
emitbyte: procedure(b) external;
|
||
declare b byte;
|
||
end emitbyte;
|
||
|
||
emitcrlf: procedure external;
|
||
end emitcrlf;
|
||
|
||
emitoptab: procedure(a) external;
|
||
declare a address;
|
||
end emitoptab;
|
||
|
||
emitcomma: procedure external;
|
||
end emitcomma;
|
||
|
||
emitaddr: procedure(a) external;
|
||
declare a address;
|
||
end emitaddr;
|
||
|
||
emitchar: procedure(a) external;
|
||
declare a address;
|
||
end emitchar;
|
||
|
||
emitline: procedure external;
|
||
end emitline;
|
||
|
||
emitcharn: procedure(a,n) external;
|
||
declare a address, n byte;
|
||
/* symbol, followed by two digit n */
|
||
end emitcharn;
|
||
|
||
emitcomment: procedure(a) external;
|
||
declare a address;
|
||
end emitcomment;
|
||
|
||
emitdec8: procedure(b) external;
|
||
declare b byte;
|
||
end emitdec8;
|
||
|
||
emitdec16: procedure(w) external;
|
||
declare w address;
|
||
end emitdec16;
|
||
|
||
emitdecb: procedure(w) external;
|
||
declare w address;
|
||
end emitdecb;
|
||
|
||
emitdw: procedure external;
|
||
end emitdw;
|
||
|
||
emitdb: procedure external;
|
||
end emitdb;
|
||
|
||
emitdwn: procedure(n) external;
|
||
declare n address;
|
||
end emitdwn;
|
||
|
||
emitdbn: procedure(n) external;
|
||
declare n byte;
|
||
end emitdbn;
|
||
|
||
emitdwnc: procedure(n,c) external;
|
||
declare (n,c) address;
|
||
end emitdwnc;
|
||
|
||
emitdbnc: procedure(n,c) external;
|
||
declare n byte, c address;
|
||
end emitdbnc;
|
||
|
||
efinis: procedure external;
|
||
end efinis;
|
||
|
||
emittab: procedure external;
|
||
end emittab;
|
||
|
||
emitnulcom: procedure external;
|
||
end emitnulcom;
|
||
|
||
/* global variables */
|
||
declare
|
||
parm (26) byte external,
|
||
comm$tog byte at (.parm(2)), /* disk comment */
|
||
off$tog byte at (.parm(14)), /* generate 'offset' */
|
||
scan$tog byte at (.parm(18)), /* scanner trace */
|
||
z80$tog byte at (.parm(25)); /* z80, 8080, 8085 mode */
|
||
|
||
declare
|
||
errset byte external,
|
||
eofset byte external,
|
||
cbuff(8) byte external,
|
||
value address external,
|
||
nextc byte external,
|
||
token byte external,
|
||
continue byte external,
|
||
acclen byte external,
|
||
accum(32) byte external;
|
||
|
||
/* code emitters */
|
||
setemit: procedure external;
|
||
end setemit;
|
||
|
||
prnib: procedure(d);
|
||
declare d byte;
|
||
/* print nibble d */
|
||
if d > 9 then
|
||
d = 'A' + d - 10; else
|
||
d = d + '0';
|
||
call printchar(d);
|
||
end prnib;
|
||
|
||
prhex: procedure(h);
|
||
declare h byte;
|
||
call prnib(shr(h,4));
|
||
call prnib(h and 0fh);
|
||
end prhex;
|
||
|
||
praddr: procedure(a);
|
||
declare a address;
|
||
call prhex(high(a));
|
||
call prhex(low(a));
|
||
end praddr;
|
||
|
||
prdig: procedure(d);
|
||
declare d byte;
|
||
/* print the decimal number given by d */
|
||
call printchar('0'+d);
|
||
end prdig;
|
||
|
||
prdec: procedure(b);
|
||
declare b byte;
|
||
/* print the decimal value of b */
|
||
call prdig(b/100);
|
||
call prdig(b/10 mod 10);
|
||
call prdig(b mod 10);
|
||
end prdec;
|
||
|
||
/* trace functions */
|
||
|
||
declare
|
||
ident lit '1',
|
||
number lit '2',
|
||
string lit '3',
|
||
special lit '4';
|
||
|
||
trace: procedure(msga);
|
||
declare
|
||
msga address,
|
||
(i,c) byte;
|
||
if scan$tog then
|
||
do;
|
||
call putline;
|
||
call print(msga);
|
||
call printchar(',');
|
||
do i = 1 to acclen;
|
||
if (c:=accum(i-1)) < ' ' then
|
||
do;
|
||
call printchar('#');
|
||
call prhex(c);
|
||
end; else
|
||
call printchar(c);
|
||
end;
|
||
call printchar(':');
|
||
call prdec(token);
|
||
if token = number then
|
||
do;
|
||
call printchar(',');
|
||
call praddr(value);
|
||
call printchar('H');
|
||
end;
|
||
if eofset then
|
||
call print(.('End-File$'));
|
||
end;
|
||
end trace;
|
||
|
||
/* parsing procedures for non terminals */
|
||
|
||
bypass: procedure(x) byte;
|
||
declare x byte;
|
||
if token = x then
|
||
do;
|
||
call scan;
|
||
return true;
|
||
end;
|
||
return false;
|
||
end bypass;
|
||
|
||
declare eltinx byte; /* index into set when 'element' returns true */
|
||
|
||
element: procedure(list) byte;
|
||
declare list address; /* address of set to search */
|
||
/* element searches for the current token in the set of
|
||
tokens addressed by 'list' and returns true if item is
|
||
found. as a side-effect, 'eltinx' is set to the item's index */
|
||
declare set based list (1) byte, x byte;
|
||
eltinx = -1;
|
||
do forever;
|
||
if (x := set(eltinx:=eltinx+1)) = 0 then return false;
|
||
if token = x then return true;
|
||
end;
|
||
end element;
|
||
|
||
endline: procedure byte;
|
||
/* return true if end of line or file */
|
||
return (token = cr) or eofset;
|
||
end endline;
|
||
|
||
recover: procedure;
|
||
do while not endline;
|
||
call scan;
|
||
end;
|
||
end recover;
|
||
|
||
emitdollar: procedure;
|
||
if not z80$tog then
|
||
call emitchar(.('offset $'));
|
||
call emitbyte('$');
|
||
end emitdollar;
|
||
|
||
declare
|
||
/* diskdef parameter values */
|
||
maxdisks lit '16',
|
||
ndisks byte, /* number of disks */
|
||
diskset (maxdisks) byte; /* true if included in diskdef */
|
||
|
||
disks: procedure;
|
||
/* handle the disks n macro */
|
||
declare i byte;
|
||
if ndisks > 0 then
|
||
ndisks = 0; else
|
||
if token = number then
|
||
ndisks = value; else
|
||
ndisks = 0;
|
||
if ndisks = 0 or ndisks > maxdisks then
|
||
call errptr(.('bad val$'));
|
||
call scan;
|
||
/* dpbase equ $ */
|
||
call emitchar(.('dpbase$'));
|
||
call emitoptab(.('equ$'));
|
||
if off$tog then
|
||
call emitdollar; else
|
||
call emitbyte('$');
|
||
call emitcomment(.('Base of Disk Parameter Blocks$'));
|
||
do i = 1 to ndisks;
|
||
/* dpe00: dw xlt00,0000h */
|
||
call emitcharn(.('dpe$'),i-1);
|
||
if z80$tog then
|
||
call emitbyte(':');
|
||
call emitdw;
|
||
call emitcharn(.('xlt$'),i-1);
|
||
call emitcomma;
|
||
call emitaddr(0);
|
||
call emitcomment(.('Translate Table$'));
|
||
/* dw 0000h,0000h */
|
||
call emitdw;
|
||
call emitaddr(0);
|
||
call emitcomma;
|
||
call emitaddr(0);
|
||
call emitcomment(.('Scratch Area$'));
|
||
/* dw dirbuf,dpb00 */
|
||
call emitdw;
|
||
call emitchar(.('dirbuf,$'));
|
||
call emitcharn(.('dpb$'),i-1);
|
||
call emitcomment(.('Dir Buff, Parm Block$'));
|
||
/* dw csv00,alv00 */
|
||
call emitdw;
|
||
call emitcharn(.('csv$'),i-1);
|
||
call emitcomma;
|
||
call emitcharn(.('alv$'),i-1);
|
||
call emitcomment(.('Check, Alloc Vectors$'));
|
||
end;
|
||
end disks;
|
||
|
||
declare
|
||
npar lit '11',
|
||
rpar lit '9', /* no. of required parms */
|
||
dn lit '0', /* disk number */
|
||
fsc lit '1', /* first sector */
|
||
lsc lit '2', /* last sector */
|
||
skf lit '3', /* skew factor */
|
||
bls lit '4', /* block size */
|
||
dks lit '5', /* disk size */
|
||
dir lit '6', /* directory size */
|
||
cks lit '7', /* check sum size */
|
||
ofs lit '8', /* offset tracks */
|
||
com lit '9', /* CP/M 1.4 compatibility flag */
|
||
prm lit '10'; /* permanent disk drive */
|
||
|
||
declare
|
||
lower (*) address data
|
||
/* dn fsc lsc skf bls */
|
||
(0000, 0000, 0001, 0000, 1024,
|
||
/* dks dir cks ofs com */
|
||
0001, 0001, 0000, 0000, 0000,
|
||
/* prm */
|
||
0000),
|
||
upper (*) address data
|
||
/* dn fsc lsc skf bls */
|
||
(0015, 0015, 65535, 0255, 16384,
|
||
/* dks dir cks ofs com */
|
||
65535, 65534, 65534, 65535, 0000,
|
||
/* prm */
|
||
0000),
|
||
optional (*) byte data
|
||
/* dn fsc lsc skf bls */
|
||
(false, false, false, true, false,
|
||
/* dks dir cks ofs com */
|
||
false, false, false, false, true,
|
||
/* prm */
|
||
true);
|
||
|
||
declare
|
||
dsmax (*) address data
|
||
/* value of bls */
|
||
/* 1024 2048 4096 8192 16384 */
|
||
( 8192, 4096, 2048, 1024, 512 );
|
||
|
||
declare
|
||
bsh (*) byte data
|
||
/* 1024 2048 4096 8192 16384 */
|
||
( 3, 4, 5, 6, 7 ),
|
||
blm (*) byte data
|
||
/* 1024 2048 4096 8192 16384 */
|
||
( 7, 15, 31, 63, 127 ),
|
||
dsm (*) byte data
|
||
/* 1024 2048 4096 8192 16384 */
|
||
( 0, 1, 3, 7, 15 );
|
||
|
||
declare
|
||
ddir (*) address data
|
||
/* 1024 2048 4096 8192 16384 */
|
||
( 32, 64, 128, 256, 512 );
|
||
|
||
range: procedure;
|
||
call errptr(.('range $'));
|
||
end range;
|
||
|
||
diskdef: procedure;
|
||
/* handle diskdef, first item scanned */
|
||
declare
|
||
pv (npar) address,
|
||
parmissing (npar) byte,
|
||
(pc, i) byte,
|
||
(d, v) address;
|
||
declare
|
||
sectors address,
|
||
(nxtsec, nxtbas, neltst, nelts) address;
|
||
|
||
gcd: procedure(m,n) address;
|
||
declare (m,n,r) address;
|
||
do forever;
|
||
r = m mod n;
|
||
if r = 0 then
|
||
return n;
|
||
m = n;
|
||
n = r;
|
||
end;
|
||
end gcd;
|
||
|
||
equiv: procedure(a,b);
|
||
declare (a,b) address;
|
||
/* dpb1 equ dpb0 */
|
||
call emitcharn(a,pv(0));
|
||
call emitoptab(.('equ$'));
|
||
call emitcharn(a,pv(1));
|
||
call emitcomment(b);
|
||
end equiv;
|
||
|
||
comment: procedure(v,a);
|
||
declare (v, a) address;
|
||
/* write diskdef comment line */
|
||
call emitbyte(';');
|
||
call emittab;
|
||
call emitdecb(v);
|
||
call emitbyte(':');
|
||
call emittab;
|
||
call emitchar(a);
|
||
call emitcrlf;
|
||
end comment;
|
||
|
||
do i = 0 to last(parmissing);
|
||
parmissing(i) = true;
|
||
end;
|
||
pc = 0;
|
||
token = ',';
|
||
do while not (endline or pc = npar);
|
||
call trace(.(' diskparm$'));
|
||
pv(pc) = 0;
|
||
if not bypass(',') then
|
||
call errptr(.('delimit$')); else
|
||
if (parmissing (pc) :=
|
||
(token = cr or token = ',')) then
|
||
do;
|
||
if not optional(pc) then
|
||
call errptr(.('missing$'));
|
||
end; else
|
||
do;
|
||
if token <> number then
|
||
call errptr(.('numeric$')); else
|
||
do;
|
||
/* numeric value, check range */
|
||
if value < lower(pc) or
|
||
value > upper(pc) then
|
||
call range; else
|
||
/* make special range checks */
|
||
if pc = dn then
|
||
do;
|
||
if diskset(value) then
|
||
call errptr(.('duplic $'));
|
||
diskset(value) = true;
|
||
end; else
|
||
if pc = lsc and value <= pv(fsc) then
|
||
call range; else
|
||
if pc = skf and
|
||
value > (pv(lsc) - pv(fsc)) then
|
||
call range; else
|
||
if pc = bls then
|
||
do;
|
||
if value = 1024 then value = 0; else
|
||
if value = 2048 then value = 1; else
|
||
if value = 4096 then value = 2; else
|
||
if value = 8192 then value = 3; else
|
||
if value = 16384 then value = 4; else
|
||
call range;
|
||
end; else
|
||
if pc = dks then
|
||
do;
|
||
if value > 256 and pv(bls) = 0 then
|
||
call range; else
|
||
if value > dsmax(pv(bls)) then
|
||
call range;
|
||
end; else
|
||
if pc = dir then
|
||
do;
|
||
if (value and 11b) <> 0 then
|
||
call range; else
|
||
do;
|
||
/* compute alloc vector */
|
||
v = 0;
|
||
d = value;
|
||
/* loop until zero or negative */
|
||
do while not rol(high(d-1),1);
|
||
d = d - ddir(pv(bls));
|
||
if low(v) then
|
||
do;
|
||
call errptr(.('Alloc $'));
|
||
d = 0;
|
||
end; else
|
||
v = shr(v,1) or 8000h;
|
||
end;
|
||
end;
|
||
end; else
|
||
if pc = cks and ((value and 11b) <> 0 or
|
||
value > pv(dir)) then
|
||
call range;
|
||
if pc = prm and pv(cks) > 0 then
|
||
call errptr(.('conflict$'));
|
||
pv(pc) = value;
|
||
end;
|
||
call scan;
|
||
end;
|
||
if errset then
|
||
return;
|
||
pc = pc + 1;
|
||
end;
|
||
/* check for abbreviated form */
|
||
if not endline then
|
||
return;
|
||
if pc = 2 then
|
||
do;
|
||
if not diskset(pv(1)) then
|
||
call errptr(.('no disk$'));
|
||
if comm$tog then
|
||
do;
|
||
call emitnulcom;
|
||
call emitbyte(';');
|
||
call emittab;
|
||
call emitchar(.('Disk $'));
|
||
call emitdec8(pv(0));
|
||
call emitchar(.(' is the same as Disk $'));
|
||
call emitdec8(pv(1));
|
||
call emitcrlf;
|
||
call emitnulcom;
|
||
end;
|
||
call equiv(.('dpb$'),.('Equivalent Parameters$'));
|
||
call equiv(.('als$'),.('Same Allocation Vector Size$'));
|
||
call equiv(.('css$'),.('Same Checksum Vector Size$'));
|
||
call equiv(.('xlt$'),.('Same Translate Table$'));
|
||
return;
|
||
end; else
|
||
if pc < rpar then
|
||
do;
|
||
call errptr(.('too few$'));
|
||
return;
|
||
end;
|
||
/* write general disk statistics */
|
||
sectors = pv(lsc) - pv(fsc) + 1;
|
||
if pv(skf) = 0 then parmissing(skf) = true;
|
||
if comm$tog then
|
||
do;
|
||
/* ;<crlf>;<tab>Disk 000 is CP/M 1.4 Single(/Double) .. */
|
||
call emitnulcom;
|
||
if not parmissing(com) then
|
||
do;
|
||
call emitbyte(';');
|
||
call emittab;
|
||
call emitchar(.('Disk $'));
|
||
call emitdec8(pv(dn));
|
||
call emitchar(
|
||
.(' is CP/M 1.4 Double Density Compatible$'));
|
||
call emitcrlf;
|
||
end;
|
||
/* pv(dks) * 8/16/32/64/128 for 1k/2k/4k/8k/16k */
|
||
d = pv (dks) * shl(100b,pv(bls)+1);
|
||
call emitbyte(';');
|
||
call emittab;
|
||
if d > 0 then
|
||
call emitdecb(d); else
|
||
call emitchar(.('65536$'));
|
||
call emitbyte(':');
|
||
call emittab;
|
||
call emitchar(.('128 Byte Record Capacity$'));
|
||
call emitcrlf;
|
||
/* pv(dks) * 1k/2k/4k/8k/16k */
|
||
d = 1;
|
||
if pv(bls) > 0 then
|
||
d = shl(d,pv(bls));
|
||
call comment(pv(dks) * d,.('Kilobyte Drive Capacity$'));
|
||
call comment(pv(dir),.('32 Byte Directory Entries$'));
|
||
call comment(pv(cks),.('Checked Directory Entries$'));
|
||
if not parmissing(com) then
|
||
d = 128; else
|
||
do;
|
||
/* extents are folded */
|
||
if pv(dks) > 256 then
|
||
d = 32; else d = 64;
|
||
d = shl(d,pv(bls)+1);
|
||
end;
|
||
call comment(d,.('Records / Extent$'));
|
||
call comment(shl(100b,pv(bls)+1),
|
||
.('Records / Block$'));
|
||
call comment(sectors,.('Sectors / Track$'));
|
||
call comment(pv(ofs),.('Reserved Tracks$'));
|
||
if not parmissing(skf) then
|
||
call comment(pv(skf),.('Sector Skew Factor$'));
|
||
call emitnulcom;
|
||
end;
|
||
/* dpb0 equ $ */
|
||
call emitcharn(.('dpb$'),pv(dn));
|
||
call emitoptab(.('equ$'));
|
||
call emitdollar;
|
||
call emitcomment(.('Disk Parameter Block$'));
|
||
call emitdwnc(sectors,
|
||
.('Sectors Per Track$'));
|
||
call emitdbnc(bsh(pv(bls)),
|
||
.('Block Shift$'));
|
||
call emitdbnc(blm(pv(bls)),
|
||
.('Block Mask$'));
|
||
i = pv(bls);
|
||
if pv(dks) > 256 then
|
||
i = i - 1;
|
||
if parmissing(com) then
|
||
call emitdbnc(dsm(i),.('Extnt Mask$')); else
|
||
call emitdbnc(pv(com),.('1.4 Compatible$'));
|
||
call emitdwnc(pv(dks)-1,.('Disk Size - 1$'));
|
||
call emitdwnc(pv(dir)-1,.('Directory Max$'));
|
||
/* compute allocation vector initialization */
|
||
call emitdbnc(high(v),.('Alloc0$'));
|
||
call emitdbnc(low(v),.('Alloc1$'));
|
||
if parmissing(prm) then
|
||
call emitdwnc(pv(cks)/4,.('Check Size$')); else
|
||
call emitdwnc(8000h,.('Permanent Disk$'));
|
||
call emitdwnc(pv(ofs),.('Offset$'));
|
||
|
||
/* generate allocation vector */
|
||
call emitcharn(.('xlt$'),pv(dn));
|
||
call emitoptab(.('equ$'));
|
||
if parmissing(skf) then
|
||
do;
|
||
call emitdec8(0);
|
||
call emitcomment(.('No Translate Table$'));
|
||
end; else
|
||
do;
|
||
call emitdollar;
|
||
call emitcomment(.('Translate Table$'));
|
||
nxtsec, nxtbas = 0;
|
||
neltst = sectors/gcd(sectors,pv(skf));
|
||
nelts = neltst;
|
||
do d = 0 to sectors-1;
|
||
if d mod 4 <> 0 then
|
||
call emitcomma; else
|
||
do;
|
||
if d > 0 then
|
||
call emitcrlf;
|
||
if sectors < 256 then
|
||
call emitdb; else
|
||
call emitdw;
|
||
end;
|
||
call emitdec16(nxtsec+pv(fsc));
|
||
nxtsec = nxtsec + pv(skf);
|
||
if nxtsec >= sectors then
|
||
nxtsec = nxtsec - sectors;
|
||
if (nelts := nelts - 1) = 0 then
|
||
do;
|
||
nxtsec = (nxtbas := nxtbas + 1);
|
||
nelts = neltst;
|
||
end;
|
||
end;
|
||
call emitcrlf;
|
||
end;
|
||
|
||
/* generate allocation vector size */
|
||
call emitcharn(.('als$'),pv(dn));
|
||
call emitoptab(.('equ$'));
|
||
d = pv(dks)/8;
|
||
if pv(dks) mod 8 <> 0 then
|
||
d = d + 1;
|
||
call emitdec16(d);
|
||
call emitcomment(.('Allocation Vector Size$'));
|
||
|
||
/* generate checksum vector size */
|
||
call emitcharn(.('css$'),pv(dn));
|
||
call emitoptab(.('equ$'));
|
||
call emitdec16(pv(cks)/4);
|
||
call emitcomment(.('Check Vector Size$'));
|
||
end diskdef;
|
||
|
||
endef: procedure;
|
||
/* generate end of disk def code */
|
||
declare i byte;
|
||
reserve: procedure;
|
||
if z80$tog then
|
||
/* $z set for z80, 8080, or 8085 */
|
||
call emitoptab(.('ds$')); else
|
||
call emitoptab(.('rs$'));
|
||
end reserve;
|
||
call emitnulcom;
|
||
call emitbyte(';');
|
||
call emittab;
|
||
call emitchar(.('Uninitialized Scratch Memory Follows:$'));
|
||
call emitcrlf;
|
||
call emitnulcom;
|
||
|
||
/* begdat equ $ */
|
||
call emitchar(.('begdat$'));
|
||
call emitoptab(.('equ$'));
|
||
call emitdollar;
|
||
call emitcomment(.('Start of Scratch Area$'));
|
||
|
||
/* dirbuf: ds/rs 128 */
|
||
call emitchar(.('dirbuf$'));
|
||
if z80$tog then
|
||
call emitbyte(':');
|
||
call reserve;
|
||
call emitdec8(128);
|
||
call emitcomment(.('Directory Buffer$'));
|
||
|
||
/* alv0: ds als0, csv0: ds css0 */
|
||
do i = 0 to last(diskset);
|
||
if diskset(i) then
|
||
do;
|
||
call emitcharn(.('alv$'),i);
|
||
if z80$tog then
|
||
call emitbyte(':');
|
||
call reserve;
|
||
call emitcharn(.('als$'),i);
|
||
call emitcomment(.('Alloc Vector$'));
|
||
call emitcharn(.('csv$'),i);
|
||
if z80$tog then
|
||
call emitbyte(':');
|
||
call reserve;
|
||
call emitcharn(.('css$'),i);
|
||
call emitcomment(.('Check Vector$'));
|
||
end;
|
||
end;
|
||
|
||
/* enddat equ $, datsiz equ $-begdat */
|
||
call emitchar(.('enddat$'));
|
||
call emitoptab(.('equ$'));
|
||
call emitdollar;
|
||
call emitcomment(.('End of Scratch Area$'));
|
||
call emitchar(.('datsiz$'));
|
||
call emitoptab(.('equ$'));
|
||
call emitdollar;
|
||
call emitchar(.('-begdat$'));
|
||
call emitcomment(.('Size of Scratch Area$'));
|
||
call emitdbnc(0,.('Marks End of Module$'));
|
||
end endef;
|
||
|
||
program: procedure;
|
||
/* handle the entire genlib program */
|
||
declare
|
||
i byte;
|
||
do i = 0 to last(diskset);
|
||
diskset(i) = false;
|
||
end;
|
||
ndisks = 0;
|
||
do while not eofset;
|
||
errset = false;
|
||
call scan;
|
||
call emitline;
|
||
call trace(.('program$'));
|
||
if token <> cr then
|
||
if not element(.(
|
||
tmaclib,
|
||
tdisks,
|
||
tdiskdef,
|
||
tendef,
|
||
0)) then
|
||
call errptr(.('No Stmt$')); else
|
||
do;
|
||
do case eltinx;
|
||
/* maclib */
|
||
do;
|
||
call scan;
|
||
call trace(.(' maclib$'));
|
||
call scan;
|
||
call trace(.(' macpar$'));
|
||
end;
|
||
/* disks */
|
||
do;
|
||
call scan;
|
||
call trace(.(' disks$'));
|
||
call disks;
|
||
end;
|
||
/* diskdef (10 parameters) */
|
||
do;
|
||
call trace(.(' diskdef$'));
|
||
call diskdef;
|
||
end;
|
||
/* endef */
|
||
do;
|
||
call scan;
|
||
call endef;
|
||
end;
|
||
end;
|
||
if token <> cr then
|
||
call errptr(.('extra $'));
|
||
end;
|
||
call recover;
|
||
end;
|
||
end program;
|
||
|
||
plmstart: procedure public;
|
||
/* main program, called from transient interface */
|
||
call setemit; /* setup the code emitters */
|
||
call scan$ini; /* initialize the scanner */
|
||
call setup; /* set up the input file */
|
||
call program;
|
||
call writerrs;
|
||
call efinis; /* close the code file */
|
||
call boot;
|
||
end plmstart;
|
||
end;
|
||
|