-- 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.