// RouteMisc.bcpl

// Stuff that used to be in RouteC and RouteSyms but is only needed in overlays
// than the RouteNet overlay.

// last modified by Taft, September 22, 1979 8:50 PM

get "route.defs"

let ReadICType(str) = valof
[
static
[
npins
family
]

let NewICType(ictype) be
[
ictype>>ictype.npins = npins
ictype>>ictype.icclass = DefineNamee(family, typeIcclass, CallSwat)
]

until char eq $( do char = Gets(str) //read up to left paren
let typen = vec 50; typen!0= 0
[
char = Gets(str)
if char eq $/ then break
AppendC(typen,char)
] repeat

npins =0
[
char = Gets(str)
if char eq $/ then break
npins = npins*10 + (char-$0)
] repeat

let f = vec 20
family = f
let len = 0
char = used
until GetValidChar(str) eq $) do
[
len = len+1
family>>str.char↑len = char
char = used
]
family>>str.length = len

until char eq $*n do char = Gets(str) //discard rest of line
char = used

let extraPins = npins-(size ictype.outpins-1)
if extraPins ls 0 then extraPins = 0
let completename = vec 30
resultis DefineNamee(ExpandTemplate(completename, "$S/$D/$S",
typen, npins, family) ,typeIctype,NewICType, (extraPins+15)/16)
]
and ReadNetName(stream, name, attributes, pcluster, endMask, startMask; numargs na) = valof
[
DefaultArgs(lv na, 3, empty, colonMask, netNameMask)

name!0 = 0
attributes!0 = 0
until (GetValidChar(stream) eq filegone)%((charTab!char&startMask) ne 0) do
char = used

until (char eq filegone)%(charTab!char&endMask) ne 0 do
[
AppendC(name, char)
char = Gets(stream)
]

if char eq filegone then resultis false // can’t, because end of file

while name>>str.length ge 0 do
[
let len = name>>str.length
let atch = name>>str.char↑len
if (charTab!atch&netNameMask) ne 0 then break
name>>str.length = len-1
AppendC(attributes, atch)
]

if pcluster ne empty then
[
let clusterNumber = 0
let base = 1
for i = name>>str.length to 1 by -1 do
[
let c = name>>str.char↑i
if c eq $! then
[
name>>str.length = i-1
@pcluster = clusterNumber
break
]
if c ls $0 % c gr $9 then break
clusterNumber = (base*(c-$0))+clusterNumber
base = 10*base
]
]
resultis true
]
and GetValidChar(stream) = valof
[
if char eq used then // need to refill
[

if Endofs(stream) then
[
char = filegone
resultis filegone
]
char = Gets(stream)
]

while (char eq $;) % (char eq $|) do
[
[ // copies comment lines to .WL and .AD files
if copyComments & (CommentsFile ne empty) then
Puts(CommentsFile,char)

if char eq $*n then break
if Endofs(stream) then break
char=Gets(stream)
] repeat
if Endofs(stream) then
[
char = filegone
resultis filegone
]
char = Gets(stream)
]
resultis char
]
and InsertDeviceIfPossible(boardloc, type, suppressWarnings, forceInstance; numargs na) = valof
[
static [ ictype ]
let NewInst(icinst) = NewICInst(icinst, ictype)

DefaultArgs(lv na, -2, false, false)

ictype = type

let result = TryInserting(boardloc, ictype)
unless suppressWarnings % result eq 0 do switchon result into
[
case 1:
Warning("*nIC $S conflicts with a different IC installed earlier.",
boardloc)
endcase

case 2:
Serious("*nAt least one pin of IC $S doesn’t correspond to a socket in the board.",
boardloc)
endcase
]

resultis (result eq 0 % forceInstance)?
DefineNamee(boardloc, typeIcinst, NewInst, Npins(ictype)-1),
empty
]
and TryInserting(boardloc, ictype, tentative; numargs na) = valof
[ // 0 => fits OK, insert it; 1 => another IC overlaps
// 2 => socket needed where board has none

DefaultArgs(lv na, -2, false)
let minx,miny = infinity,infinity
let maxx,maxy = 0,0

for pinNo=1 to Npins(ictype) do
[
let x,y = nil,nil
unless BoardPinCoord(boardloc, ictype, pinNo, lv x, lv y) do loop

if FindIndexFromCoord(x,y) eq 0 then resultis 2

if x ls minx then minx = x
if y ls miny then miny = y
if x gr maxx then maxx = x
if y gr maxy then maxy = y
]

let spMin = Sperge(minx,miny)
let spMax = Sperge(maxx,maxy)
if OverlapsClaimedArea(spMin,spMax) then resultis 1
unless tentative do ClaimArea(spMin,spMax)
resultis 0
]
and GetPatternCoord(string, px, py) = valof
[
if FindCoordFromString(string, px, py) eq absolute then resultis true

// Not a kosher IC position. Try parsing it.

let boardloc = vec 20
let pinNo, modifier = 0, 0
ParsePin(string, boardloc, lv pinNo, lv modifier)
let icinst = TryFindingNamee(boardloc, typeIcinst)
if icinst eq empty then resultis false
resultis GetPinCoord(icinst, pinNo, px, py)
]

// P i n a n d B o a r d L o c a t i o n P a r s i n g R o u t i n e s

and ParsePin(pin, boardloc, pPinNo, pModifier) be
[
let lastPeriod = 0
let lastNonDigit = 0

for i=pin>>str.length to 1 by -1 do
[
if pin>>str.char↑i eq $. then
[
lastPeriod = i
break
]
]

if lastPeriod eq 0 then // edge pin, find lastNonDigit
[
for i=pin>>str.length to 1 by -1 do
[
let c = pin>>str.char↑i
if (c ls $0) % (c gr $9) then
[
lastNonDigit = i
break
]
]
]

let boardloclen = (lastPeriod gr 0)? lastPeriod-1, lastNonDigit
boardloc>>str.length = boardloclen
for i=1 to boardloclen do boardloc>>str.char↑i = pin>>str.char↑i
let firstPinNoDigit = (lastPeriod gr 0)? lastPeriod+1, lastNonDigit+1
let lastPinNoDigit = pin>>str.length
let c = pin>>str.char↑lastPinNoDigit
test (c ls $0) % (c gr $9)
ifso
[
@pModifier = c
lastPinNoDigit = lastPinNoDigit-1
]
ifnot
[
@pModifier = 0
]

let pinNo = 0
for i=firstPinNoDigit to lastPinNoDigit do
[
c = pin>>str.char↑i
test (c ls $0)%(c gr $9)
ifso
[
Serious("*nIllegal pin format *"$S*".", pin)
]
ifnot
[
pinNo = 10*pinNo+(c-$0)
]
]
@pPinNo = pinNo
]

and NormalizeBoardLoc(boardloc) be
[
let boardloclen = boardloc>>str.length

let firstchar = boardloc>>str.char↑1
if firstchar ne $# & firstchar ne $? then
[
while boardloclen gr 3 & boardloc>>string.char↑2 eq $0 do
[
boardloclen = boardloclen-1
for i=2 to boardloclen do boardloc>>str.char↑i = boardloc>>str.char↑(i+1)
]

while boardloclen ls 3 do
[
boardloclen = boardloclen+1
for i=3 to boardloclen do boardloc>>str.char↑(i+1) = boardloc>>str.char↑i
boardloc>>string.char↑2 = $0
]
]
boardloc>>str.length = boardloclen
]