-- PupNetImpl.mesa -- Gifford, July 19, 1985 3:25:05 pm PDT -- This program parses pup-network.txt, extracting host names, owners, and locations DIRECTORY Ascii, FS, IO, PupNet, Rope; PupNetImpl: CEDAR PROGRAM IMPORTS Ascii, FS, IO, Rope EXPORTS PupNet = { buffer: REF TEXT _ NEW[TEXT[100]]; eof: BOOLEAN; inputStream: IO.STREAM _ NIL; -- Input IO sream 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] = { -- get an input token 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] = { -- check to see if next token is either c1 or c2 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 [] = { -- skip to the end of the line WHILE GetToken[].token[0] # Ascii.CR DO ENDLOOP; }; ParseLine: PROC [] RETURNS [name, owner, location: Rope.ROPE _ NIL, gateway, network: BOOLEAN _ FALSE] = { -- Parses a single line of the input file -- Precondition: Stream pointer at beginning of line -- Postcondition: Stream pointer at beginning of next line -- Grammar of an input line: -- ::= =
; eol, socket: BOOLEAN _ FALSE; [name, eol] _ ParseNameList[]; IF eol THEN RETURN; [network,gateway,socket, eol] _ ParseAddressList[]; IF socket THEN RETURN[NIL, NIL, NIL, FALSE, FALSE]; IF eol THEN RETURN; [owner, location] _ ParseAttributeList[]; }; ParseNameList: PROC [] RETURNS [name: Rope.ROPE _ NIL, eol: BOOLEAN _ FALSE] = { -- ::= | , -- ::= * | -- Precondition: Stream at beginning of name list -- Postcondition: Stream positioned at beginning of address list -- Postcondition: If name found, name#NIL 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 _ Rope.FromRefText[t]; ENDCASE; ENDLOOP; }; ParseAddressList: PROC [] RETURNS [network, gateway, socket, eol: BOOLEAN _ FALSE] = { --
::=
|
,
--
::= | -- ::= | + -- ::= |
--
::= | # | -- # # -- ::= | empty -- Precondition: Stream positioned at beginning of address list -- Postconditions: -- network is T if the entry is a network -- gateway is T if the entry is a gateway -- socket is T if the entry is a socket id and should be ignored -- eol is T if we have hit the end of the line -- Input Stream positioned at beginning of attribute list count: INT _ 0; t: REF TEXT; WHILE TRUE DO t _ GetToken[]; SELECT t[0] FROM Ascii.CR => {eol _ TRUE; RETURN}; '; => RETURN ENDCASE; -- see if a socket IF t[t.length-1]#'# THEN { socket _ TRUE; eol _ TRUE; SkipToEOL[]; RETURN; }; -- not a socket id. see if a network IF t.length < 2 THEN LOOP; -- if the address ends in "##", then it is a network IF t[t.length-1]='# AND t[t.length-2]='# THEN {network _ TRUE; LOOP}; -- if there is more than one address, then the host is a gateway count _ count + 1; IF count > 1 THEN gateway _ TRUE; ENDLOOP; }; ParseAttributeList: PROC [] RETURNS [owner, location: Rope.ROPE _ NIL] = { -- The grammar for an attribute list USED TO BE: -- ::= | , -- Unfortunately, because this part of pup-network.txt is no longer -- parsed, people have become sloppy. eol: BOOLEAN _ FALSE; name, value: Rope.ROPE; -- Examine each attribute until we get to the end of line 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; }; ENDLOOP; }; ParseAttribute: PROC [] RETURNS [name, value: Rope.ROPE, eol: BOOLEAN _ FALSE] = { -- ::= : " " t: REF TEXT; t _ GetToken[]; IF t[0]=Ascii.CR THEN {eol _ TRUE; RETURN}; name _ Rope.FromRefText[t]; eol _ CheckToken[':, '=]; IF eol THEN RETURN; eol _ CheckToken['", '"]; IF eol THEN RETURN; t _ GetToken[]; UNTIL t[0]='" OR t[0]=Ascii.CR 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] = { -- reads a file and calls proc name, owner, location: Rope.ROPE; gateway, network: BOOLEAN; eof _ FALSE; -- open the input stream inputStream _ FS.StreamOpen[file]; -- now read the entire file UNTIL eof DO [name, owner, location, gateway, network] _ ParseLine[]; IF name#NIL THEN proc[name, owner, location, gateway, network]; ENDLOOP; -- at end of file inputStream.Close[]; }; }.