// DLSConfig.bcpl -- Alto DLS configuration file reader // Last modified June 20, 1982 10:46 AM by Taft // Last modified January 15, 1985 11:11 AM by Diebert get "DLSDriver.decl" get "Pup.decl" get "DLSControl.decl" get "DLSConfig.decl" // Syntax of DLS configuration file: // One or more entries, each terminated by return. // <entry> ::= <line> <description> | // <comment> // <line> ::= <octal line number of line being described> // <description> ::= <attribute> | <description> <attribute> // <attribute> ::= <lineType> | <controlLine> | <defaultHost> | // <baudRate> | <terminalType> | <length> | <width> | // <diallerInfo> | <stopBits> | <loopLine> | <otherAttribute> // <lineType> ::= Unused | Hardwired | DataSet | Telenet | Log | <diallerStuff> // <diallerStuff> ::= Dialler <diallerSignal> <diallerType> | Dialler <diallerSignal> // <controlLine> ::= Control <line> // <defaultHost> ::= Host <hostName> // <baudRate> ::= Baud <decimal number> // <terminalType> ::= Type <decimal number> // Tenex terminal type // <length> ::= Length <decimal number> // Lines/page // <width> ::= Width <decimal number> // Chars/line // <diallerInfo> ::= DialOut <decimal number> <decimal number> // <stopBits> ::= Stop 1 | Stop 2 // <loopLine> ::= Loop <line> // Implemented only in ChollaDLS // <diallerSignal> ::= CRQ | DP | NB1 | NB2 | NB4 | NB8 // <diallerType> ::= DiallerType <decimal number> // <otherAttribute> ::= DialOutOnly | NoPad | 8Bit // Each entry must contain a <lineType>, and entries with <lineType> of // DataSet or Telenet must contain a <ControlLine>. // If a <baudRate> is specified, the line will run at that fixed rate. // Normally <baudRate> is omitted, and speed determination is performed // at connection time. // Dial-out lines, as well as having a <controlLine> attribute, also // have a <diallerInfo> attribute with two arguments: // Modem address, i.e., Vadic card cage slot number (1-16) in the // cage that has the dialler. // Modem type: 1 = 103-compatible modem, 0 = Vadic modem // 3 = 103/212 compatible modem, 2 = illegal // There are 6 lines that control the dialler itself; each is declared by // a "Dialler <diallerSignal>" entry, where the argument is the name // of the output signal being controlled. Some of the lines also have // input signals connected to them; the correspondence is: // output: CRQ DP NB1 NB2 NB4 NB8 // input: PND ACR DSS -- -- -- // Each dialler has an associated DiallerType; declared by a // a "DiallerType <decimal number>" entry, wher the number is // 1 for a Vadic VA811 dialler and 0 for any other types // You must code one "Log" line // DialOutOnly means that the line is controlled exclusively from the network // side; input from the line is ignored when the line is idle. external [ // Outgoing procedures ReadDLSConfig // Incoming procedures OpenFile; Closes; Gets; FilePos; SetFilePos; ReadUserCmItem Zero; CallSwat; Allocate; MoveBlock ReturnFrom ] static [ file; char; startPos; uniqueStringList = 0 ] structure UniqueStr: [ next word string @String ] // --------------------------------------------------------------------------- let ReadDLSConfig(dlsConfig, zone) be // --------------------------------------------------------------------------- // Reads DLS configuration file and loads data into dlsConfig. // Calls Swat if the file is malformed. [ Zero(dlsConfig, lenDLSConfig) let parsed = false // First look for [DLS] section in User.cm let userCm = OpenFile("User.cm", ksTypeReadOnly, charItem) if userCm ne 0 then [ let token = vec 127 let inDLSSection = false switchon ReadUserCmItem(userCm, token) into [ // repeat case $N: inDLSSection = StringEq(token, "DLS") endcase case $L: if inDLSSection then test StringEq(token, "Indirect") ifso [ // Indirect: fileName ReadUserCmItem(userCm, token) ParseDLSConfig(dlsConfig, token, zone) parsed = true ] ifnot test StringEq(token, "Name") ifso [ // Name: name ReadUserCmItem(userCm, token) dlsConfig>>DLSConfig.name = MakeUniqueString(token, zone) ] ifnot test StringEq(token, "Registry") ifso [ // Registry: reg ReadUserCmItem(userCm, token) dlsConfig>>DLSConfig.thisRegistry = MakeUniqueString(token, zone) ] ifnot test StringEq(token, "AuthorizationList") ifso [ // AuthorizationList: list ReadUserCmItem(userCm, token) dlsConfig>>DLSConfig.thisOutList = MakeUniqueString(token, zone) ] ifnot test StringEq(token, "InAuthorizationList") ifso [ // AuthorizationList: list ReadUserCmItem(userCm, token) dlsConfig>>DLSConfig.thisInList = MakeUniqueString(token, zone) ] ifnot test StringEq(token, "WizardList") ifso [ // WizardList: list ReadUserCmItem(userCm, token) dlsConfig>>DLSConfig.thisWizardList = MakeUniqueString(token, zone) ] ifnot CallSwat("[ReadDLSConfig] Undefined User.cm item:", token) endcase case $E: break ] repeat Closes(userCm) ] // If nothing found in User.cm, assume correct name is DLS.config. unless parsed do ParseDLSConfig(dlsConfig, "DLS.config", zone) if dlsConfig>>DLSConfig.name eq 0 then dlsConfig>>DLSConfig.name = MakeUniqueString("DLS", zone) if dlsConfig>>DLSConfig.thisRegistry eq 0 then dlsConfig>>DLSConfig.thisRegistry = MakeUniqueString("PA", zone) if dlsConfig>>DLSConfig.thisWizardList eq 0 then dlsConfig>>DLSConfig.thisWizardList = MakeUniqueString("DLSWizards↑.PA", zone) ] // --------------------------------------------------------------------------- and ParseDLSConfig(dlsConfig, fileName, zone) be // --------------------------------------------------------------------------- [ file = OpenFile(fileName, ksTypeReadOnly, charItem) if file eq 0 then CallSwat("[ReadDLSConfig] Can't find configuration file:", fileName) let MyStreamError(file, ec) be [ Closes(file); ReturnFrom(ParseDLSConfig) ] file>>ST.error = MyStreamError [ //repeat char = Gets(file) repeatwhile char eq $*n % char eq $*s % char eq $*t % char eq $*014 if char eq $; % char eq $/ then [ char = Gets(file) repeatuntil char eq $*n; loop ] startPos = FilePos(file)-1 let line = ReadLineNumber(file) let lc = lv dlsConfig>>DLSConfig.lc↑line if lc>>LC.lineType ne ltUnused then Malformed("[ReadDLSConfig] Duplicate line entry") let string = vec 127 until char eq $*n do [ ReadToken(file, string) test StringEq(string, "Baud") ifso lc>>LC.data.constantBaud = ReadNumber(file) ifnot test StringEq(string, "Control") ifso [ let otherLine = ReadLineNumber(file) lc>>LC.otherLine = otherLine dlsConfig>>DLSConfig.lc↑otherLine.lineType = ltControl dlsConfig>>DLSConfig.lc↑otherLine.otherLine = line ] ifnot test StringEq(string, "DataSet") ifso lc>>LC.lineType = ltDataSet ifnot test StringEq(string, "Log") ifso lc>>LC.lineType = ltLog ifnot test StringEq(string, "Dialler") ifso [ lc>>LC.lineType = ltDialler ReadToken(file, string) lc>>LC.dialler.signalIndex = StringEq(string, "CRQ")? 0, StringEq(string, "DP")? 1, StringEq(string, "NB1")? 2, StringEq(string, "NB2")? 3, StringEq(string, "NB4")? 4, StringEq(string, "NB8")? 5, Malformed() ] ifnot test StringEq(string, "DiallerType") ifso lc>>LC.data.diallerType = ReadRangeCheckedNumber(file, 10, 0, 1) ifnot test StringEq(string, "DialOut") ifso [ lc>>LC.dialOut = true lc>>LC.data.modemAddress = ReadRangeCheckedNumber(file, 10, 1, 15)-1 lc>>LC.data.modemType = ReadRangeCheckedNumber(file, 10, 0, 3) ] ifnot test StringEq(string, "DialOutOnly") ifso lc>>LC.data.dialOutOnly = true ifnot test StringEq(string, "Hardwired") ifso lc>>LC.lineType = ltHardwired ifnot test StringEq(string, "Host") ifso lc>>LC.data.host = ReadUniqueString(file, zone) ifnot test StringEq(string, "Length") ifso lc>>LC.data.terminalLength = ReadNumber(file) ifnot test StringEq(string, "Loop") ifso lc>>LC.otherLine = ReadLineNumber(file) ifnot test StringEq(string, "NoPad") ifso lc>>LC.data.noPad = true // ParseDLSConfig(dlsConfig, fileName, zone) continued ifnot test StringEq(string, "8Bit") ifso lc>>LC.data.eightBit = true ifnot test StringEq(string, "Stop") ifso lc>>LC.data.stopBits = ReadRangeCheckedNumber(file, 10, 1, 2) ifnot test StringEq(string, "Telenet") ifso lc>>LC.lineType = ltTelenet ifnot test StringEq(string, "Type") ifso lc>>LC.data.terminalType = ReadNumber(file) ifnot test StringEq(string, "Unused") ifso lc>>LC.lineType = ltUnused ifnot test StringEq(string, "Width") ifso lc>>LC.data.terminalWidth = ReadNumber(file) ifnot Malformed("[ReadDLSConfig] Undefined attribute") ] ] repeat ] // --------------------------------------------------------------------------- and ReadLineNumber(file) = ReadRangeCheckedNumber(file, 8, 0, numLines-1) // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- and ReadRangeCheckedNumber(file, radix, min, max) = valof // --------------------------------------------------------------------------- [ let num = ReadNumber(file, radix) if num ls min % num gr max then Malformed("[ReadDLSConfig] Number out of range") resultis num ] // --------------------------------------------------------------------------- and ReadNumber(file, radix; numargs na) = valof // --------------------------------------------------------------------------- [ if na ls 2 then radix = 10 let string = vec 127 let length = ReadToken(file, string) let num = 0 for i = 1 to length do [ let digit = string>>String.char↑i - $0 if digit ls 0 % digit ge radix then Malformed() num = radix*num + digit ] resultis num ] // --------------------------------------------------------------------------- and ReadUniqueString(file, zone) = valof // --------------------------------------------------------------------------- [ let string = vec 127 ReadToken(file, string) resultis MakeUniqueString(string, zone) ] // --------------------------------------------------------------------------- and MakeUniqueString(string, zone) = valof // --------------------------------------------------------------------------- [ let uniqueStr = uniqueStringList while uniqueStr ne 0 do [ if StringEq(string, lv uniqueStr>>UniqueStr.string) then resultis lv uniqueStr>>UniqueStr.string uniqueStr = uniqueStr>>UniqueStr.next ] let len = string>>String.length rshift 1 +1 uniqueStr = Allocate(zone, len + offset UniqueStr.string/16) MoveBlock(lv uniqueStr>>UniqueStr.string, string, len) uniqueStr>>UniqueStr.next = uniqueStringList uniqueStringList = uniqueStr resultis lv uniqueStr>>UniqueStr.string ] // --------------------------------------------------------------------------- and ReadToken(file, string) = valof // --------------------------------------------------------------------------- [ let length = 0 while char eq $*s % char eq $*t do char = Gets(file) if char eq $*n then Malformed() [ length = length+1 string>>String.char↑length = char char = Gets(file) ] repeatuntil char eq $*s % char eq $*t % char eq $*n % char eq $; string>>String.length = length while char eq $*s % char eq $*t do char = Gets(file) if char eq $/ then until char eq $*n do char = Gets(file) resultis length ] // --------------------------------------------------------------------------- and StringEq(str1, str2) = valof // --------------------------------------------------------------------------- [ if str1>>String.length ne str2>>String.length resultis false for i = 1 to str1>>String.length do [ let c1 = str1>>String.char↑i if c1 ge $a & c1 le $z then c1 = c1-($a-$A) let c2 = str2>>String.char↑i if c2 ge $a & c2 le $z then c2 = c2-($a-$A) if c1 ne c2 resultis false ] resultis true ] // --------------------------------------------------------------------------- and Malformed(message; numargs na) be // --------------------------------------------------------------------------- [ if na eq 0 then message = "[ReadDLSConfig] Configuration file malformed" let text = vec 127 SetFilePos(file, 0, startPos) for i = 1 to 255 do [ text>>String.char↑i = Gets(file) text>>String.length = i if text>>String.char↑i eq $*n break ] CallSwat(message, text) ]