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] ~ { break: IO.BreakProc = { 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] ~ { 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] ~ { 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] ~ { 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] = { 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] = { 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[]; }; }. dPupNetImpl.mesa -- Gifford, July 19, 1985 3:25:05 pm PDT -- This program parses pup-network.txt, extracting host names, owners, and locations Donahue, May 21, 1986 11:31:37 am PDT Ewan Tempero August 25, 1986 3:42:56 pm PDT get an input token check to see if next token is either c1 or c2 skip to the end of the line ... returns the next symbolic net name found in stream. [char: CHAR] RETURNS [IO.CharClass] ...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. ... looks at netAddress and determines the net value. ... finds the occurance of name in list and returns the corresponding value. 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: ::= =
; ::= | , ::= * | Precondition: Stream at beginning of name list Postcondition: Stream positioned at beginning of address list Postcondition: If name found, name#NIL
::=
|
,
::= | ::= | + ::= |
::= | # | # # ::= | empty Precondition: Stream positioned at beginning of address list. AND ALL NETWORKS are listed before anything else. I think this is probably reasonable --edt. 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 see if a socket not a socket id. see if a network if the address ends in "##", then it is a network A little hack to make sure that none of the "+"s that the maintainers of this file seem to love are still in the net address ( there should be only 1 and will only be in non-network machines ). if there is more than one address, then the host is a gateway 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. People now tend to use something of the form ::= , and this checks for both forms. --edt Examine each attribute until we get to the end of line ::= : " " | | precondition seems to be start is at after the ";" --edt. reads a file and calls proc open the input stream now read the entire file at end of file Κ ¬˜šœ™Icode™%K™+—J˜šΟk ˜ J˜Jšœœ˜+Jšœ˜Jšœ˜J˜J˜—J˜šΟn œœ˜Jšœœœ˜$Jšœ ˜J˜Jš œœœœœ˜"J˜Jšœœ˜ J˜Jšœ œœœΟc˜0J˜Kšžœœœ˜K˜šœ œœ˜Kšœ œœ˜Kšœœ˜K˜—K˜Kšœ œœ ˜K˜Kšœ œœ œ˜K˜šœ œ˜šœ˜Jšœœ œœœ œ œœ˜[Jšœœœœ˜ 2œ*™šJšœ™Jšœ&™&Jšœ&™&Jšœ=™=Jšœ+™+Jšœ6™6Jšœœ˜Jšœœ˜ Jšœœœ˜ Jšœœ˜šœœ˜ J˜Kšœ œ˜!K˜šœ˜Jšœœ œœ˜!Jšœ˜ Jšœ˜—Jšœ™šœœ˜Jšœ œ˜Jšœœ˜ J˜ Jšœ˜J˜—Jšœ"™"Jšœœœ˜J˜Jšœ"˜"J™Jšœ1™1šœœœ˜/Jšœ œ˜Jšœ œœF˜XJšœ˜J˜—J™ΑKšœ*œM˜}J˜Kšœœ œ7˜JJ™šœ œ œœ˜$Jšœ&˜&Jšœ ˜J˜—Jšœ=™=J˜Jšœ œ œ˜!Jšœ˜Jšœ˜—J˜—J˜š žœœœœœ˜IJšœ-™-JšœA™AJ˜Jšœ@™@Jšœ"™"J™Jšœ™Jšœœœ˜Jšœœ˜Jšœœœ˜Jšœ7™7šœ˜ J˜&šœœœœœœœ˜BJšœœ˜7Jšœœ˜4šœ!˜'Kš œœœ œŸ˜_—J˜—Jšœ˜—J˜—J˜š žœœœœœœ˜QJšœV™VJ™9Jšœœœ˜ J˜Kšœ œŸ˜5Jš œ œœœœ˜+J˜J˜#J˜šœ œ ˜š˜J˜Jšœœœ˜J˜Jšœ˜ —Jš˜—šœ4˜8K˜—š œ œ œœ ˜,šœœœœ˜J˜)Jšœ˜—J˜Jšœ˜—Jšœ œœœ˜!J˜—J˜š žœœœ œœœ˜KJšœ™Jšœ(œ˜-Jšœœ˜Jšœ œ˜Jšœœ˜ Jšœ™Jšœœ˜"Jšœ™šœ˜ J˜Dšœœ˜Kšœ˜Kšœ Οsœ˜K˜—Kšœ˜!Kšœœœ;˜KJšœ˜—Jšœ™J˜J˜J˜——J˜—…—X/h