// ResistParse.bcpl -- parse/unparse routines // Last modified by McCreight June 25, 1984 10:48 AM get "Resist.decl" get "Streams.d" external [ // outgoing procedures ReadResistFile; ReadWireListFile; UnparseIC // incoming procedures EncodeOhms; DecodeOhms LookupOrDefineSymbol; DefineSymbol; LookupSymbol; InsertSymbol SymbolsObject; ObjectsString; SymbolsString; CreateNet ReportError; ExpandTemplate FilePos; SetFilePos Ws; Wss; Gets; Puts; Endofs; PutTemplate; DefaultArgs Allocate; Free; Zero; MoveBlock // outgoing statics unknownNet // incoming statics dsp; sysZone; maxNPins ] static [ unknownNet = 0 ] manifest ecEof = 1302 manifest [ ok = 0; bad = 1; ignore = 2 ] // --------------------------------------------------------------------------- let ReadResistFile(stream, symbolTable, readingExceptions; numargs na) = valof // --------------------------------------------------------------------------- [ DefaultArgs(lv na, -2, false) let firstIC = 0 let lvNextIC = lv firstIC let locationString, tempString = vec 127, vec 127 stream>>ST.par1 = 0 let filePos = vec 1 stream>>ST.par2 = stream>>ST.error stream>>ST.error = ReadTokenError let symDIP3 = LookupOrDefineSymbol(symbolTable, "DIP3", stICPackage) let symSIP = LookupOrDefineSymbol(symbolTable, "SIP", stICPackage) if unknownNet eq 0 then unknownNet = CreateNet(symbolTable, "?") let ic = Allocate(sysZone, lenIC + maxNPins*lenPin) [ // repeat FilePos(stream, filePos) let token = ReadToken(stream, locationString) if token eq -1 then break if token eq $*n loop let result = valof [ if token ne 0 resultis bad if ReadToken(stream, tempString) ne $( resultis bad if ReadToken(stream, tempString) ne 0 resultis bad ic>>IC.package = LookupOrDefineSymbol(symbolTable, tempString, stICPackage) if ReadToken(stream, tempString) ne $, resultis bad unless ReadNumber(stream, lv ic>>IC.nPins) resultis bad if ic>>IC.nPins ls 1 % ic>>IC.nPins gr maxNPins then resultis ExpandTemplate("IC has too many pins -- only $D allowed.", maxNPins) // Ignore SIPs and bypass capacitors if ic>>IC.package eq symSIP % (ic>>IC.package eq symDIP3 & ic>>IC.nPins eq 2) resultis ignore if ReadToken(stream, tempString) ne $, resultis bad if ReadToken(stream, tempString) ne 0 resultis bad for i = 1 to tempString>>String.length do if tempString>>String.char↑i eq $/ then [ tempString>>String.length = i-1; break ] ic>>IC.type = LookupOrDefineSymbol(symbolTable, tempString, stICType) if ReadToken(stream, tempString) ne $) resultis bad for i = 1 to ic>>IC.nPins do [ let pin = lv ic>>IC.pins↑i let expectedOhms = nil if ReadToken(stream, tempString) ne 0 resultis bad unless GetNumber(tempString, lv expectedOhms) do [ if tempString>>String.length ne 1 resultis bad switchon tempString>>String.char↑1 into [ case $$: expectedOhms = open; endcase case $?: expectedOhms = unknown; endcase default: resultis bad ] ] let token = ReadToken(stream, tempString) if token eq $< then [ token = ReadToken(stream, tempString) repeatuntil token eq $> token = ReadToken(stream, tempString) ] if token ne (i eq ic>>IC.nPins? $*n, $,) resultis bad pin>>Pin.expectedOhmsCode = EncodeOhms(expectedOhms) pin>>Pin.measuredOhmsCode = unknownCode pin>>Pin.nextPin = lv unknownNet>>Net.dummyPin ] resultis ok ] switchon result into [ case ignore: until ReadToken(stream, tempString) eq $*n do loop endcase case ok: [ let icSymbol = LookupSymbol(symbolTable, locationString) test icSymbol eq 0 ifso unless readingExceptions do [ let icObject = SymbolsObject(DefineSymbol(symbolTable, locationString, stIC, ic, lenIC + ic>>IC.nPins*lenPin)) @lvNextIC = icObject lvNextIC = lv icObject>>IC.next icObject>>IC.next = 0 ] ifnot [ unless readingExceptions do [ result = ExpandTemplate("IC at $S defined multiple times.", locationString) docase bad ] let icObject = SymbolsObject(icSymbol) if ic>>IC.nPins ne icObject>>IC.nPins % ic>>IC.package ne icObject>>IC.package % ic>>IC.type ne icObject>>IC.type then [ result = ExpandTemplate("Exceptions file inconsistent with Resist file for IC at $S.", locationString) docase bad ] MoveBlock(lv icObject>>IC.pins, lv ic>>IC.pins, ic>>IC.nPins*lenPin) ] endcase ] default: Ws("*n") SetFilePos(stream, filePos) [ // repeat let char = Gets(stream) if char eq $*n % char eq -1 break Puts(dsp, char) ] repeat test result eq bad ifso ReportError("Syntax error in $S file.", (readingExceptions? "Exceptions", "Resist")) ifnot [ ReportError(result); Free(sysZone, result) ] stream>>ST.par1 = 0 endcase ] ] repeat Free(sysZone, ic) stream>>ST.error = stream>>ST.par2 resultis firstIC ] // --------------------------------------------------------------------------- and ReadWireListFile(stream, symbolTable) be // --------------------------------------------------------------------------- [ let netNameString, tempString = vec 127, vec 127 stream>>ST.par1 = 0 let filePos = vec 1 stream>>ST.par2 = stream>>ST.error stream>>ST.error = ReadTokenError let symCALIBRATE = LookupOrDefineSymbol(symbolTable, "CALIBRATE", stDummy) let symDISCONNECT = LookupOrDefineSymbol(symbolTable, "DISCONNECT", stDummy) until ReadToken(stream, tempString) eq 0 & tempString>>String.length eq 1 & tempString>>String.char↑1 eq $@ do loop [ // repeat FilePos(stream, filePos) let token = ReadToken(stream, netNameString, true) if token eq -1 then break if token eq $*n loop let result = valof [ if token ne 0 resultis bad let length = netNameString>>String.length if netNameString>>String.char↑length ne $: resultis bad netNameString>>String.length = length-1 let netSymbol = LookupSymbol(symbolTable, netNameString) if netSymbol eq symCALIBRATE % netSymbol eq symDISCONNECT then resultis ignore if netSymbol ne 0 then resultis ExpandTemplate("Multiply-defined net: $S", SymbolsString(netSymbol)) until ReadToken(stream, tempString) eq $*n do loop let net, pLastNextPin = 0, nil [ // repeat let token = ReadToken(stream, tempString) if token eq $*n then [ token = ReadToken(stream, tempString) if token eq $*n % token eq -1 resultis ok ] if token ne 0 resultis bad result = valof [ let period = 0 for i = 1 to tempString>>String.length do if tempString>>String.char↑i eq $. then period = i if period eq 0 resultis ignore let pinNumber = 0 for i = period+1 to tempString>>String.length do [ let digit = tempString>>String.char↑i - $0 if digit ls 0 % digit gr 9 then test i eq tempString>>String.length ifso break ifnot resultis ExpandTemplate("Illegal pin name: $S", tempString) pinNumber = 10*pinNumber + digit ] tempString>>String.length = period-1 let icSymbol = LookupSymbol(symbolTable, tempString) if icSymbol eq 0 resultis ignore let ic = SymbolsObject(icSymbol) if pinNumber ls 1 % pinNumber gr ic>>IC.nPins then resultis ExpandTemplate("Pin number $D illegal for IC at $S", pinNumber, SymbolsString(icSymbol)) let pin = lv ic>>IC.pins↑pinNumber if net eq 0 then [ net = CreateNet(symbolTable, netNameString) pLastNextPin = lv net>>Net.firstPin ] @pLastNextPin = pin pLastNextPin = lv pin>>Pin.nextPin pin>>Pin.nextPin = lv net>>Net.dummyPin resultis ok ] unless result eq ok % result eq ignore resultis result until ReadToken(stream, tempString) eq $} do loop ] repeat ] switchon result into [ case ok: endcase case ignore: [ // repeat let token = ReadToken(stream, tempString) if token eq $*n then if ReadToken(stream, tempString) eq $*n then endcase if token eq -1 then endcase ] repeat default: Ws("*n") SetFilePos(stream, filePos) [ // repeat let char = Gets(stream) if char eq $*n % char eq -1 break Puts(dsp, char) ] repeat test result eq bad ifso ReportError("Syntax error in Wire List file.") ifnot [ ReportError(result); Free(sysZone, result) ] stream>>ST.par1 = 0 endcase ] ] repeat stream>>ST.error = stream>>ST.par2 ] // --------------------------------------------------------------------------- and ReadToken(stream, string, dontStopOnParen; numargs na) = valof // --------------------------------------------------------------------------- // Reads the next token from the input stream. // If the token is a separator character, returns it. // If the token is an atom, copies it into string and returns zero. // If end of file has been reached, returns -1. // Separator characters are: { } < > , *n // plus ( ) if dontStopOnParen is false (the default). // Ignores comments (beginning with ;) and spaces between tokens. [ let char = stream>>ST.par1 stream>>ST.par1 = 0 let length = 0 [ // repeat switchon char into [ case $*s: if length ne 0 then [ char = 0; break ] endcase case $;: char = Gets(stream) repeatuntil char eq $*n % char eq -1 docase char case $(: case $): if na ge 3 & dontStopOnParen then docase $A // docase default case $<: case $>: case ${: case $}: case $,: case $*n: case -1: if length eq 0 break stream>>ST.par1 = char char = 0 break default: length = length+1 string>>String.char↑length = char case 0: endcase ] char = Gets(stream) ] repeat string>>String.length = length resultis char ] // --------------------------------------------------------------------------- and ReadTokenError(stream, ec) = // --------------------------------------------------------------------------- ec eq ecEof? -1, stream>>ST.par2(stream, ec) // --------------------------------------------------------------------------- and ReadNumber(stream, lvNumber, radix; numargs na) = valof // --------------------------------------------------------------------------- [ if na ls 3 then radix = 10 let tempString = vec 127 if ReadToken(stream, tempString) ne 0 resultis false resultis GetNumber(tempString, lvNumber, radix) ] // --------------------------------------------------------------------------- and GetNumber(string, lvNumber, radix; numargs na) = valof // --------------------------------------------------------------------------- // Converts string to a number and stores the result in @lvNumber. // Returns true normally, false if string wasn't a number. [ if na ls 3 then radix = 10 let number = 0 for i = 1 to string>>String.length do [ let digit = string>>String.char↑i - $0 if digit ls 0 % digit ge radix resultis false number = 10*number + digit ] @lvNumber = number resultis true ] // --------------------------------------------------------------------------- and UnparseIC(stream, ic) be // --------------------------------------------------------------------------- // Unparses ic and sends the result to stream. [ PutTemplate(stream, "$S ($S, $D, $S)", ObjectsString(ic), SymbolsString(ic>>IC.package), ic>>IC.nPins, SymbolsString(ic>>IC.type)) for i = 1 to ic>>IC.nPins do [ Wss(stream, (i eq 1? " ", ", ")) let pin = lv ic>>IC.pins↑i switchon pin>>Pin.expectedOhmsCode into [ case openCode: Puts(stream, $$); endcase case unknownCode: Puts(stream, $?); endcase default: PutTemplate(stream, "$D", DecodeOhms(pin>>Pin.expectedOhmsCode)); endcase ] ] Puts(stream, $*n) ]