ExpertPartList.mesa
Christophe Cuenod April 7, 1989 2:32:08 pm PDT
Reads a .partlist file and generates a .newpartlist file
DIRECTORY
Basics USING [CompareInt, Comparison],
Commander USING [CommandProc, Register],
IO USING [BreakProc, card, Close, EndOf, GetLineRope, GetTokenRope, PutF, RIS, rope, STREAM],
FS USING [StreamOpen],
List USING [Compare, CompareProc, Comparison, LORA, Merge, Sort],
Rope USING [Cat, Compare, Equal, Fetch, Length, ROPE, Substr],
SymTab USING [Create, Fetch, EachPairAction, Pairs, Ref, Store];
ExpertPartList: CEDAR PROGRAM
IMPORTS Basics, Commander, List, FS, IO, Rope, SymTab =
BEGIN
ROPE: TYPE = Rope.ROPE;
Entry: TYPE = REF EntryRep;
EntryRep: TYPE = RECORD [
refDes: ROPE,
part: ROPE
];
PartTable: TYPE = SymTab.Ref;
RefDesList: TYPE = List.LORA;
TokenProc1: IO.BreakProc ~ { -- Takes any character different from SP for the name
IF char = ' THEN RETURN [sepr];
RETURN [other];
};
Compare: List.CompareProc ~ {
comp: List.Comparison;
x1, x2, mul: INT;
r1, r2: ROPE;
len1, len2: INT;
IF ISTYPE[ref1, Entry] THEN {
entry1: Entry ← NARROW[ref1];
entry2: Entry ← NARROW[ref2];
RETURN Compare[entry1.refDes, entry2.refDes];
};
r1 ← NARROW[ref1];
r2 ← NARROW[ref2];
len1 ← Rope.Length[r1];
len2 ← Rope.Length[r2];
x1 ← 0;
mul ← 1;
WHILE len1 # 0 AND '0 <= Rope.Fetch[r1, len1-1] AND Rope.Fetch[r1, len1-1] <= '9 DO
x1 ← x1 + mul * (Rope.Fetch[r1, len1-1] - '0);
len1 ← len1 - 1;
mul ← mul * 10;
ENDLOOP;
x2 ← 0;
mul ← 1;
WHILE len2 # 0 AND '0 <= Rope.Fetch[r2, len2-1] AND Rope.Fetch[r2, len2-1] <= '9 DO
x2 ← x2 + mul * (Rope.Fetch[r2, len2-1] - '0);
len2 ← len2 - 1;
mul ← mul * 10;
ENDLOOP;
r1 ← Rope.Substr[r1, 0, len1];
r2 ← Rope.Substr[r2, 0, len2];
comp ← Rope.Compare[r1, r2, FALSE];
IF comp # equal THEN RETURN Rope.Compare[r1, r2, FALSE];
RETURN Basics.CompareInt[x1, x2];
};
IsNext: PROC [r1, r2: ROPE] RETURNS [next: BOOLFALSE] ~ {
comp: List.Comparison;
x1, x2, mul: INT;
len1: INT ← Rope.Length[r1];
len2: INT ← Rope.Length[r2];
x1 ← 0;
mul ← 1;
WHILE len1 # 0 AND '0 <= Rope.Fetch[r1, len1-1] AND Rope.Fetch[r1, len1-1] <= '9 DO
x1 ← x1 + mul * (Rope.Fetch[r1, len1-1] - '0);
len1 ← len1 - 1;
mul ← mul * 10;
ENDLOOP;
x2 ← 0;
mul ← 1;
WHILE len2 # 0 AND '0 <= Rope.Fetch[r2, len2-1] AND Rope.Fetch[r2, len2-1] <= '9 DO
x2 ← x2 + mul * (Rope.Fetch[r2, len2-1] - '0);
len2 ← len2 - 1;
mul ← mul * 10;
ENDLOOP;
r1 ← Rope.Substr[r1, 0, len1];
r2 ← Rope.Substr[r2, 0, len2];
comp ← Rope.Compare[r1, r2, FALSE];
IF comp # equal THEN RETURN;
IF (x1 + 1) = x2 THEN next ← TRUE;
};
ProcessEachLine: PROC [partTable: PartTable, line: ROPE] RETURNS [entry: Entry] ~ {
refDes, key: ROPE;
x, refDesList, newRefDesList: RefDesList;
in: IO.STREAMIO.RIS[line];
refDes ← IO.GetTokenRope[in, TokenProc1].token;
key ← IO.GetTokenRope[in, TokenProc1].token;
x ← CONS[refDes, NIL];
refDesList ← NIL;
IF SymTab.Fetch[partTable, key].found THEN {
refDesList ← NARROW[SymTab.Fetch[partTable, key].val];
};
newRefDesList ← List.Merge[x, refDesList, Compare];
[] ← SymTab.Store[partTable, key, newRefDesList];
entry ← NEW[EntryRep];
entry.refDes ← refDes;
entry.part ← key;
};
ReadPartFile: PROC [file: ROPE] RETURNS [partTable: PartTable, completeRefDesList: RefDesList] ~ {
x: RefDesList;
r: Entry;
line, spareLine: ROPE;
exit: BOOLEANFALSE;
in: IO.STREAMFS.StreamOpen[file];
partTable ← SymTab.Create[];
line ← IO.GetLineRope[in];
x ← NIL;
WHILE NOT IO.EndOf[in] AND line # NIL DO
spareLine ← IO.GetLineRope[in];
r ← ProcessEachLine[partTable, line];
x ← CONS[r, x];
line ← spareLine;
ENDLOOP;
completeRefDesList ← List.Sort[x, Compare];
};
ReadPartFile: PROC [file: ROPE] RETURNS [partTable: PartTable, completeEntryList: List.LORA] ~ {
x: List.LORA;
r: Entry;
line: ROPE;
exit: BOOLEANFALSE;
in: IO.STREAMFS.StreamOpen[file];
partTable ← SymTab.Create[];
x ← NIL;
WHILE NOT IO.EndOf[in] DO
line ← IO.GetLineRope[in];
r ← ProcessEachLine[partTable, line];
x ← CONS[r, x];
ENDLOOP;
completeEntryList ← List.Sort[x, Compare];
};
PrintEachEntry: PROC [out: IO.STREAM, entry: ROPE, refDesList:List.LORA] ~ {
i, j: CARD ← 0;
r, r1, r2, r3: ROPENIL;
FOR l: List.LORA ← refDesList, l.rest UNTIL l = NIL DO
i ← i + 1;
r3 ← NARROW[l.first];
IF IsNext[r2, r3] THEN {
r2 ← r3;
LOOP;
};
IF r1 # NIL THEN {
IF (j MOD 5) = 0 THEN r ← Rope.Cat[r, "\n\t\t"];
IF Rope.Equal[r1, r2] THEN r ← Rope.Cat[r, r1, "\t"]
ELSE IF IsNext[r1, r2] THEN r ← Rope.Cat[r, r1, "\t", r2 ,"\t"]
ELSE r ← Rope.Cat[r, r1, "-", r2 ,"\t"];
j ← j + 1;
};
r1 ← r3;
r2 ← r3;
ENDLOOP;
IF r1 # NIL THEN {
IF (j MOD 5) = 0 THEN r ← Rope.Cat[r, "\n\t\t"];
IF Rope.Equal[r1, r2] THEN r ← Rope.Cat[r, r1, "\t"]
ELSE IF IsNext[r1, r2] THEN r ← Rope.Cat[r, r1, "\t", r2 ,"\t"]
ELSE r ← Rope.Cat[r, r1, "-", r2 ,"\t"];
};
IO.PutF[out, "%g\t%g%g\n\n", IO.rope[entry], IO.card[i], IO.rope[r]];
};
ExpertPartListProc: Commander.CommandProc = BEGIN
SortEachEntry: SymTab.EachPairAction ~ {
x: List.LORACONS[key, NIL];
sortedPartList ← List.Merge[x, sortedPartList, Compare];
};
totalNumberOfParts: CARD;
partTable: PartTable;
completeEntryList: List.LORA;
sortedPartList: List.LORA;
savedRefDes1, savedRefDes2, savedPart: ROPE;
stream: IO.STREAMIO.RIS[cmd.commandLine];
name: ROPEIO.GetTokenRope[stream].token;
partlistName: ROPE ← Rope.Cat[name, ".partlist"];
newpartlistName: ROPE ← Rope.Cat[name, ".newnewpartlist"];
out: IO.STREAMFS.StreamOpen[newpartlistName, $create];
IO.PutF[cmd.out, "Reading %g\n", IO.rope[partlistName]];
[partTable, completeEntryList] ← ReadPartFile[partlistName];
IO.PutF[cmd.out, "Writing %g\n", IO.rope[newpartlistName]];
IO.PutF[out, "Partlist sorted by reference designators\n\n"];
savedPart ← NIL;
totalNumberOfParts ← 0;
FOR l: List.LORA ← completeEntryList, l.rest UNTIL l = NIL DO
entry: Entry ← NARROW[l.first];
totalNumberOfParts ← totalNumberOfParts + 1;
IF Rope.Equal[entry.part, savedPart] AND IsNext[savedRefDes2, entry.refDes] THEN {
savedRefDes2 ← entry.refDes;
}
ELSE {
IF savedPart # NIL THEN {
IF Rope.Equal[savedRefDes1, savedRefDes2] THEN {
IO.PutF[out, "%g\t\t%g\n", IO.rope[savedRefDes1], IO.rope[savedPart]];
}
ELSE {
IO.PutF[out, "%g-%g\t%g\n", IO.rope[savedRefDes1], IO.rope[savedRefDes2], IO.rope[savedPart]];
};
};
savedRefDes1 ← entry.refDes;
savedRefDes2 ← entry.refDes;
savedPart ← entry.part;
};
ENDLOOP;
IF Rope.Equal[savedRefDes1, savedRefDes2] THEN {
IO.PutF[out, "%g\t%g\n", IO.rope[savedRefDes1], IO.rope[savedPart]];
}
ELSE {
IO.PutF[out, "%g to %g\t%g\n", IO.rope[savedRefDes1], IO.rope[savedRefDes2], IO.rope[savedPart]];
};
IO.PutF[out, "\n\nPartlist sorted by part type\n\n"];
IO.PutF[cmd.out, "Total number of parts: %g\n", IO.card[totalNumberOfParts]];
sortedPartList ← NIL;
[] ← SymTab.Pairs[partTable, SortEachEntry];
totalNumberOfParts ← 0;
FOR l: List.LORA ← sortedPartList, l.rest UNTIL l = NIL DO
totalNumberOfParts ← totalNumberOfParts + 1;
PrintEachEntry[out, NARROW[l.first], NARROW[SymTab.Fetch[partTable, NARROW[l.first]].val]];
ENDLOOP;
IO.Close[out];
IO.PutF[cmd.out, "Number of different parts: %g\n", IO.card[totalNumberOfParts]];
END;
Commander.Register[
key: "ExpertPartList", proc: ExpertPartListProc, doc: "Read a .pcb and a .lib file and generates a .partlist file\n"];
END.