-- a program to run within Chipmonk

-- last modified by Petit, October 13, 1981 8:00 PM
-- written by Petit, October 9, 1981 2:04 PM

DIRECTORY
ppddefs,
ppdefs,
rldefs,
AltoFileDefs,
ZoneAllocDefs,
StreamDefs,
DirectoryDefs,
StringDefs;

rlin: PROGRAM
IMPORTS ppdefs, StreamDefs, DirectoryDefs, rldefs, StringDefs
EXPORTS rldefs =
BEGIN OPEN ppddefs, rldefs, StreamDefs, DirectoryDefs, ppdefs, StringDefs;


fHandle:DiskHandle;
fp:AltoFileDefs.FP;

myZone: PUBLIC UNCOUNTED ZONE;

fileErr:PUBLIC SIGNAL=CODE;
abbrt:PUBLIC SIGNAL=CODE;


-- NEW FILE FORMAT:

-- each gate is represented by one line of text, thus:
-- <output Node Name> ( <#> ) : <input Spec> <sep> <input Spec> ... <CR>
-- Where <input Spec> is either <Node Name> for a single nor input
-- or [ <Node Name> <sep> <Node Name> ... ] for an AND nor input
-- <sep> is either space or comma.
-- Node Names are identifiers (strings of <Digit> and/or <Letter>)
-- The "( <#> )" following the <output Node Name> is the
-- parameter (pullup strength) index. It is optional, and if
-- it is left out the current default will be used.
-- A line consisting of only: (<#>)<CR> will set the default.
-- N.B.: identifiers are limited to 100 Characters!
-- file ends with a line consisting of @

-- <CR> and ; are equivalent. Comma and space are equivalent.
-- a line starting with (first non-blank chr) a minus (-) is ignored.


itemType:TYPE = {ident,num,sep,lend,colon,lpar,rpar,lbrk,rbrk,fend,commt};
pinType:TYPE = {out,nor,firstAnd,and};
pinDef:TYPE = RECORD[nxt:LONG POINTER TO pinDef,node:INTEGER,type:pinType];

nodeNameList:TYPE = RECORD[nxt:LONG POINTER TO nodeNameList,
node:INTEGER,name:STRING];

termChar:CHARACTER;
dummytc:CHARACTER = 177C;
pins,pnp:LONG POINTER TO pinDef;
savePD:LONG POINTER TO pinDef←NIL;
nnList:LONG POINTER TO nodeNameList;

inputCircuit:PUBLIC PROCEDURE
RETURNS[pnt:LONG POINTER TO GateList,dwCnt,maxNN:INTEGER] =
BEGIN
s:STRING;
ok:BOOLEAN;
typ:itemType;
gc:LONG POINTER TO gateCharac;
gat:LONG POINTER TO gate;
gp,mostRecent:LONG POINTER TO GateList;
norCnt,inCnt,i,a,parm:INTEGER;
defparm:INTEGER←1;--default
[ok,s,]←typeIn["Type File Name"L,"With Extension"L,""L];
IF NOT ok THEN SIGNAL abbrt;
ok←openF[s];
pnt←NIL;
pins←NIL;
dwCnt←maxNN←0;
nnList←NIL;
WHILE NOT ok DO
[ok,s,]←typeIn["No Such File"L,"Type File Name"L,
"With Extension"L];
IF NOT ok THEN SIGNAL abbrt;
ok←openF[s];
ENDLOOP;

termChar←dummytc;
DO
[typ,s,a]←scan[];
IF typ=fend THEN EXIT;
IF typ=commt THEN UNTIL typ=lend DO [typ,,]←scan[];ENDLOOP;
IF typ=lend THEN LOOP;
IF typ=lpar THEN
BEGIN
defparm←readNum[];
checkForChr[’)];
[typ,,]←scan[];
IF typ#lend THEN SIGNAL fileErr;
END
ELSE IF typ#ident THEN SIGNAL fileErr
ELSE
BEGIN
parm←defparm;
enterPin[out,s];
[typ,,]←scan[];
IF typ=lpar THEN
BEGIN
parm←readNum[];
checkForChr[’)];
[typ,,]←scan[];
END;
IF typ#colon THEN SIGNAL fileErr;
IF NOT parm IN parmaCnt THEN SIGNAL fileErr;
norCnt←0;
DO
[typ,s,a]←scan[];
IF typ=lbrk THEN
BEGIN
[typ,s,a]←scan[];
IF typ#ident THEN SIGNAL fileErr;
enterPin[firstAnd,s];
norCnt←norCnt+1;
DO
[typ,s,a]←scan[];
IF typ=rbrk THEN EXIT;
IF typ#ident THEN SIGNAL fileErr;
enterPin[and,s];
ENDLOOP;
LOOP;
END;
IF typ=lend THEN EXIT;
IF typ#ident THEN SIGNAL fileErr;
norCnt←norCnt+1;
enterPin[nor,s];
ENDLOOP;
gc←GetSpace[SIZE[gateCharac[norCnt]]];
gc.norCnt←norCnt;
inCnt←i←0;
pnp←pins;
WHILE pnp#NIL DO
SELECT pnp.type FROM
out => {pnp←pnp.nxt;LOOP};
nor => {inCnt←inCnt+1;gc.ands[i]←1;i←i+1;pnp←pnp.nxt};
firstAnd => BEGIN
a←1;
inCnt←inCnt+1;
pnp←pnp.nxt;
WHILE pnp#NIL AND pnp.type=and DO
a←a+1;
inCnt←inCnt+1;
pnp←pnp.nxt;
ENDLOOP;
gc.ands[i]←a;
i←i+1;
END;
ENDCASE;
ENDLOOP;
gc.inCnt←inCnt;
gat←getGate[gc,parm];
gp←getNewGateList[inCnt];
i←0;
pnp←pins;
a←pnp.node;
maxNN←MAX[maxNN,a];
gp.outNode←a;
pnp←pnp.nxt;
WHILE pnp#NIL DO
a←pnp.node;
gp.nodes[i]←a;
maxNN←MAX[maxNN,a];
i←i+1;
pnp←pnp.nxt;
ENDLOOP;
dwCnt←dwCnt+inCnt+1;
gp.gat←gat;
gp.nxt←NIL;
IF pnt=NIL THEN pnt←gp ELSE mostRecent.nxt←gp;
mostRecent←gp;
freeupPins[];
END;
ENDLOOP;
END;
checkForChr:PROCEDURE[c:CHARACTER] =
BEGIN
chr:CHARACTER;
WHILE (chr←readChr[]) = ’ OR chr=’, OR chr=11C DO ENDLOOP;
IF chr#c THEN SIGNAL fileErr;
END;
openF:PROCEDURE [fname: STRING]
RETURNS [BOOLEAN] =
BEGIN
IF NOT DirectoryLookup[@fp, fname, FALSE] THEN RETURN[FALSE];
fHandle ← NewByteStream[fname, Read];
RETURN[TRUE];
END;
readChr:PROCEDURE RETURNS[CHARACTER] =
BEGIN
c:CHARACTER←termChar;
termChar←dummytc;
IF c#dummytc THEN RETURN[c];
IF NOT fHandle.endof[fHandle] THEN RETURN[fHandle.get[fHandle]];
RETURN[15C];
END;
readNum:PROCEDURE RETURNS[i:INTEGER] =
BEGIN
c:CHARACTER;
i←0;
WHILE (c←readChr[]) = ’ OR c=’, OR c=11C DO ENDLOOP;
WHILE c IN [’0..’9] DO
i←i*10+(c-’0);
c←readChr[];
ENDLOOP;
termChar←c;
END;
scan:PROCEDURE RETURNS[t:itemType,s:STRING,i:INTEGER] =
BEGIN
c:CHARACTER;
ss:STRING←[100];
i←0;
s←NIL;
WHILE (c←readChr[]) = ’ OR c=’, OR c=11C DO ENDLOOP;
t←num;
IF NOT (c IN [’0..’9] OR c IN [’a..’z] OR c IN [’A..’Z]) THEN
BEGIN
SELECT c FROM
’,,’ => t←sep;
’: => t←colon;
15C,’; => t←lend;
’( => t←lpar;
’[ => t←lbrk;
’] => t←rbrk;
’) => t←rpar;
’@ => t←fend;
’- => t←commt;
ENDCASE => SIGNAL fileErr;
RETURN;
END;
WHILE c IN [’0..’9] OR c IN [’a..’z] OR c IN [’A..’Z] DO
IF t=num THEN
BEGIN
IF c IN [’0..’9] THEN i←i*10+(c-’0)
ELSE t←ident;
END;
AppendChar[ss,c];
c←readChr[];
ENDLOOP;
s←newString[ss];
termChar←c;
END;
getNewGateList:PROCEDURE[cnt:INTEGER] RETURNS[LONG POINTER TO GateList] =
BEGIN
RETURN[myZone.NEW[GateList[cnt]]];
END;

