<> <> <> <> <> 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 _ "\017P"; 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 ]; }.