DIRECTORY Atom, Basics, IO, PhoneMappings USING [ PhoneMap ], Rope USING [Cat, Fetch, Flatten, FromChar, Length, MakeRope, ROPE], ThNet ; WhitePagesImpl: CEDAR PROGRAM IMPORTS Atom, IO, Rope EXPORTS ThNet = { ROPE:TYPE=Rope.ROPE; intelnetPause: ROPE _ "\017"; CR: CHAR = '\n; Blank: CHAR = ' ; -- space endChar: CHAR='\000; HowToDial: PUBLIC PROC[phoneNumber: ROPE, ownExtension: ROPE] RETURNS [whatToDial: ROPE, isLocalExtension: BOOLEAN] = { map: PhoneMappings.PhoneMap _ NARROW[Atom.GetProp[$PhoneMap, $map]]; phoneNumber _ MapNumber[phoneNumber, map, intelnetPause, ownExtension]; RETURN[phoneNumber, phoneNumber.Length[]<6]; }; MapNumber: PROC [from: ROPE, map: PhoneMappings.PhoneMap, a1: ROPE_NIL, a2: ROPE_NIL] RETURNS [to: ROPE] = { mapStream: IO.STREAM _ NIL; fromStream: IO.STREAM _ NIL; toStream: IO.STREAM _ NIL; repStream: IO.STREAM _ NIL; mc: CHAR _ 'n; changed: BOOL_FALSE; to _ from; FOR nextMap: PhoneMappings.PhoneMap _ map, nextMap.rest WHILE nextMap #NIL DO mapStream _ IO.RIS[nextMap.first.pattern, mapStream]; repStream _ IO.RIS[nextMap.first.replacement, repStream]; fromStream _ IO.RIS[to, fromStream]; toStream _ IO.ROS[toStream]; toStream.Reset[]; WHILE TRUE DO fc: CHAR; mc _ IF mapStream.EndOf[] THEN endChar ELSE mapStream.GetChar[]; IF mc=Blank THEN LOOP; fc _ NextNonBlank[fromStream]; SELECT mc FROM Blank, CR => LOOP; 'n, 'x, 'y => IF fc#endChar THEN { IF CopyLiterals[toStream, repStream, mc, a1, a2] THEN toStream.PutChar[fc]} ELSE EXIT; 'z => IF changed THEN EXIT ELSE IF fc=endChar THEN GOTO matched ELSE toStream.PutChar[fc]; -- Plain copy! endChar => IF fc#endChar THEN EXIT ELSE GOTO matched; ENDCASE => IF fc#mc THEN EXIT; REPEAT matched => { IF mc#'z AND CopyLiterals[toStream, repStream, 'n, a1, a2] THEN ERROR; -- replacement out of synch to _ IO.RopeFromROS[toStream]; changed _ TRUE; }; ENDLOOP; ENDLOOP; mapStream.Close[]; fromStream.Close[]; toStream.Close[]; repStream.Close[]; }; NextNonBlank: PROC[s: IO.STREAM] RETURNS [c: CHAR] = { WHILE ~s.EndOf[] DO SELECT (c_s.GetChar[]) FROM IN ['0..'9] => RETURN; ENDCASE; ENDLOOP; RETURN[endChar]; }; CopyLiterals: PROC[to, from: IO.STREAM, patternChar: CHAR, arg1: ROPE, arg2: ROPE] RETURNS[needAChar: BOOL] = { c: CHAR; WHILE ~from.EndOf[] DO SELECT (c_from.GetChar[]) FROM 'n, 'x, 'y => { IF c=patternChar THEN RETURN[TRUE]; from.Backup[c]; RETURN[FALSE]; }; 'A => to.PutRope[arg1]; 'B => to.PutRope[arg2]; ENDCASE => to.PutChar[c]; ENDLOOP; RETURN[FALSE]; }; FeepName: PUBLIC PROC[rName: ROPE] RETURNS[feepName: ROPE] = { qdCheck: CARDINAL_0; FeepFetch: PROC[data: REF, index: INT] RETURNS [c: CHAR] = { c_NARROW[data, ROPE].Fetch[index]; IF c IN ['A..'Z] THEN c_c+('a-'A); qdCheck _ qdCheck+LOOPHOLE[c, [0..256)]; IF c NOT IN ['a..'z] THEN c_'z+1; RETURN[FeepMap[c]]; }; feepName _ Rope.MakeRope[base: rName, size: rName.Length[], fetch: FeepFetch]; feepName _ Rope.Flatten[feepName]; feepName _ Rope.Cat[feepName, Rope.FromChar[LOOPHOLE[LOOPHOLE[qdCheck, Basics.BytePair].high, CHAR]], Rope.FromChar[LOOPHOLE[LOOPHOLE[qdCheck, Basics.BytePair].low, CHAR]] ]; }; FeepMap: PACKED ARRAY CHAR['a..'z+1] OF CHAR = [ '2, '2, '2, '3, '3, '3, '4, '4, '4, '5, '5, '5, '6, '6, '6, '7, '7, '7, '7, '8, '8, '8, '9, '9, '9, '9, '1 ]; }. ΰWhitePagesImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last modified by Swinehart, May 22, 1986 10:58:57 am PDT Last modified by Stewart, June 20, 1983 11:21 am Last Edited by: Lia, July 26, 1983 6:17 pm Maps phone number patterns according to local conventions, as represented in the "map" list. This string is a list of lines, each line representing a pattern match and substitution. MapNumber goes through the sequence once. For each line, the left hand side is matched with the current phone number. If it matches, the right hand side is substituted for the current phone number (wild cards are replaced by the input characters they matched). An example of a line is "408nnnnnnn = 9,408nnnnnnn". It says, "to dial something in the 408 area code, dial 9 for an outside line, pause a second, then dial 408 and the local number." Put the unlikely pair ["zzzzzzzzzzzzzzzzzzz", "z"] at the end of the map list to be sure that the result has had punctuation stripped from it. (Otherwise an input that has not been converted for other reasons will still have punctuation in it!) Don't put any 'z characters anywhere else. Swinehart, May 22, 1986 10:56:04 am PDT Cedar 6.1 changes to: DIRECTORY, WhitePagesImpl Κ™˜šœ™Icodešœ Οmœ1™Jšœ žœ˜š   œžœžœ žœžœžœ˜