-- CorrectMwWl.mesa -- Last modified November 2, 1979 5:08 PM by Taft DIRECTORY ImageDefs: FROM "ImageDefs" USING [StopMesa], IODefs: FROM "IODefs", MiscDefs: FROM "MiscDefs" USING [CommandLineCFA], SegmentDefs: FROM "SegmentDefs", StreamDefs: FROM "StreamDefs", StringDefs: FROM "StringDefs"; CorrectMwWl: PROGRAM IMPORTS ImageDefs, IODefs, MiscDefs, SegmentDefs, StreamDefs, StringDefs = BEGIN OPEN IODefs, StreamDefs, StringDefs; Coordinate: TYPE = CARDINAL; -- 25-mil units gridUnit: Coordinate = 2; -- 50-mil grid inStream, outStream: StreamHandle; AdjustCoordinates: PROCEDURE [x, y: Coordinate] RETURNS [xNew, yNew: Coordinate, changed: BOOLEAN] = BEGIN -- Note that x is rounded up but y is rounded down!! xNew ← (x + gridUnit/2) - (x + gridUnit/2) MOD gridUnit; yNew ← (y + gridUnit/2 -1) - (y + gridUnit/2 -1) MOD gridUnit; changed ← xNew#x OR yNew#y; END; currentChar: CHARACTER ← NUL; ReadToken: PROCEDURE [s: STRING, copy: BOOLEAN] RETURNS [c: CHARACTER] = -- If the next token is a separator character, returns it. -- If it is an atom, copies it into s and returns NUL. -- Lets through the signal StreamError[inStream, StreamAccess] after -- the last token has been returned. -- Copies all characters to outStream iff copy is TRUE. BEGIN s.length ← 0; DO SELECT currentChar FROM NUL => NULL; SP => IF s.length#0 THEN RETURN [NUL] ELSE IF copy THEN outStream.put[outStream, currentChar]; '; => BEGIN IF copy THEN outStream.put[outStream, currentChar]; UNTIL currentChar=CR DO currentChar ← inStream.get[inStream ! StreamError => IF error=StreamAccess THEN BEGIN currentChar ← CR; CONTINUE END]; IF copy AND currentChar#CR THEN outStream.put[outStream, currentChar]; ENDLOOP; LOOP; END; '<, '>, '{, '}, ',, CR => BEGIN IF s.length=0 THEN BEGIN IF copy THEN outStream.put[outStream, currentChar]; c ← currentChar; currentChar ← NUL; END ELSE c ← NUL; RETURN; END; ENDCASE => BEGIN IF copy THEN outStream.put[outStream, currentChar]; AppendChar[s, currentChar]; END; currentChar ← inStream.get[inStream ! StreamError => IF error=StreamAccess AND s.length#0 THEN BEGIN currentChar ← CR; CONTINUE END]; ENDLOOP; END; ReportChangedCoordinates: PROCEDURE [ netName, pinName: STRING, x, y, xNew, yNew: Coordinate] = BEGIN WriteCoordinates: PROCEDURE [x, y: Coordinate] = BEGIN WriteChar['{]; WriteNumber[x, [10, FALSE, FALSE, 3]]; WriteChar[',]; WriteNumber[y, [10, FALSE, FALSE, 3]]; WriteChar['}]; END; WriteString[netName]; WriteChar[':]; THROUGH [netName.length..20] DO WriteChar[' ] ENDLOOP; WriteString[pinName]; THROUGH [pinName.length..10] DO WriteChar[' ] ENDLOOP; WriteCoordinates[x, y]; WriteString[" => "L]; WriteCoordinates[xNew, yNew]; WriteChar[CR]; END; MalformedWireList: SIGNAL = CODE; CorrectWireList: PROCEDURE = BEGIN ENABLE StreamError => IF error=StreamAccess THEN GOTO Done; netName: STRING = [100]; pinName: STRING = [100]; tempName: STRING = [100]; token: CHARACTER; x, y, xNew, yNew: Coordinate; changed: BOOLEAN; UNTIL ReadToken[tempName, TRUE]=NUL AND EqualString[tempName, "@"L] DO NULL ENDLOOP; DO token ← ReadToken[netName, TRUE]; IF token=CR THEN LOOP; IF token#NUL THEN SIGNAL MalformedWireList; IF netName[netName.length-1]#': THEN SIGNAL MalformedWireList; netName.length ← netName.length-1; UNTIL ReadToken[tempName, TRUE]=CR DO NULL ENDLOOP; DO token ← ReadToken[pinName, TRUE]; IF token=CR THEN BEGIN token ← ReadToken[pinName, TRUE]; IF token=CR THEN EXIT END; IF token#NUL THEN SIGNAL MalformedWireList; UNTIL ReadToken[tempName, TRUE]='{ DO NULL ENDLOOP; IF ReadToken[tempName, FALSE]#NUL THEN SIGNAL MalformedWireList; x ← StringToDecimal[tempName]; IF ReadToken[tempName, FALSE]#', THEN SIGNAL MalformedWireList; IF ReadToken[tempName, FALSE]#NUL THEN SIGNAL MalformedWireList; y ← StringToDecimal[tempName]; [xNew, yNew, changed] ← AdjustCoordinates[x, y]; IF changed THEN ReportChangedCoordinates[netName, pinName, x, y, xNew, yNew]; OutNumber[outStream, xNew, [10, FALSE, FALSE, 0]]; outStream.put[outStream, ',]; OutNumber[outStream, yNew, [10, FALSE, FALSE, 0]]; IF ReadToken[tempName, TRUE]#'} THEN SIGNAL MalformedWireList; ENDLOOP; ENDLOOP; EXITS Done => NULL; END; comStream: StreamHandle; BeginCommandScan: PROCEDURE = BEGIN comStream ← NewByteStream["Com.cm"L, Read]; JumpToFA[comStream, @MiscDefs.CommandLineCFA[].fa]; END; EndCommandScan: PROCEDURE = BEGIN GetFA[comStream, @MiscDefs.CommandLineCFA[].fa]; comStream.destroy[comStream]; END; GetCommandAtom: PROCEDURE [s, prompt: STRING] = BEGIN ENABLE StreamError => IF error=StreamAccess THEN BEGIN ENABLE Rubout => RETRY; WriteChar[CR]; WriteString[prompt]; ReadID[s]; GOTO Done; END; c: CHARACTER; s.length ← 0; DO c ← comStream.get[comStream]; SELECT c FROM SP, TAB => IF s.length#0 THEN EXIT; CR => EXIT; ENDCASE => AppendChar[s, c]; ENDLOOP; EXITS Done => NULL; END; ParseCommandLine: PROCEDURE = BEGIN inName: STRING = [50]; outName: STRING = [50]; i: CARDINAL; BeginCommandScan[]; BEGIN ENABLE SegmentDefs.FileNameError => RETRY; GetCommandAtom[inName, "Input wire list file: "L]; inStream ← NewByteStream[inName, Read]; END; EndCommandScan[]; FOR i DECREASING IN [0..inName.length) DO IF inName[i]='. THEN BEGIN inName.length ← i; EXIT END; ENDLOOP; AppendString[outName, inName]; AppendString[outName, ".cwl"L]; outStream ← NewByteStream[outName, Write+Append]; outName.length ← 0; AppendString[outName, inName]; AppendString[outName, ".log"L]; logStream ← NewByteStream[outName, Write+Append]; splitStream.put ← SplitPut; END; logStream, displayStream: StreamHandle; splitStreamObject: Other StreamObject; splitStream: POINTER TO Other StreamObject = @splitStreamObject; SplitPut: PROCEDURE [stream: StreamHandle, c: CHARACTER] = BEGIN logStream.put[logStream, c]; displayStream.put[displayStream, c]; END; -- Main body. ParseCommandLine[]; displayStream ← GetOutputStream[]; SetOutputStream[splitStream]; CorrectWireList[]; SetOutputStream[displayStream]; inStream.destroy[inStream]; outStream.destroy[outStream]; logStream.destroy[logStream]; ImageDefs.StopMesa[]; END.