ArpaNameSupportImpl:
CEDAR
PROGRAM
IMPORTS Ascii, IO, Rope
EXPORTS ArpaNameSupport =
BEGIN
ROPE: TYPE = Rope.ROPE;
AddressInList:
PUBLIC
PROC [addresses:
LIST
OF Arpa.Address, address: Arpa.Address]
RETURNS [yes: BOOL] = {
FOR list:
LIST
OF Arpa.Address ← addresses, list.rest
UNTIL list =
NIL
DO
IF list.first = address THEN RETURN [TRUE];
ENDLOOP;
RETURN[FALSE]; };
CountAddresses:
PUBLIC PROC [addresses:
LIST
OF Arpa.Address]
RETURNS [count:
INT𡤀] = {
FOR list:
LIST
OF Arpa.Address ← addresses, list.rest
UNTIL list =
NIL
DO
count ← count +1;
ENDLOOP;
};
AppendUniqueAddress:
PUBLIC
PROC [address: Arpa.Address, addresses:
LIST
OF Arpa.Address ←
NIL]
RETURNS [new: LIST OF Arpa.Address] = {
IF addresses = NIL THEN RETURN[LIST[address]];
new ← addresses;
DO
IF addresses.first = address THEN RETURN;
IF addresses.rest = NIL THEN { addresses.rest ← LIST[address]; RETURN; };
addresses ← addresses.rest;
ENDLOOP; };
AppendUniqueRope:
PUBLIC
PROC [ropes:
LIST
OF
ROPE, name:
ROPE]
RETURNS [new: LIST OF ROPE] = {
IF ropes = NIL THEN RETURN[LIST[name]];
new ← ropes;
DO
IF Rope.Equal[ropes.first, name, FALSE] THEN RETURN;
IF ropes.rest = NIL THEN { ropes.rest ← LIST[name]; RETURN; };
ropes ← ropes.rest;
ENDLOOP; };
AddressToRope:
PUBLIC
PROC [address: Arpa.Address, brackets:
BOOL ←
TRUE]
RETURNS [rope: Rope.
ROPE] = {
rope ←
IO.PutFR["%g.%g.%g.%g",
[cardinal[address.a]], [cardinal[address.b]], [cardinal[address.c]], [cardinal[address.d]]];
IF brackets THEN rope ← Rope.Cat["[", rope, "]"];
};
IsAddressRope:
PUBLIC PROC [rope:
ROPE]
RETURNS [
BOOL] = {
firstChar: CHAR;
length: INT ← Rope.Length[rope];
IF Rope.IsEmpty[rope] THEN RETURN[FALSE];
firstChar ← Rope.Fetch[rope, 0];
IF length > 2 AND (firstChar = '[ OR Ascii.Digit[firstChar]) THEN RETURN[TRUE];
RETURN[FALSE];};
AddressRopeToQueryRope:
PUBLIC PROC [addrRope:
ROPE]
RETURNS [queryRope:
ROPE] = {
addr: Arpa.Address ← RopeToAddress[addrRope];
IF ~IsAddressRope[addrRope] THEN RETURN[NIL];
addr ← RopeToAddress[addrRope];
IF addr = Arpa.nullAddress THEN RETURN[NIL];
queryRope ← AddressToQueryRope[addr];
};
AddressToQueryRope:
PUBLIC PROC [addr: Arpa.Address]
RETURNS [queryRope:
ROPE] = {
queryRope ← IO.PutFR["%G.%G.%G.%G.IN-ADDR.ARPA", [integer[addr.d]], [integer[addr.c]], [integer[addr.b]], [integer[addr.a]]];
};
StripBrackets:
PUBLIC PROC [inRope:
ROPE]
RETURNS [outRope:
ROPE] = {
firstChar: CHAR;
length: INT ← Rope.Length[inRope];
IF Rope.IsEmpty[inRope] THEN RETURN[NIL];
firstChar ← Rope.Fetch[inRope, 0];
IF length > 2 AND firstChar = '[ THEN outRope ← Rope.Substr[inRope, 1, length-2]
ELSE outRope ← inRope;
};
RopeToAddress:
PUBLIC PROC [rope:
ROPE]
RETURNS [address: Arpa.Address𡤊rpa.nullAddress] = {
len: CARDINAL;
i: CARDINAL ← 0;
AtEnd: PROC RETURNS [BOOL] ~ INLINE { RETURN [i >= len] };
GetChar: PROC RETURNS [c: CHAR] ~ INLINE { c ← Rope.InlineFetch[rope, i]; i ← i + 1 };
Skip: PROC [c: CHAR] ~ INLINE { IF (i < len) AND (Rope.InlineFetch[rope, i] = c) THEN i ← i + 1 };
AToI:
PROC
RETURNS [n:
CARDINAL ← 0] ~ {
DO
c: CHAR;
IF AtEnd[] THEN RETURN;
IF NOT Ascii.Digit[c ← GetChar[]] THEN RETURN;
n ← n * 10 + (c - '0);
ENDLOOP;
};
IF rope = NIL THEN RETURN[Arpa.nullAddress];
len ← Rope.Length[rope];
Skip['[]; IF AtEnd[] THEN RETURN[Arpa.nullAddress];
address.a ← AToI[];
Skip['.]; IF AtEnd[] THEN RETURN[Arpa.nullAddress];
address.b ← AToI[];
Skip['.]; IF AtEnd[] THEN RETURN[Arpa.nullAddress];
address.c ← AToI[];
Skip['.]; IF AtEnd[] THEN RETURN[Arpa.nullAddress];
address.d ← AToI[];
RETURN[address];
};
Tailed:
PUBLIC PROC [body, tail:
ROPE]
RETURNS [match:
BOOL] = {
bodyLength: INT = Rope.Length[body];
tailLength: INT = Rope.Length[tail];
back: ROPE;
IF bodyLength <= tailLength THEN RETURN[FALSE];
back ← Rope.Substr[body, bodyLength-tailLength, tailLength];
IF ~Rope.Equal[back, tail, FALSE] THEN RETURN[FALSE];
RETURN[TRUE]; };
StripTail:
PUBLIC PROC [body, tail:
ROPE]
RETURNS [new:
ROPE] = {
bodyLength: INT = body.Length[];
tailLength: INT = tail.Length[];
RETURN[Rope.Substr[body, 0, bodyLength - tailLength]]};
END.