//and.bcpl
//new analyzer for sil files

get "sysdefs.d"
get "altofilesys.d"
get "ana.defs"



//R E A D C O M P O N E N T D I C T I O N A R Y

let GetCompNames(dictcnt,fname) =valof
[
let newfpDict = Dprvec + dictcnt*(lCFA+1)+1
if newfpDict!-1 eq -1 then resultis dictcnt //file not present
test newfpDict eq fpDict
ifso Resets(dict)
ifnot
[
if dict ne 0 then Closes(dict)
fpDict = newfpDict
dict = OpenFile(fname,ksTypeReadOnly,1,0,fpDict,0,SilZone)
if dict eq 0 then test dictcnt eq 0
ifso [ CallSwat("Can’t open first Dictionary:",fname); resultis 0 ]
ifnot
[
Err2("*nCouldn’t open Dictionary file ",fname,noError)
fpDict!-1 = -1//mark so we won’t try again
resultis dictcnt
]
]

let pname = vec 32;let rname = vec 32 //print names and real names
let compcnt = 0
while ReadHdr(pname,rname,dict) do //unusual termination on @ or eof
[
if StEq("get",pname) then // get a new dictionary
[
if dictcnt eq 8 then
[ Err2("*nTo many Dictionary files, skipped ",rname,noError); loop ]
GetCompleteFa(dict,fpDict) //save current file position
dictcnt = GetCompNames(dictcnt+1,rname)
if dict ne 0 then Closes(dict) //dict eq 0 if new dict is not present
fpDict = newfpDict //now restore file position and proceed
dict = OpenFile(0,ksTypeReadOnly,1,0,fpDict,0,SilZone)
JumpToFa(dict,lv fpDict>>CFA.fa)
loop
]
let pstp=Lookup(pname)
if pstp eq 0 then loop //this component not used
//change the type field in the symbol table to type stComp
compcnt = compcnt+1
pstp>>strec.type = stComp
let rstp = Lookup(rname) //component’s real name
test rstp eq 0
ifnot
[
let type = rstp>>strec.type
if (type ne stComp) & (type ne stRcomp) then
Err2("*nComponent real name conflicts with other symbol type: ",rname) //this is not fatal
]

ifso rstp = DefineSymbol(rname,stRcomp)
pstp>>strec.rname = rstp
]
GetCompleteFa(dict,fpDict) //this saves a file pointer to the first "@" in the file
fpDict!-1 = compcnt //if 0 then this dict is not used
resultis dictcnt
]


and ReadHdr(s1,s2,stream) = valof
[
if Endofs(stream) then resultis false
s1!0 = 0; s2!0 = 0
let tc1 = ReadName(s1,stream)
if (tc1 ne $=) & (tc1 ne $←) then
[
if tc1 eq $@ then resultis false
if (tc1 eq $;) % (tc1 eq $|) do [ FlushLine(stream); loop ] //comment line

if tc1 eq $*n then loop //blank line

//some type of error
AppendC(tc1,s1)
until Endofs(stream)%(tc1 eq $*n) do
[
tc1 = Gets(stream)
AppendC(tc1,s1)
]

Err2("*NStrange entry in dictionary header: ",s1)
loop //throw away this line and go on to the next
]

//got print name, get real name now
let tc2 = ReadName(s2,stream)
switchon tc2 into
[
case $;: //line ends in a comment
FlushLine(stream)
resultis true

case $>:
//pseudo carrage return
case $*n: resultis true

default: //some funny
[
AppendC(tc1,s1)
AppendS(s2,s1)
AppendC(tc2,s1)
until Endofs(stream)%(tc2 eq $*n) do
[
tc2 = Gets(stream)
AppendC(tc2,s1)
]

Err2("*nStrange entry in dictionary header: ",s1)
loop //discard funny line
]
]
] repeat



and ReadName(string,stream) = valof
[
let c = Gets(stream)
if c eq #32 then c = $; //↑Z: convert Bravo format into a comment
if (c eq $*n)%(c eq $=)%(c eq $@)%(c eq $;)%(c eq $|)%(c eq $>) then resultis c
if c le $*s then loop //control character
AppendC(c,string)
if string>>str.length gr 60 do CallSwat("Name in Dict to long:",string)
] repeat