// GateParameter.bcpl
// Last modified December 26, 1981  11:25 PM by Boggs

get "Pup0.decl"
get "Pup1.decl"
get "Streams.d"

external
[
// outgoing procedures
ReadGateParam

// incoming procedures
MyFrame; GotoFrame; HInsert; CallSwat
OpenFile; Closes; Endofs; Gets
AddNameToBFQ; SetNameBcstInterval; SetBootBcstInterval
SetTimeCorrection; SetTimeZone; SetTimeDST

// incoming statics
pupRT; ndbQ
]

manifest
[
maxAtomChars = 30
numAtomWords = maxAtomChars rshift 1 +1
]

static [ paramFile; inComment; end; buffer; lastNumberWasPositive ]

//----------------------------------------------------------------------------
let ReadGateParam() be
//----------------------------------------------------------------------------
[
paramFile = OpenFile("GATEPARAMETER.TXT", ksTypeReadOnly, charItem)
if paramFile eq 0 then CallSwat("Can't open GATEPARAMETER.TXT*n")
let v = vec numAtomWords; buffer = v
end = MyFrame()
inComment = false
InterpretParam()
Closes(paramFile)
]

//----------------------------------------------------------------------------
and InterpretParam() be
//----------------------------------------------------------------------------
[
let atom = ReadAtom()
switchon atom>>String.char↑1 into
   [
   case $B: case $b:  //Boot <code> <filename>
      [
      let bfn = ReadNumber(8)
      let name = ReadAtom()
      AddNameToBFQ(bfn, name)
      endcase
      ]
   case $C: case $c:  //Correction <sign> <correction in seconds per day)>
      [
      let seconds = ReadNumber(10)
      SetTimeCorrection(seconds, lastNumberWasPositive)
      endcase
      ]
   case $D: case $d:
      [
      let beginDST = ReadNumber(10)
      let endDST = ReadNumber(10)
      SetTimeDST(beginDST, endDST)
      endcase
      ]
   case $H: case $h:  //Host <netType> <device code> <net> <host>
      [
      let netType = ReadNumber(8)
      let deviceNum = ReadNumber(8)
      let net = ReadNumber(8)
      let host = ReadNumber(8)
      let ndb = ndbQ!0; while ndb ne 0 do
         [
         if ndb>>NDB.netType eq netType & ndb>>NDB.deviceNum eq deviceNum then
            [
            if ndb>>NDB.localHost ne 0 & ndb>>NDB.localHost ne host then
               CallSwat("Wrong GATEPARAMETER.TXT for this gateway*N")
            ndb>>NDB.localNet = net
            ndb>>NDB.localHost = host
            let rte = HInsert(pupRT, net)
            rte>>RTE.ndb = ndb
            rte>>RTE.host = host
            break
            ]
         ndb = ndb>>NDB.link
         ]
      endcase
      ]

// InterpretParam (Cont'd)

   case $P: case $p:  //Probe <Hours>
      [
      let hours = ReadNumber(10)
      SetNameBcstInterval(hours)
      SetBootBcstInterval(hours)
      endcase
      ]
   case $Z: case $z:  //Zone <sign: + is West of Greenwich> <Hours>:<Minutes>
      [
      let zoneH = ReadNumber(10)
      let zoneS = not lastNumberWasPositive
      let zoneM = ReadNumber(10)
      SetTimeZone(zoneS, zoneH, zoneM)
      endcase
      ]
   default:
      [
      let char = ReadChar()
      if char eq -1 % char eq $*N endcase
      ] repeat
   ]
] repeat

//----------------------------------------------------------------------------
and IsBreak(char) =
//----------------------------------------------------------------------------
   char eq $*N % char eq $*S % char eq $*T %
    char eq -1 % char eq $; % char eq $: % char eq $,

//----------------------------------------------------------------------------
and ReadNumber(radix; numargs na) = valof
//----------------------------------------------------------------------------
// interprets the next atom as a number in the given radix
[
if na eq 0 then radix = 8
let atom = ReadAtom()
let number = 0
lastNumberWasPositive = true
for i = 1 to atom>>String.length do
   [
   let char = atom>>String.char↑i
   if i eq 1 & (char eq $- % char eq $+) then
      [ lastNumberWasPositive = char eq $+; loop ]
   char = char-$0
   unless char ge 0 & char le radix-1 do
      CallSwat("*N[ReadNumber] - illegal character in number")
   number = number * radix + char
   ]
resultis number
]

//----------------------------------------------------------------------------
and ReadAtom() = valof
//----------------------------------------------------------------------------
// returns pointer to a string
// goes to top frame if end of file before reading any chars
[
let char = nil
   [  //ignore leading junk
   char = ReadChar()
   if char eq -1 then GotoFrame(end)
   unless IsBreak(char) break
   ] repeat
let count = 0
   [  //collect an atom
   count = count + 1
   if count gr maxAtomChars then
      CallSwat("*N[ReadAtom] - atom too long")
   buffer>>String.char↑count = char
   char = ReadChar()
   if IsBreak(char) break
   ] repeat
buffer>>String.length = count
resultis buffer
]

//----------------------------------------------------------------------------
and ReadChar() = valof
//----------------------------------------------------------------------------
// returns the next character in the stream
// returns -1 on end of file
[
until Endofs(paramFile) do
   [  //filter out comments here
   let char = Gets(paramFile)
   if char eq $*N then inComment = false
   if inComment loop
   if char eq $; then inComment = true
   resultis char
   ]
resultis -1
]