// PeekParams.bcpl
// Copyright Xerox Corporation 1979
// Last modified February 12, 1979  12:46 AM by Boggs

get "streams.d"

external
[
// outgoing procedures
PeekParams

// incoming procedures
MyFrame; GotoFrame; CallSwat
Allocate; Free; Zero; MoveBlock
OpenFile; Closes; Endofs; Gets; Puts
AddNameToBFQ; StringCompare
SetBootBcstInterval; SetNameBcstInterval
SetTimeCorrection; SetTimeZone; SetTimeDST
CreatePeekServ; CreateERPServer

// incoming statics
sysZone; ctxQ; dsp; fpUserCm
]

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

structure String [ length byte; char↑1,255 byte ]

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

//----------------------------------------------------------------------------
let PeekParams() be
//----------------------------------------------------------------------------
[
paramFile = OpenFile("User.cm", ksTypeReadOnly, charItem, 0, fpUserCm)
if paramFile eq 0 then CallSwat("[PeekParams] - can't open User.cm")
buffer = Allocate(sysZone, numAtomWords)
end = MyFrame()
InterpretParam()
Free(sysZone, buffer)
Closes(paramFile)
]

//----------------------------------------------------------------------------
and InterpretParam() be
//----------------------------------------------------------------------------
[
inComment, doComment = false, false
   [
   let atom = ReadAtom()
   if StringCompare(atom, "[PEEK]") eq 0 break
   ] repeat
inComment, doComment = false, true
   [
   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:  // DST <begin day number> <end day number>
         [
         let beginDST = ReadNumber(10)
         let endDST = ReadNumber(10)
         SetTimeDST(beginDST, endDST)
         endcase
         ]
      case $E: case $e:  // ERP <soc> <filename>
         [
         let port = vec 2; Zero(port, 3)
         port!2 = ReadNumber(8)
         let file = OpenFile(ReadAtom(), ksTypeWriteOnly, charItem)
         if file eq 0 then CallSwat("[InterpretParam] - cant open event file")
         CreateERPServer(sysZone, ctxQ, port, file)
         endcase
         ]
      case $P: case $p:
         [
         switchon atom>>String.char↑2 into
            [
            case $E: case $e:  // Peek <filename>
               [
               CreatePeekServ(ReadAtom())
               endcase
               ]
            case $R: case $r:  // Probe <hours>
               [
               let hours = ReadNumber(10)
               SetBootBcstInterval(hours)
               SetNameBcstInterval(hours)
               endcase
               ]
            ]
         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
         ]
      case $[: return
      default:
         [
         let char = ReadChar()
         if char eq -1 % char eq $*N endcase
         ] repeat
      ]
   ] repeat
]

//----------------------------------------------------------------------------
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); Puts(dsp,char)
   if char eq $*N then inComment = false
   if inComment loop
   if doComment & char eq $; then inComment = true
   resultis char
   ]
resultis -1
]

//----------------------------------------------------------------------------
and IsBreak(char) =
//----------------------------------------------------------------------------
   char eq $*N % char eq $*S % char eq $*T %
    char eq -1 % char eq $; % char eq $: % char eq $,