<> <> <> <<>> <> <> <> <> <> <<>> <> <<4 EntryNumber of the library>> <<2 ?>> <<2 X>> <<2 Y>> <<2 Orientation (MSB used to tell if placed on the drawing)>> <<11 ?>> <<1 Number of pins>> <<1 ?>> <<1 Length of the Reference designator>> <<2, 3 or 4 Reference designator>> <<>> <> <<>> <<>> <<>> <<>> DIRECTORY Basics USING [BITAND], Convert USING [RopeFromChar], FS USING [StreamOpen], IO USING [EndOf, GetByte, STREAM], Rope USING [Cat, ROPE], ExpertPCBRead, SymTab USING [Create, Insert, Ref]; ExpertPCBReadImpl: CEDAR PROGRAM IMPORTS Basics, Convert, FS, IO, Rope, SymTab EXPORTS ExpertPCBRead ~ BEGIN ROPE: TYPE = Rope.ROPE; PCBTable: TYPE = ExpertPCBRead.PCBTable; Part: TYPE = ExpertPCBRead.Part; PartRep: TYPE = ExpertPCBRead.PartRep; bufferSize: NAT = 50; BufferRep: TYPE = RECORD[ size: NAT _ bufferSize, lastentryindex: NAT, table: ARRAY[0..bufferSize) OF BYTE ]; Buffer: TYPE = REF BufferRep; <> CircularBufferPut: PROC [buffer: Buffer, i: BYTE] ~ { buffer.lastentryindex _ buffer.lastentryindex + 1; IF buffer.lastentryindex = bufferSize THEN buffer.lastentryindex _ 0; buffer.table[buffer.lastentryindex] _ i; }; CircularBufferGet: PROC [buffer: Buffer, offset: INT] RETURNS [i: BYTE] ~ { index: INT; index _ buffer.lastentryindex + offset; IF index < 0 THEN index _ index + bufferSize; IF index - bufferSize >= 0 THEN index _ index - bufferSize; i _ buffer.table[index]; }; IsChar: PROC [i: BYTE] RETURNS [yes: BOOLEAN _ FALSE] ~ { IF i IN [ORD['A]..ORD['Z]] OR i IN [ORD['a]..ORD['z]] THEN yes _ TRUE; }; IsNum: PROC [i: BYTE] RETURNS [yes: BOOLEAN _ FALSE] ~ { IF i IN [ORD['0]..ORD['9]] THEN yes _ TRUE; }; TryMatch: PROC [buffer: Buffer, pCBTable: SymTab.Ref] ~ { part: Part; orient: NAT; refDesLength: NAT; refDes: ROPE; IF NOT IsChar[CircularBufferGet[buffer, -3]] THEN RETURN; IF (NOT IsNum[CircularBufferGet[buffer, -2]]) AND (NOT IsChar[CircularBufferGet[buffer, -2]]) THEN RETURN; <> orient _ Basics.BITAND[CircularBufferGet[buffer, -19], 07FH]; -- Mask the MSB orient _ orient * 256 + CircularBufferGet[buffer, -18]; <> IF orient # 0 AND orient # 90 AND orient # 180 AND orient # 270 THEN RETURN; refDesLength _ CircularBufferGet[buffer, -4]; refDes _ Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -3]], FALSE]; refDes _ Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -2]], FALSE]]; SELECT refDesLength FROM = 3 => { refDes _ Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -1]], FALSE]]; }; = 4 => { refDes _ Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, -1]], FALSE]]; refDes _ Rope.Cat[refDes, Convert.RopeFromChar[VAL[CircularBufferGet[buffer, 0]], FALSE]]; }; ENDCASE; part _ NEW[PartRep]; part.x _ CircularBufferGet[buffer, -23]; part.x _ part.x * 256 + CircularBufferGet[buffer, -22]; part.y _ CircularBufferGet[buffer, -21]; part.y _ - (part.y * 256 + CircularBufferGet[buffer, -20]); part.orientation _ orient; part.libraryEntry _ CircularBufferGet[buffer, -27]; part.libraryEntry _ part.libraryEntry * 256 + CircularBufferGet[buffer, -26]; part.libraryEntry _ part.libraryEntry * 256 + CircularBufferGet[buffer, -29]; part.libraryEntry _ part.libraryEntry * 256 + CircularBufferGet[buffer, -28]; IF part.libraryEntry < 200 THEN RETURN; <> [] _ SymTab.Insert[pCBTable, refDes, part]; }; <> ReadPCBFile: PUBLIC PROC [file: ROPE] RETURNS [pCBTable: PCBTable] ~ { i: INT; buffer: Buffer _ NEW[BufferRep]; <<>> in: IO.STREAM _ FS.StreamOpen[file]; pCBTable _ SymTab.Create[]; WHILE NOT IO.EndOf[in] DO CircularBufferPut[buffer, IO.GetByte[in]]; i _ CircularBufferGet[buffer, -4]; <<2, 3 or 4 can be the length of a reference designator.>> IF i = 2 OR i = 3 OR i = 4 THEN TryMatch[buffer, pCBTable]; ENDLOOP; }; <<>> END.