enterPin:PROCEDURE[typ:pinType,s:STRING] =
BEGIN
p:LONG POINTER TO pinDef;
pp:LONG POINTER TO pinDef←getPinDef[];
pp↑←[NIL,enterNodeName[s],typ];
IF pins=NIL THEN pins←pp
ELSE
BEGIN
p←pins;
WHILE p.nxt#NIL DO p←p.nxt;ENDLOOP;
p.nxt←pp;
END;
END;
getPinDef:PROCEDURE RETURNS[p:LONG POINTER TO pinDef] =
BEGIN
IF savePD=NIL THEN RETURN[myZone.NEW[pinDef]];
p←savePD;
savePD←p.nxt;
END;
freeupPins:PROCEDURE =
BEGIN
IF savePD=NIL THEN {savePD←pins;pins←NIL;RETURN};
pnp←savePD;
WHILE pnp.nxt#NIL DO pnp←pnp.nxt;ENDLOOP;
pnp.nxt←pins;
pins←NIL;
END;
enterNodeName:PROCEDURE[s:STRING] RETURNS[INTEGER] =
BEGIN
n:INTEGER←0;
nn:LONG POINTER TO nodeNameList←nnList;
WHILE nn#NIL DO
IF EquivalentString[s,nn.name] THEN RETURN[nn.node];
n←MAX[n,nn.node];
nn←nn.nxt;
ENDLOOP;
n←n+1;
nn←myZone.NEW[nodeNameList];
nn.name←s;
nn.node←n;
nn.nxt←nnList;
nnList←nn;
RETURN[n];
END;



END. -- of rlin