DIRECTORY
Basics USING [BITAND, Int16FromH],
FS USING [StreamOpen],
IntHashTable USING [Create, Fetch, Insert, Table],
IO USING [EndOf, GetByte, GetHWord, GetRope, STREAM],
Rope USING [Cat, FromChar, ROPE],
ExpertLibRead;
~
BEGIN
ROPE: TYPE = Rope.ROPE;
PinPos: TYPE = ExpertLibRead.PinPos;
PartPinInfo: TYPE = ExpertLibRead.PartPinInfo;
LibTable: TYPE = ExpertLibRead.LibTable;
LibEntry: TYPE = ExpertLibRead.LibEntry;
LibEntryRep: TYPE = ExpertLibRead.LibEntryRep;
bufferSize: NAT = 20;
BufferRep: TYPE = RECORD[
size: NAT ← bufferSize,
lastentryindex: NAT,
table: ARRAY[0..bufferSize) OF BYTE
];
Buffer: TYPE = REF BufferRep;
Private procedures
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];
};
Skip:
PROC [in:
IO.
STREAM, number:
CARD] ~ {
WHILE number # 0
DO
[] ← IO.GetByte[in];
number ← number - 1;
ENDLOOP;
};
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;
};
IsAscii:
PROC [i:
BYTE]
RETURNS [yes:
BOOLEAN ←
FALSE] ~ {
IF i IN [020H..07FH] THEN yes ← TRUE;
};
GetFullPinsPosition:
PROC [in:
IO.
STREAM]
RETURNS [libEntry: LibEntry] ~ {
numberOfPins: NAT;
numberOfPins ← IO.GetByte[in];
Skip[in, 7]; -- Align with first pin entry
libEntry ← NEW[LibEntryRep[numberOfPins]];
FOR i:
NAT
IN [0..numberOfPins)
DO
libEntry.partPinInfo[i].pinPos.x ← Basics.Int16FromH[IO.GetHWord[in]];
libEntry.partPinInfo[i].pinPos.y ← - Basics.Int16FromH[IO.GetHWord[in]];
Skip[in, 1];
libEntry.partPinInfo[i].diameter ← IO.GetByte[in];
FillRemainingOfPartPinInfo[libEntry, i, in];
ENDLOOP;
};
GetAbreviatedPinsPosition:
PROC [in:
IO.
STREAM]
RETURNS [libEntry: LibEntry] ~ {
numberOfPins, diameter: NAT;
deltax, deltay: CARD;
numberOfPins ← IO.GetByte[in];
Skip[in, 11]; -- Align with deltas
deltay ← Basics.Int16FromH[IO.GetHWord[in]]; -- Find delta y
deltax ← Basics.Int16FromH[IO.GetHWord[in]]; -- Find delta x
Skip[in, 1];
diameter ← IO.GetByte[in];
libEntry ← NEW[LibEntryRep[numberOfPins]];
IF (numberOfPins MOD 2) # 0 THEN ERROR;
FOR i:
NAT
IN [0..numberOfPins/2)
DO
libEntry.partPinInfo[i].pinPos.x ← 0;
libEntry.partPinInfo[i].pinPos.y ← -(deltay * i);
libEntry.partPinInfo[i].diameter ← diameter;
FillRemainingOfPartPinInfo[libEntry, i, in];
ENDLOOP;
FOR i:
NAT
IN [numberOfPins/2..numberOfPins)
DO
libEntry.partPinInfo[i].pinPos.x ← deltax;
libEntry.partPinInfo[i].pinPos.y ← deltay * (1+i-numberOfPins);
libEntry.partPinInfo[i].diameter ← diameter;
FillRemainingOfPartPinInfo[libEntry, i, in];
ENDLOOP;
};
FillRemainingOfPartPinInfo:
PROC [libEntry: LibEntry, pin: NAT, in:
IO.
STREAM] ~ {
temp, pinNameLength: NAT;
libEntry.partPinInfo[pin].site ← IO.GetByte[in] + 1;
libEntry.partPinInfo[pin].padStack ← IO.GetByte[in];
libEntry.partPinInfo[pin].swap ← IO.GetByte[in];
temp ← IO.GetByte[in];
libEntry.partPinInfo[pin].type ← temp/16;
pinNameLength ← Basics.BITAND[temp, 00FH]; --Low digit is significant
IF pinNameLength = 0 THEN pinNameLength ← 16;
libEntry.partPinInfo[pin].name ← IO.GetRope[in, pinNameLength];
};
TryMatch:
PROC [buffer: Buffer, libTable: IntHashTable.Table, in:
IO.
STREAM] ~ {
c: BYTE;
partName: ROPE ← NIL;
partNumberLength: CARD;
pinNumberingType: INT;
libEntry: LibEntry;
entryLength, entryNumber: CARD;
nameLength: BYTE ← CircularBufferGet[buffer, 0];
entryLength ← CircularBufferGet[buffer, -5];
entryLength ← entryLength * 256 + CircularBufferGet[buffer, -4];
IF entryLength < 20 THEN RETURN; -- Impossible to have a so short entry
entryNumber ← CircularBufferGet[buffer, -7];
entryNumber ← entryNumber * 256 + CircularBufferGet[buffer, -6];
entryNumber ← entryNumber * 256 + CircularBufferGet[buffer, -9];
entryNumber ← entryNumber * 256 + CircularBufferGet[buffer, -8];
IF nameLength = 0 THEN RETURN;
WHILE nameLength # 0
DO
c ← IO.GetByte[in];
IF NOT IsAscii[c] THEN RETURN;
partName ← Rope.Cat[partName, Rope.FromChar[LOOPHOLE[c]]];
nameLength ← nameLength-1;
ENDLOOP;
pinNumberingType ← Basics.Int16FromH[IO.GetHWord[in]];
Skip[in, 38]; -- Align with pin number
SELECT pinNumberingType
FROM
= 0 => {
-- Implied position of the pins
libEntry ← GetAbreviatedPinsPosition[in];
};
= 1 => {
-- Full x and y position for each pin
libEntry ← GetFullPinsPosition[in];
};
ENDCASE => RETURN;
Skip[in, 1]; -- Align with "Part number"
partNumberLength ← IO.GetByte[in];
libEntry.partNumber ← IO.GetRope[in, partNumberLength];
libEntry.partName ← partName;
[] ← IntHashTable.Insert[libTable, entryNumber, libEntry];
};
Public Procedures
ReadLibFile:
PUBLIC
PROC [file: Rope.
ROPE]
RETURNS [libTable: LibTable] ~ {
Creates libTable from the input file
buffer: Buffer ← NEW[BufferRep];
in: IO.STREAM ← FS.StreamOpen[file];
libTable ← IntHashTable.Create[];
WHILE
NOT
IO.EndOf[in]
DO
CircularBufferPut[buffer, IO.GetByte[in]];
A caracteristic pattern of a part is 00 07 00 followed by the lenght of the name (#0)
IF CircularBufferGet[buffer, -2] = 7 AND
CircularBufferGet[buffer, -3] = 0 AND
CircularBufferGet[buffer, -1] = 0 AND
CircularBufferGet[buffer, 0] # 0 THEN TryMatch[buffer, libTable, in];
ENDLOOP;
};
PartName:
PUBLIC
PROC [libTable: LibTable, entryNumber:
CARD]
RETURNS [partName: Rope.
ROPE] ~{
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
partName ← libEntry.partName;
};
PartNumber:
PUBLIC
PROC [libTable: LibTable, entryNumber:
CARD]
RETURNS [partNumber: Rope.
ROPE] ~{
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
partNumber ← libEntry.partNumber;
};
PinNumber:
PUBLIC
PROC [libTable: LibTable, entryNumber:
CARD]
RETURNS [pinNumber:
NAT] ~{
gives the number of pins of an entry
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
pinNumber ← libEntry.size;
};
RelativePinPosition:
PUBLIC
PROC [libTable: LibTable, entryNumber:
CARD, pin:
NAT]
RETURNS [pinPos: PinPos] ~{
gives the relative position of any pin for an unrotated entry
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
pinPos ← libEntry.partPinInfo[pin-1].pinPos;
};
FirstPinOfThisType:
PUBLIC
PROC [libTable: LibTable, entryNumber:
CARD, type:
NAT, swap:
NAT]
RETURNS [pinNumber:
NAT ← 0] ~{
index: NAT ← 0;
libEntry: LibEntry;
libEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
WHILE index < libEntry.size
DO
IF libEntry.partPinInfo[index].type = type
AND libEntry.partPinInfo[index].swap = swap
THEN {
pinNumber ← index + 1;
EXIT;
};
index ← index + 1;
ENDLOOP;
};
IsPinOfThisType:
PUBLIC
PROC [libTable: LibTable, entryNumber:
CARD, pinNumber:
CARD, type:
NAT, swap:
NAT]
RETURNS [yes:
BOOLEAN ←
FALSE] ~{
libEntry: LibEntry ← NARROW[IntHashTable.Fetch[libTable, entryNumber].value];
IF libEntry.partPinInfo[pinNumber - 1].type = type
AND libEntry.partPinInfo[pinNumber - 1].swap = swap THEN yes ← TRUE;
};
END.