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 ]; }. lWhitePagesImpl.mesa Interface to "Callup" databases Last modified by Swinehart, April 29, 1986 6:00:33 pm 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. Êw˜Jšœ™Jšœ™Jšœ9™9Jšœ0™0J™*šÏk ˜ J˜J˜Jšœ˜Jšœœ˜!Jšœœ3œ˜CJ˜J˜J˜—šœœ˜Jšœœ˜Jšœ ˜J˜Jšœœœ˜Jšœœ ˜Jšœœ˜JšœœœÏc˜Jšœ œ˜J˜š Ïn œœœœœ˜=Jšœœœ˜9Jšœœ ˜DJšœG˜GJšœ&˜,J˜—J˜šŸ œœœ#œœœœ˜UJšœœ˜Jšœ¸Ÿ œ¸™ùJ™ Jšœ œœœ˜Jšœ œœœ˜Jšœ œœœ˜Jšœ œœœ˜Jšœœ˜Jšœ œœ˜J˜ šœ5œ œ˜MJšœ œœ#˜5Jšœ œœ'˜9Jšœ œœ˜$Jšœ œœ˜.šœœ˜ Jšœœ˜ Jšœœœ œ˜@Jšœ œœ˜Jšœ˜šœ˜Jšœœœ˜šœœ ˜ Jš œœ/œœœ˜X—šœœ œ˜Jš œœ œœ œž˜N—Jš œ œ œœœœ ˜5Jšœœœœ˜—š˜˜ Jš œœ/œœž˜bJšœœ˜Jšœ œ˜J˜——Jšœ˜—Jšœ˜—JšœK˜KJ˜—˜š Ÿ œœœœœœ˜6šœ ˜šœ˜Jšœ œ˜Jšœ˜—Jšœ˜—Jšœ ˜J˜J˜—šŸ œœ œœœœœ˜RJšœ œ˜Jšœœ˜šœ˜šœ˜˜Jšœœœœ˜#J˜Jšœœ˜J˜—J˜J˜Jšœ˜—Jšœ˜—Jšœœ˜J˜J˜——š Ÿœœœœœ œ˜>Jšœ œ˜š Ÿ œœœ œœœ˜