<> <> <> DIRECTORY Ascii, Convert USING [RopeFromCard, CardFromRope], FS, IO, PupNet, Rope; PupNetImpl: CEDAR PROGRAM IMPORTS Ascii, Convert, FS, IO, Rope EXPORTS PupNet = { buffer: REF TEXT _ NEW[TEXT[100]]; eof: BOOLEAN; inputStream: IO.STREAM _ NIL; -- Input IO sream PupNetImplERROR: ERROR ~ CODE; NetRecord: TYPE ~ RECORD [ name: Rope.ROPE _ NIL, value: CARD _ 0 ]; NetData: TYPE ~ REF NetRecord; netList: LIST OF NetData _ NIL; breakProc: IO.BreakProc = { SELECT char FROM IN [Ascii.NUL .. Ascii.FF], IN[Ascii.ESC .. Ascii.SP], '\255 => RETURN[IO.CharClass[sepr]]; ':, '=, '", ';, Ascii.CR, ', => RETURN[IO.CharClass[break]]; ENDCASE => RETURN[IO.CharClass[other]]}; GetToken: PROC [] RETURNS [token: REF TEXT] = { <> token _ IO.GetToken[inputStream, breakProc, buffer ! IO.EndOfStream => { buffer[0] _ Ascii.CR; token _ buffer; eof _ TRUE; CONTINUE} ].token; }; CheckToken: PROC [c1, c2: CHAR] RETURNS [eol: BOOLEAN _ FALSE] = { <> token: REF TEXT _ GetToken[]; IF token[0]=Ascii.CR THEN {eol _ TRUE; RETURN}; IF token[0]#c1 AND token[0]#c2 THEN { SkipToEOL[]; eol _ TRUE; RETURN}; }; SkipToEOL: PROC [] = { <> WHILE GetToken[].token[0] # Ascii.CR DO ENDLOOP; }; GetNetNameTokenRope: PROC [stream: IO.STREAM] RETURNS [token: Rope.ROPE] ~ { <<... returns the next symbolic net name found in stream.>> break: IO.BreakProc = { <<[char: CHAR] RETURNS [IO.CharClass]>> SELECT char FROM '# => RETURN [IO.CharClass.break]; ENDCASE => RETURN [IO.CharClass.other] }; -- break RETURN [IO.GetTokenRope[stream: stream, breakProc: break].token] }; -- GetNetNameTokenRope ConvertNetAddress: PROC [symbolicName: Rope.ROPE, convertList: LIST OF NetData] RETURNS [realNetName: Rope.ROPE] ~ { <<...takes symbolicName which is a net address using a symbolic net name and converts it to its real net address using the information in convertList.>> <<>> stream: IO.STREAM _ IO.RIS[rope: symbolicName]; symbolicNetName: Rope.ROPE _ GetNetNameTokenRope[stream: stream].token; value: CARD _ FindValueInList[name: symbolicNetName, list: convertList]; realNetName _ Rope.Cat[Convert.RopeFromCard[from: value], Rope.Substr[base: symbolicName, start: Rope.Length[base: symbolicNetName] ]] }; -- Convert GetNetValue: PROC [netAddress: Rope.ROPE] RETURNS [value: CARD] ~ { <<... looks at netAddress and determines the net value.>> stream: IO.STREAM _ IO.RIS[rope: netAddress]; valueRope: Rope.ROPE _ IO.GetCedarTokenRope[stream: stream].token; RETURN[value _ Convert.CardFromRope[r: valueRope]] }; -- GetNetValue FindValueInList: PROC [name: Rope.ROPE, list: LIST OF NetData] RETURNS [value: CARD] ~ { <<... finds the occurance of name in list and returns the corresponding value.>> <<>> FOR netItem: LIST OF NetData _ list, netItem.rest UNTIL netItem = NIL DO IF Rope.Equal[s1: name, s2: netItem.first.name, case: FALSE] THEN RETURN[value _ netItem.first.value] ENDLOOP; RETURN [0] -- somethings wrong if we don't have a value }; -- FindValueInList ParseLine: PROC [] RETURNS [name, owner, location, netAddress: Rope.ROPE _ NIL, gateway, network: BOOLEAN _ FALSE] = { <> <> <> <> << ::= =
; >> eol, socket: BOOLEAN _ FALSE; [name, eol] _ ParseNameList[]; IF eol THEN RETURN; [netAddress, network, gateway, socket, eol] _ ParseAddressList[name: name]; IF socket THEN RETURN[NIL, NIL, NIL, NIL, FALSE, FALSE]; IF eol THEN RETURN; [owner, location] _ ParseAttributeList[]; }; ParseNameList: PROC [] RETURNS [name: Rope.ROPE _ NIL, eol: BOOLEAN _ FALSE] = { << ::= | , >> << ::= * | >> <> <> <> t: REF TEXT; WHILE TRUE DO t _ GetToken[]; SELECT t[0] FROM Ascii.CR => {eol _ TRUE; RETURN}; '; => {SkipToEOL[]; eol _ TRUE; RETURN}; '= => RETURN; IN ['a .. 'z], IN['A .. 'Z] => name _ IF name#NIL THEN Rope.Cat[name, " ", Rope.FromRefText[t]] ELSE Rope.FromRefText[t]; ENDCASE; ENDLOOP; }; ParseAddressList: PROC [name: Rope.ROPE] RETURNS [netAddress: Rope.ROPE, network, gateway, socket, eol: BOOLEAN _ FALSE] = { <<
::=
|
,
>> <<
::= | >> << ::= | + >> << ::= |
>> <<
::= | # |>> << # # >> << ::= | empty>> <> <> <> <> <> <> <> count: INT _ 0; pos: INT _ 0; t: REF TEXT; tNetAddress: Rope.ROPE; WHILE TRUE DO t _ GetToken[]; IF t[0] = ', THEN t _ GetToken[]; SELECT t[0] FROM Ascii.CR => {eol _ TRUE; RETURN}; '; => RETURN ENDCASE; <> IF t[t.length-1]#'# THEN { socket _ TRUE; eol _ TRUE; SkipToEOL[]; RETURN; }; <> IF t.length < 2 THEN LOOP; tNetAddress _ Rope.FromRefText[t]; <<>> <> IF t[t.length-1]='# AND t[t.length-2]='# THEN { network _ TRUE; netList _ CONS[NEW[NetRecord _ [name: name, value: GetNetValue[tNetAddress]]], netList]; }; <> IF (pos _ Rope.Find[tNetAddress, "+"]) # -1 THEN tNetAddress _ Rope.Replace[base: tNetAddress, start: pos, len: 1, with:"#"]; IF NOT network THEN tNetAddress _ ConvertNetAddress[tNetAddress, netList]; <<>> netAddress _ IF netAddress#NIL THEN Rope.Cat[netAddress, " ", tNetAddress] ELSE tNetAddress; <> count _ count + 1; IF count > 1 THEN gateway _ TRUE; ENDLOOP; }; ParseAttributeList: PROC []RETURNS [owner, location: Rope.ROPE _ NIL] = { <> << ::= | , >> <> <> <<>> < ::= , and this checks for both forms. --edt>> eol: BOOLEAN _ FALSE; name, value: Rope.ROPE; sloppy: BOOLEAN _ FALSE; <> UNTIL eol DO [name, value, eol] _ ParseAttribute[]; IF name#NIL AND value#NIL AND (NOT Rope.Equal[value, "?"]) THEN { IF Ascii.Upper[name.Fetch[0]]='L THEN location _ value; IF Ascii.Upper[name.Fetch[0]]='O THEN owner _ value; IF (Ascii.Upper[name.Fetch[0]]='S) THEN IF sloppy THEN owner _ value ELSE { sloppy _ TRUE; location _ value } -- hack! hack! (he cried) }; ENDLOOP; }; ParseAttribute: PROC []RETURNS [name, value: Rope.ROPE, eol: BOOLEAN _ FALSE] = { << ::= : " " | | >> <> t: REF TEXT; t _ GetToken[]; IF t[0] = ', THEN t _ GetToken[]; -- this is messy... IF t[0]=Ascii.CR THEN {eol _ TRUE; RETURN}; name _ value _ Rope.FromRefText[t]; t_ GetToken[]; IF t[0]='= OR t[0]=': THEN BEGIN eol _ CheckToken['", '"]; IF eol THEN RETURN; t _ GetToken[]; value _ NIL END ELSE name _ "Some random attribute (location or owner)"; UNTIL t[0]='" OR t[0]=Ascii.CR OR t[0]=', DO value _ IF value#NIL THEN Rope.Cat[value, " ", Rope.FromRefText[t]] ELSE Rope.FromRefText[t]; t _ GetToken[]; ENDLOOP; IF t[0]=Ascii.CR THEN eol _ TRUE; }; ReadFile: PUBLIC PROC [file: Rope.ROPE, proc: PupNet.P, log: IO.STREAM] = { <> name, owner, location, netAddress: Rope.ROPE; gateway, network: BOOLEAN; sillyCount: CARDINAL _ 0; eof _ FALSE; <> inputStream _ FS.StreamOpen[file]; <> UNTIL eof DO [name, owner, location, netAddress, gateway, network] _ ParseLine[]; IF sillyCount = 100 THEN { sillyCount _ 0; log.PutF["+ "]; } ELSE sillyCount _ sillyCount + 1; IF name#NIL THEN proc[name, owner, location, netAddress, gateway, network]; ENDLOOP; <> inputStream.Close[]; }; }.