File: NewPart.mesa
Christophe Cuenod March 20, 1987 3:45:02 pm PST
DIRECTORY
Commander USING [CommandProc, Register],
Rope USING [ROPE, Length, Fetch, Equal],
FS USING [StreamOpen],
IO USING [ GetChar, PutChar, PutRope, EndOf, EndOfStream, GetInt, STREAM, RIS, GetTokenRope, TokenProc, BreakProc, Close];
The part file is a text file containing exactly:
entry number    new part
entry number   shape assossiated
xmin    part outline
ymin    part outline
xmax    part outline
ymax     part outline
xprefix yprefix    location of the prefix
part name
part number    (inventory number)
prefi
    and for each pin:
x
y
name
swap
dia
site
type
pad  
NewPart: CEDAR PROGRAM
IMPORTS IO, Commander, Rope, FS =
BEGIN
ROPE: TYPE = Rope.ROPE;
offset: CARD = 186; -- Experimental constant. Everything is relatif to this offset.
tablelocation: CARD = 256*2; --Experimental constant. First table location.
tablelength: CARD = 256*3; --Experimental constant. Length of the table.
Lib: TYPE = REF LibRep;
LibarrayRep: TYPE = ARRAY[0..15000] OF BYTE;
LibRep: TYPE = RECORD [
lib: REF LibarrayRep,
length: CARD,
tablelocation: CARD,
tablelength: CARD,
offset: CARD
];
Pininfo: TYPE = REF PininfoRep;
PininfoRep: TYPE = ARRAY[0..255] OF RECORD [
xpos: INT,
ypos: INT,
name: ROPE,
swap: CARD,
dia: CARD,
site: CARD,
type: CARD,
pad: CARD
];
Partinfo: TYPE = REF PartinfoRep;
PartinfoRep: TYPE = RECORD [
entrynumber: CARD,
shapenumber: CARD,
xmin: INT,
ymin: INT,
xmax: INT,
ymax: INT,
xprefix: INT,
yprefix: INT,
pinnumber: CARD,
name: ROPE,
number: ROPE,
prefix: ROPE
];
Parthandle: TYPE = REF ParthandleRep;
ParthandleRep: TYPE = RECORD [
partinfo: Partinfo,
pininfo: Pininfo
];
GetRope: PROC [stream: IO.STREAM, breakProc: IO.BreakProc ← TokenBreak] RETURNS [r:ROPE] = {
r ← IO.GetTokenRope[stream, breakProc ! IO.EndOfStream => CONTINUE].token;
};
TokenBreak: IO.BreakProc ~ {
IF char = ' OR char = '\t OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
CmdTokenBreak: IO.BreakProc = {
IF char = '← THEN RETURN [break];
IF char = ' OR char = '\t OR char = ', OR char = '; OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
ReadInitialLib: PROC [initiallibfile: ROPE] RETURNS [lib: Lib] = {
in: IO.STREAMFS.StreamOpen[initiallibfile];
index: CARD ← 0;
lib ← NEW [LibRep];
lib.lib ← NEW[LibarrayRep];
WHILE NOT IO.EndOf[in] DO
lib.lib[index] ← ORD[CHAR[IO.GetChar[in]]];
index ← index + 1;
ENDLOOP;
lib.length ← index;
};
ReadPartFile: PROC [initialpartfile: ROPE] RETURNS [parthandle: Parthandle] = {
pinindex: CARD ← 0;
in: IO.STREAMFS.StreamOpen[initialpartfile];
parthandle ← NEW[ParthandleRep];
parthandle.partinfo ← NEW[PartinfoRep];
parthandle.pininfo ← NEW[PininfoRep];
parthandle.partinfo.entrynumber ← IO.GetInt[in];
parthandle.partinfo.shapenumber ← IO.GetInt[in];
parthandle.partinfo.xmin ← IO.GetInt[in];
parthandle.partinfo.ymin ← IO.GetInt[in];
parthandle.partinfo.xmax ← IO.GetInt[in];
parthandle.partinfo.ymax ← IO.GetInt[in];
parthandle.partinfo.xprefix ← IO.GetInt[in];
parthandle.partinfo.yprefix ← IO.GetInt[in];
parthandle.partinfo.name ← GetRope[in];
parthandle.partinfo.number ← GetRope[in];
parthandle.partinfo.prefix ← GetRope[in];
WHILE TRUE DO
parthandle.pininfo[pinindex].xpos ← IO.GetInt[in ! IO.EndOfStream => EXIT];
parthandle.pininfo[pinindex].ypos ← IO.GetInt[in];
parthandle.pininfo[pinindex].name ← GetRope[in];
parthandle.pininfo[pinindex].swap ← IO.GetInt[in];
parthandle.pininfo[pinindex].dia ← IO.GetInt[in];
parthandle.pininfo[pinindex].site ← IO.GetInt[in];
parthandle.pininfo[pinindex].type ← IO.GetInt[in];
parthandle.pininfo[pinindex].pad ← IO.GetInt[in];
pinindex ← pinindex + 1;
ENDLOOP;
parthandle.partinfo.pinnumber ← pinindex;
};
VerifyTableLocation: PROC[lib: Lib] = {
firstentrynumber: CARD ← ReadLong[lib, lib.tablelocation]; --First presumed entry number
firstentrylocation: CARD ← ReadShort[lib, lib.tablelocation+4]; --Address of first entry
IF ReadLong[lib, firstentrylocation] # firstentrynumber THEN ERROR;
};
ReadShort: PROC[lib: Lib, index: CARD] RETURNS [value: CARD]= {
value ← 256*lib.lib[lib.offset+index];
value ← value + lib.lib[lib.offset+index+1];
};
ReadLong: PROC[lib: Lib, index: CARD] RETURNS [value: CARD]= {
value ← 256*ReadShort[lib,index+2];
value ← ReadShort[lib,index] + value*256;
};
WriteByte: PROC [lib: Lib, index: CARD, value: CARD] ~ {
lib.lib[lib.offset+index] ← value MOD 256;
};
WriteShort: PROC [lib: Lib, index: CARD, value: CARD] ~ {
WriteByte[lib: lib, index: index, value: value/256];
WriteByte[lib: lib, index: index+1, value: value - (value/256)*256];
};
WriteShortInt: PROC [lib: Lib, index: CARD, value: INTEGER] ~ {
c: CARD;
IF value >= 0 THEN {
c ← value;
}
ELSE {
c ← 128*256 + value + 128*256
};
WriteShort[lib, index, c];
};
WriteLong: PROC [lib: Lib, index: CARD, value: CARD] ~ {
WriteShort[lib, index, value - ((value/256)/256)*256*256];
WriteShort[lib, index+2, (value/256)/256];
};
InsertEntryInTable: PROC[lib: Lib, entrynumber: CARD] RETURNS [ entryposition: CARD] = {
index: INT ← lib.tablelength - 16;
currententry: CARD ← ReadLong[lib, index];
WHILE currententry > entrynumber DO
WriteLong[lib: lib, index: index+8, value: currententry];
WriteLong[lib: lib, index: index+12, value: ReadLong[lib, index+4]];
index ← index - 8;
currententry ← ReadLong[lib, index];
ENDLOOP;
IF currententry = entrynumber THEN ERROR;
WriteLong[lib: lib, index: index+8, value: entrynumber];
entryposition ← lib.length-2-lib.offset;
WriteLong[lib: lib, index: index+12, value: entryposition];
};
InsertPartInLib: PROC [lib: Lib, parthandle: Parthandle] ~ {
b: BYTE;
i,j: CARD;
tempindex: CARD;
lengthindex: CARD;
pinnamelength: CARD;
namelength: CARD ← Rope.Length[parthandle.partinfo.name];
prefixlength: CARD ← Rope.Length[parthandle.partinfo.prefix];
numberlength: CARD ← Rope.Length[parthandle.partinfo.number];
entryposition: CARD ← InsertEntryInTable[lib: lib, entrynumber: parthandle.partinfo.entrynumber];
index: CARD ← lib.length- lib.offset -2;
Entry number
WriteLong [lib: lib, index: index, value: parthandle.partinfo.entrynumber];
index ← index + 4;
Length not yet defined
lengthindex ← index;
index ← index + 2;
Type
WriteByte[lib: lib, index: index, value: 0];
index ← index + 1;
WriteByte[lib: lib, index: index, value: 7];
index ← index + 1;
WriteByte[lib: lib, index: index, value: 0];
index ← index + 1;
Length of name
WriteByte[lib: lib, index: index, value: namelength];
index ← index + 1;
Name
FOR i IN[0..namelength) DO
b ← LOOPHOLE[Rope.Fetch[parthandle.partinfo.name,i]];
WriteByte[lib: lib, index: index, value: b];
index ← index + 1;
ENDLOOP;
Dummy
WriteShort [lib: lib, index: index, value: 1];
index ← index + 2;
Shape number
WriteLong [lib: lib, index: index, value: parthandle.partinfo.shapenumber];
index ← index + 4;
Shape number
WriteLong [lib: lib, index: index, value: parthandle.partinfo.shapenumber];
index ← index + 4;
Dummy
WriteLong [lib: lib, index: index, value: 0];
index ← index + 4;
Xmin
WriteShortInt [lib: lib, index: index, value: parthandle.partinfo.xmin];
index ← index + 2;
Ymin
WriteShortInt [lib: lib, index: index, value: parthandle.partinfo.ymin];
index ← index + 2;
Xmax
WriteShortInt [lib: lib, index: index, value: parthandle.partinfo.xmax];
index ← index + 2;
Ymax
WriteShortInt [lib: lib, index: index, value: parthandle.partinfo.ymax];
index ← index + 2;
Dummy
WriteLong [lib: lib, index: index, value: 0];
index ← index + 4;
WriteLong [lib: lib, index: index, value: 0];
index ← index + 4;
WriteLong [lib: lib, index: index, value: 0];
index ← index + 4;
Xprefix
WriteShortInt [lib: lib, index: index, value: parthandle.partinfo.xprefix];
index ← index + 2;
Yprefix
WriteShortInt [lib: lib, index: index, value: parthandle.partinfo.yprefix];
index ← index + 2;
Prefix
tempindex ← index;
WriteShort [lib: lib, index: index, value: 0];
FOR i IN[0..prefixlength) DO
b ← LOOPHOLE[Rope.Fetch[parthandle.partinfo.prefix,i]];
WriteByte[lib: lib, index: index, value: b];
index ← index + 1;
ENDLOOP;
index ← tempindex + 2;
Number of pins Only one Byte!!!!
WriteByte[lib: lib, index: index, value: parthandle.partinfo.pinnumber];
index ← index + 1;
Dummy
WriteByte[lib: lib, index: index, value: 1];
index ← index + 1;
WriteShortInt [lib: lib, index: index, value: 0];
index ← index + 2;
WriteShortInt [lib: lib, index: index, value: 0];
index ← index + 2;
WriteShortInt [lib: lib, index: index, value: 0];
index ← index + 2;
For each pin
FOR i IN[0..parthandle.partinfo.pinnumber) DO
Xpos
WriteShortInt [lib: lib, index: index, value: parthandle.pininfo[i].xpos];
index ← index + 2;
Ypos
WriteShortInt [lib: lib, index: index, value: parthandle.pininfo[i].ypos];
index ← index + 2;
Dummy
WriteByte[lib: lib, index: index, value: 0];
index ← index + 1;
Diameter
WriteByte[lib: lib, index: index, value: parthandle.pininfo[i].dia];
index ← index + 1;
Site number
WriteByte[lib: lib, index: index, value: parthandle.pininfo[i].site-1];
index ← index + 1;
Pad stack
WriteByte[lib: lib, index: index, value: parthandle.pininfo[i].pad];
index ← index + 1;
Swap number
WriteByte[lib: lib, index: index, value: parthandle.pininfo[i].swap];
index ← index + 1;
Pin type and Length of pin name
pinnamelength ← Rope.Length[parthandle.pininfo[i].name];
IF pinnamelength>15 THEN ERROR;
WriteByte[lib: lib, index: index, value: 16*parthandle.pininfo[i].type+pinnamelength];
index ← index + 1;
Pin Name
FOR j IN[0..pinnamelength) DO
b ← LOOPHOLE[Rope.Fetch[parthandle.pininfo[i].name,j]];
WriteByte[lib: lib, index: index, value: b];
index ← index + 1;
ENDLOOP;
ENDLOOP;
Dummy
WriteByte[lib: lib, index: index, value: 0];
index ← index + 1;
Length of number
WriteByte[lib: lib, index: index, value: numberlength];
index ← index + 1;
Name
FOR i IN[0..numberlength) DO
b ← LOOPHOLE[Rope.Fetch[parthandle.partinfo.number,i]];
WriteByte[lib: lib, index: index, value: b];
index ← index + 1;
ENDLOOP;
Length of the entry
WriteShort [lib: lib, index: lengthindex, value: index - lengthindex - 2];
Clear next position
WriteByte[lib: lib, index: index, value: 0];
Adjust index to an even number
index ← index + index - (index/2)*2;
WriteShort [lib: lib, index: index, value: 255*256-3];
index ← index + 2;
lib.length ← index + lib.offset;
};
InsertChecksum: PROC [lib: Lib] ~ {
index: CARD ← 0;
checksum: CARD ← 0;
WHILE index < lib.length - 2 DO
checksum ← checksum + ReadShort[lib, index];
index ← index + 2;
ENDLOOP;
WriteShort [lib: lib, index: index-lib.offset, value: checksum-(((checksum/256)/256)*256)*256]
};
WriteNewLib: PROC[lib: Lib, outputfile: ROPE] = {
i: CARD;
out: IO.STREAMFS.StreamOpen[outputfile,$create];
FOR i IN [0..lib.length) DO
IO.PutChar[out,VAL[lib.lib[i]]];
ENDLOOP;
IO.Close[out];
};
NewPartProc: Commander.CommandProc = BEGIN
parthandle: Parthandle;
lib: Lib;
stream: IO.STREAMIO.RIS[cmd.commandLine];
outputfile: ROPE ← GetRope[stream, CmdTokenBreak];
gets: ROPE ← GetRope[stream, CmdTokenBreak];
initiallibfile: ROPE ← GetRope[stream, CmdTokenBreak];
initialpartfile: ROPE ← GetRope[stream, CmdTokenBreak];
IF NOT Rope.Equal[gets,"←"] OR outputfile = NIL
OR initiallibfile = NIL OR initialpartfile = NIL THEN {
cmd.out.PutRope["\nUsage:\nNewPart NewLibFile ← OldLibFile PartFile\n"];
}
ELSE {
lib ← ReadInitialLib[initiallibfile];
parthandle ← ReadPartFile[initialpartfile];
lib.offset ← offset;
lib.tablelocation ← tablelocation;
lib.tablelength ← tablelength;
VerifyTableLocation[lib];
InsertPartInLib[lib, parthandle];
InsertChecksum[lib];
WriteNewLib[lib, outputfile];
};
END;
Commander.Register[
key: "NewPart", proc: NewPartProc, doc: "Adds a new Part and a new Shape to an Expert 2.5 library.\n"];
END.