-- Copyright (C) 1984, 1985, 1986 by Xerox Corporation. All rights reserved.
-- NameAndAddressTool.mesa, WIrish, 9-Jan-87 10:08:05
-- From: NameLookupTool.mesa
-- Please don't forget to update the herald....
DIRECTORY
AddressTranslation USING [Error, ErrorRecord, StringToNetworkAddress],
Format USING [NetworkAddress, HostNumber, StringProc],
FormSW USING [
ClientItemsProcType, ProcType, AllocateItemDescriptor, newLine, CommandItem,
StringItem],
Heap USING [systemZone],
MsgSW USING [Post],
Put USING [Char, CR, Text, Line, LongDecimal],
Selection USING [Convert],
String USING [AppendChar, AppendNumber, AppendString, Copy, FreeString, InvalidNumber, Length, StringToDecimal, WordsForString],
System USING [NetworkAddress],
Time USING [AppendCurrent],
Tool USING [
Create, MakeSWsProc, MakeMsgSW, MakeFormSW, MakeFileSW, UnusedLogName],
ToolWindow USING [TransitionProcType],
Window USING [Handle],
Buffer USING [AccessHandle, DestroyPool, GetBuffer, MakePool, ReturnBuffer],
NameServerDefs USING [
nameStatsRequest, nameStatsReply, NameStatsEntry,
nameToCacheRequest, addressToCacheRequest, hereIsCacheEntry],
PupWireFormat USING [BcplToMesaLongNumber],
PupDefs USING [
PupPackageMake, PupPackageDestroy,
PupBuffer, PupSocket, PupSocketDestroy, PupSocketMake, SecondsToTocks,
GetPupContentsBytes, SetPupContentsWords, MoveStringBodyToPupBuffer,
AppendPupAddress, AppendErrorPup, GetPupAddress, PupNameTrouble],
PupTypes USING [PupAddress, fillInNetID, fillInSocketID, allHosts, miscSrvSoc];
NameAndAddressTool: PROGRAM
IMPORTS AddressTranslation, Format, FormSW, Heap, MsgSW, Put, Selection, String, Time, Tool, Buffer, PupWireFormat, PupDefs
=
BEGIN OPEN PupDefs, PupTypes;
z: UNCOUNTED ZONE = Heap.systemZone;
msg, form, log: Window.Handle;
data: LONG POINTER TO Data ← NIL;
Data: TYPE = RECORD [
where: PupAddress,
target: LONG STRING,
name: LONG STRING,
address: LONG STRING,
pupOrTcp: LONG STRING];
Stats: FormSW.ProcType =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
hit: BOOLEAN ← FALSE;
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" Pup Name Server Statistics "L];
IF ~FindPath[] THEN RETURN;
pool ← Buffer.MakePool[send: 1, receive: 2];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← NameServerDefs.nameStatsRequest;
b.pup.pupID ← [0, 0];
b.pup.pupWords[0] ← 0;
SetPupContentsWords[b, 0];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
NameServerDefs.nameStatsReply =>
BEGIN
nse: LONG POINTER TO NameServerDefs.NameStatsEntry;
hit ← TRUE;
nse ← LOOPHOLE[@b.pup.pupWords];
PrintInfo[
"Requests"L, PupWireFormat.BcplToMesaLongNumber[nse.nameRequests]];
PrintInfo[
"Directories sent"L, PupWireFormat.BcplToMesaLongNumber[
nse.directoriesSend]];
PrintInfo[
"Cache hits"L, PupWireFormat.BcplToMesaLongNumber[nse.cacheHits]];
PrintInfo[
"Cache misses"L, PupWireFormat.BcplToMesaLongNumber[
nse.cacheMisses]];
END;
ENDCASE => PrintErrorPup[b];
WriteCR[];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
END;
Version: FormSW.ProcType =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
hit: BOOLEAN ← FALSE;
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" Pup Network Directory Version "L];
IF ~FindPath[] THEN RETURN;
pool ← Buffer.MakePool[send: 1, receive: 2];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← netDirVersion;
b.pup.pupID ← [0, 0];
b.pup.pupWords[0] ← 0;
SetPupContentsWords[b, 1];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
netDirVersion =>
BEGIN
hit ← TRUE;
WriteString["Pup-network.directory version is "L];
WriteDecimal[b.pup.pupWords[0]];
IF GetPupContentsBytes[b] > 2 THEN
BEGIN
WriteLine["."L];
WriteString["Pup-network.big version is "L];
WriteDecimal[b.pup.pupWords[1]];
END;
END;
ENDCASE => PrintErrorPup[b];
WriteLine["."L];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
END;
NameToAddress: FormSW.ProcType =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
hit: BOOLEAN ← FALSE;
IF data.name = NIL OR data.name.length = 0 THEN
BEGIN MsgSW.Post[msg, "Name needed"L]; RETURN; END;
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" Name=>Address "L];
IF ~FindPath[] THEN RETURN;
pool ← Buffer.MakePool[send: 1, receive: 2];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← nameLookup;
MoveStringBodyToPupBuffer[b, data.name];
b.pup.pupID ← [0, 0];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
nameIs =>
BEGIN
i, n: CARDINAL;
addresses: LONG POINTER TO ARRAY [0..0) OF PupAddress ←
LOOPHOLE[@b.pup.pupBody];
hit ← TRUE;
WriteString[data.name];
WriteString[" => "L];
n ← GetPupContentsBytes[b]/(2*SIZE[PupAddress]);
FOR i IN [0..n) DO
IF i # 0 THEN WriteString[", "L];
PrintPupAddress[@addresses[i]];
ENDLOOP;
END;
nameError =>
BEGIN
hit ← TRUE;
WriteString[data.name];
WriteString[" => ERROR: "L];
PrintBodyAsText[b];
END;
ENDCASE => PrintErrorPup[b];
WriteCR[];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
END;
NameToCache: FormSW.ProcType =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
hit: BOOLEAN ← FALSE;
IF data.name = NIL OR data.name.length = 0 THEN
BEGIN MsgSW.Post[msg, "Name needed"L]; RETURN; END;
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" Name=>CacheEntry "L];
IF ~FindPath[] THEN RETURN;
pool ← Buffer.MakePool[send: 1, receive: 2];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← NameServerDefs.nameToCacheRequest;
MoveStringBodyToPupBuffer[b, data.name];
b.pup.pupID ← [0, 0];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
NameServerDefs.hereIsCacheEntry =>
BEGIN
hit ← TRUE;
PrintCacheEntry[b];
END;
nameError =>
BEGIN
hit ← TRUE;
WriteString[data.name];
WriteString[" => ERROR: "L];
PrintBodyAsText[b];
END;
ENDCASE => PrintErrorPup[b];
WriteCR[];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
END;
AddressToName: FormSW.ProcType =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
a: PupAddress ← [, , [0, 0]];
hit: BOOLEAN ← FALSE;
IF data.address = NIL OR data.address.length = 0 THEN
BEGIN MsgSW.Post[msg, "Address needed"L]; RETURN; END;
GetPupAddress[
@a, data.address !
PupNameTrouble =>
BEGIN MsgSW.Post[msg, e]; WriteLine[e]; GOTO Trouble; END];
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" Address=>Name "L];
IF ~FindPath[] THEN RETURN;
pool ← Buffer.MakePool[send: 1, receive: 10];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← addressLookup;
b.pup.pupID ← [0, 0];
b.pup.address ← a;
SetPupContentsWords[b, SIZE[PupAddress]];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
addressIs =>
BEGIN
hit ← TRUE;
WriteString[data.address];
WriteString[" => "L];
PrintBodyAsText[b];
END;
nameError =>
BEGIN
hit ← TRUE;
WriteString[data.address];
WriteString[" => ERROR: "L];
PrintBodyAsText[b];
END;
ENDCASE => PrintErrorPup[b];
WriteLine["."L];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
EXITS Trouble => NULL;
END;
AddressToCache: FormSW.ProcType =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
a: PupAddress ← [, , [0, 0]];
hit: BOOLEAN ← FALSE;
IF data.address = NIL OR data.address.length = 0 THEN
BEGIN MsgSW.Post[msg, "Address needed"L]; RETURN; END;
GetPupAddress[
@a, data.address !
PupNameTrouble =>
BEGIN MsgSW.Post[msg, e]; WriteLine[e]; GOTO Trouble; END];
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" Address=>CacheEntry "L];
IF ~FindPath[] THEN RETURN;
pool ← Buffer.MakePool[send: 1, receive: 2];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← NameServerDefs.addressToCacheRequest;
b.pup.pupID ← [0, 0];
b.pup.address ← a;
SetPupContentsWords[b, SIZE[PupAddress]];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
NameServerDefs.hereIsCacheEntry =>
BEGIN
hit ← TRUE;
PrintCacheEntry[b];
END;
nameError =>
BEGIN
hit ← TRUE;
WriteString[data.address];
WriteString[" => ERROR: "L];
PrintBodyAsText[b];
END;
ENDCASE => PrintErrorPup[b];
WriteLine["."L];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
EXITS Trouble => NULL;
END;
XeroxClassA: CARDINAL = 13;
PupToTcp: FormSW.ProcType =
BEGIN
a: PupAddress ← [, , [0, 0]];
hit: BOOLEAN ← FALSE;
IF data.pupOrTcp = NIL OR data.pupOrTcp.length = 0 THEN
BEGIN MsgSW.Post[msg, "Conversion value needed"L]; RETURN; END;
GetPupAddress[
@a, data.pupOrTcp !
PupNameTrouble =>
BEGIN MsgSW.Post[msg, e]; WriteLine[e]; GOTO Trouble; END];
WriteCR[];
WriteCurrentDateAndTime[];
WriteLine[" PUP=>TCP"L];
WriteString[data.pupOrTcp];
WriteString[" => "L];
PrintPupAddress[@a];
WriteString[" => "L];
WriteDecimal[XeroxClassA];
WriteChar['.];
WriteDecimal[a.net/100B];
WriteChar['.];
WriteDecimal[(a.net MOD 100B)*4];
WriteChar['.];
WriteDecimal[a.host];
WriteCR[];
EXITS Trouble => NULL;
END;
TcpToPup: FormSW.ProcType =
BEGIN
tempString: STRING = [50];
numberString: STRING = [20];
tcp: ARRAY [0..4) OF CARDINAL ← ALL[0];
i: CARDINAL ← 0;
copyNextNumber: PROCEDURE =
BEGIN
j: CARDINAL ← 1;
String.Copy[numberString, "0"L];
-- skip over junk
WHILE (i < String.Length[tempString])
AND ((tempString.text[i] < '0)
OR (tempString.text[i] > '9)) DO
i ← i + 1;
ENDLOOP;
-- copy over number
WHILE (i < String.Length[tempString])
AND (tempString.text[i] >= '0)
AND (tempString.text[i] <= '9) DO
String.AppendChar[numberString, tempString.text[i]];
i ← i + 1;
j ← j + 1;
ENDLOOP;
END;
String.Copy[tempString, data.pupOrTcp];
WriteCR[];
WriteCurrentDateAndTime[];
WriteLine[" TCP=>PUP"L];
WriteString[tempString];
WriteString[" => "L];
FOR j: CARDINAL IN [0..4) DO
copyNextNumber[];
tcp[j] ← String.StringToDecimal[numberString !
String.InvalidNumber => {tcp[j] ← 0; CONTINUE;}];
WriteDecimal[tcp[j]];
IF j < 3 THEN WriteChar['.];
ENDLOOP;
WriteString[" => "L];
IF tcp[0] # XeroxClassA THEN
BEGIN
WriteLine["Error: XEROX-NET is 013.rrr.rrr.rrr!"L];
RETURN;
END;
WriteOctal[tcp[1]*100B + tcp[2]/4];
WriteChar['#];
WriteOctal[tcp[3] + (tcp[2] MOD 4)*400B];
WriteChar['#];
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
a: PupAddress ← [, , [0, 0]];
hit: BOOLEAN ← FALSE;
a.net ← LOOPHOLE[tcp[1]*100B + tcp[2]/4];
a.host ← LOOPHOLE[tcp[3] + (tcp[2] MOD 4)*400B];
WriteString[" => "L];
IF ~SilentFindPath[] THEN
BEGIN
WriteString["Not PUP Registered"L];
RETURN;
END;
pool ← Buffer.MakePool[send: 1, receive: 10];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← addressLookup;
b.pup.pupID ← [0, 0];
b.pup.address ← a;
SetPupContentsWords[b, SIZE[PupAddress]];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL DO
IF data.where # b.pup.source THEN
BEGIN
WriteString["Reply from: "L];
PrintPupAddress[@b.pup.source];
WriteCR[];
END;
SELECT b.pup.pupType FROM
addressIs =>
BEGIN
hit ← TRUE;
PrintBodyAsText[b];
END;
nameError =>
BEGIN
hit ← TRUE;
WriteString[data.address];
WriteString[" Not found."L];
END;
ENDCASE => PrintErrorPup[b];
WriteCR[];
Buffer.ReturnBuffer[b];
ENDLOOP;
IF ~hit THEN MsgSW.Post[msg, "No Response that try."L];
ENDLOOP;
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
END;
END;
AllNSFormats: FormSW.ProcType =
BEGIN
address: System.NetworkAddress;
source: LONG STRING;
scratch: LONG STRING = [250];
stringProc: Format.StringProc = {String.AppendString[scratch, s]};
IF data.pupOrTcp # NIL
AND data.pupOrTcp.length > 0
AND data.pupOrTcp.length < scratch.maxlength
THEN String.Copy[scratch, data.pupOrTcp]
ELSE BEGIN
source ← Selection.Convert[string];
IF source # NIL THEN
BEGIN
String.Copy[scratch, source];
String.FreeString[z, source];
END;
END;
IF scratch = NIL OR scratch.length = 0 THEN
BEGIN MsgSW.Post[msg, "Conversion value needed"L]; RETURN; END;
WriteCR[];
WriteCurrentDateAndTime[];
WriteString[" NS Formats for: "L];
WriteLine[scratch];
address ← AddressTranslation.StringToNetworkAddress[scratch !
AddressTranslation.Error =>
WITH e: errorRecord SELECT FROM
scanError, badSyntax =>
{WriteLine["Unable to parse."L];
GOTO failure};
chLookupProblem, otherCHProblem =>
{WriteLine["Clearinghouse lookup problem."L];
GOTO failure};
ENDCASE].addr;
scratch.length ← 0;
Format.NetworkAddress[stringProc, address, productSoftware];
String.AppendString[scratch, " == "L];
Format.NetworkAddress[stringProc, address, octal];
String.AppendString[scratch, " == "L];
Format.NetworkAddress[stringProc, address, hex];
WriteLine[scratch];
scratch.length ← 0;
Format.HostNumber[stringProc, address.host, octal];
LookupNameAndPrintCacheEntryIfFound[scratch];
EXITS failure => NULL;
END;
LookupNameAndPrintCacheEntryIfFound: PROCEDURE [name: LONG STRING] =
BEGIN
pool: Buffer.AccessHandle;
soc: PupSocket;
b: PupBuffer;
hit: BOOLEAN ← FALSE;
IF name = NIL OR name.length = 0 THEN RETURN;
WriteString["PUP entry: "L];
data.where ← [fillInNetID, allHosts, miscSrvSoc];
pool ← Buffer.MakePool[send: 1, receive: 2];
soc ← PupSocketMake[PupTypes.fillInSocketID, data.where, SecondsToTocks[2]];
THROUGH [0..10) UNTIL hit DO
b ← Buffer.GetBuffer[pup, pool, send];
b.pup.pupType ← NameServerDefs.nameToCacheRequest;
MoveStringBodyToPupBuffer[b, name];
b.pup.pupID ← [0, 0];
soc.put[b];
UNTIL (b ← soc.get[]) = NIL OR hit DO
SELECT b.pup.pupType FROM
NameServerDefs.hereIsCacheEntry =>
BEGIN
hit ← TRUE;
PrintCacheEntry[b];
WriteCR[];
END;
nameError =>
BEGIN
hit ← TRUE;
WriteLine["no luck."L];
END;
ENDCASE => NULL;
Buffer.ReturnBuffer[b];
ENDLOOP;
ENDLOOP;
IF ~hit THEN WriteLine["not found."L];
PupSocketDestroy[soc];
Buffer.DestroyPool[pool];
END;
FindPath: PROCEDURE RETURNS [BOOLEAN] =
BEGIN OPEN data;
data.where ← [fillInNetID, allHosts, miscSrvSoc];
IF data.target = NIL OR data.target.length = 0 THEN
BEGIN WriteLine["via broadcasting on local net(s)."L]; RETURN[TRUE]; END
ELSE BEGIN WriteString["from "L]; END;
WriteString[target];
WriteChar['=];
GetPupAddress[
@where, target !
PupNameTrouble =>
BEGIN MsgSW.Post[msg, e]; WriteLine[e]; GOTO Trouble; END];
PrintPupAddress[@where];
WriteLine["."L];
RETURN[TRUE];
EXITS Trouble => RETURN[FALSE];
END;
SilentFindPath: PROCEDURE RETURNS [BOOLEAN] =
BEGIN OPEN data;
data.where ← [fillInNetID, allHosts, miscSrvSoc];
GetPupAddress[
@where, target !
PupNameTrouble =>
BEGIN GOTO Trouble; END];
RETURN[TRUE];
EXITS Trouble => RETURN[FALSE];
END;
-- IO things
WriteChar: PROCEDURE [c: CHARACTER] = BEGIN Put.Char[log, c]; END;
WriteCR: PROCEDURE = BEGIN Put.CR[log]; END;
WriteString: PROCEDURE [s: LONG STRING] = BEGIN Put.Text[log, s]; END;
WriteLine: PROCEDURE [s: LONG STRING] = BEGIN Put.Line[log, s]; END;
WriteDecimal: PROCEDURE [n: CARDINAL] = INLINE BEGIN WriteNumber[n, 10, 0]; END;
WriteOctal: PROCEDURE [n: CARDINAL] = INLINE BEGIN WriteNumber[n, 8, 0]; END;
WriteNumber: PROCEDURE [n, radix, width: CARDINAL] = INLINE
BEGIN
temp: STRING = [25];
String.AppendNumber[temp, n, radix];
THROUGH [temp.length..width) DO WriteChar[' ]; ENDLOOP;
WriteString[temp];
END;
WriteLongDecimal: PROCEDURE [n: LONG CARDINAL] = INLINE
BEGIN Put.LongDecimal[log, n]; END;
D8: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 10, 8]; END;
O3: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 8, 3]; END;
O3Z: PROCEDURE [n: CARDINAL] =
BEGIN
temp: STRING = [25];
String.AppendNumber[temp, n, 8];
THROUGH [temp.length..3) DO WriteChar['0]; ENDLOOP;
WriteString[temp];
END;
O4: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 8, 4]; END;
O6: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 8, 3]; END;
O9: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 8, 9]; END;
WriteCurrentDateAndTime: PROCEDURE =
BEGIN temp: STRING = [20]; Time.AppendCurrent[temp]; WriteString[temp]; END;
PrintInfo: PROCEDURE [s: LONG STRING, n: LONG CARDINAL] =
BEGIN
IF n = 0 THEN RETURN;
WriteString[s];
WriteString[" = "L];
WriteLongDecimal[n];
WriteLine["."L];
END;
PrintPupAddress: PROCEDURE [a: LONG POINTER TO PupAddress] =
BEGIN temp: STRING = [40]; AppendPupAddress[temp, a↑]; WriteString[temp]; END;
PrintErrorPup: PROCEDURE [b: PupBuffer] =
BEGIN temp: STRING = [200]; AppendErrorPup[temp, b]; WriteString[temp]; END;
PrintBodyAsText: PROCEDURE [b: PupBuffer] =
BEGIN
FOR i: CARDINAL IN [0..GetPupContentsBytes[b]) DO
WriteChar[b.pup.pupChars[i]]; ENDLOOP;
END;
PrintCacheEntry: PROCEDURE [b: PupBuffer] =
BEGIN
p: LONG POINTER ← @b.pup.pupWords;
n: CARDINAL ← 0;
version: CARDINAL;
names: CARDINAL;
addrs: CARDINAL;
version ← (p+n)↑; -- File version number
n ← n + SIZE[CARDINAL];
names ← (p+n)↑;
n ← n + SIZE[CARDINAL];
IF names = 0 THEN WriteString["??"L];
FOR i: CARDINAL IN [0..names) DO
s: LONG STRING = LOOPHOLE[p+n];
words: CARDINAL ← String.WordsForString[s.length];
IF i # 0 THEN WriteString[", "L];
WriteString[s];
n ← n + words;
ENDLOOP;
WriteString[" <=> "L];
addrs ← (p+n)↑;
n ← n + SIZE[CARDINAL];
IF addrs = 0 THEN WriteString["??"L];
FOR i: CARDINAL IN [0..addrs) DO
a: LONG POINTER TO PupAddress ← LOOPHOLE[(p+n)];
IF i # 0 THEN WriteString[", "L];
PrintPupAddress[a];
n ← n + SIZE[PupAddress];
ENDLOOP;
END;
Init: PROCEDURE =
BEGIN
herald: STRING = "Name and Address Tool of 9-Jan-87 10:08:12"L;
[] ← Tool.Create[
name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition];
END;
MakeSWs: Tool.MakeSWsProc =
BEGIN
logFileName: STRING = [40];
msg ← Tool.MakeMsgSW[window: window, lines: 5];
form ← Tool.MakeFormSW[window: window, formProc: MakeForm];
Tool.UnusedLogName[logFileName, "PupToTcp.log$"L];
log ← Tool.MakeFileSW[window: window, name: logFileName, allowTypeIn: FALSE];
END;
MakeForm: FormSW.ClientItemsProcType =
BEGIN
i: INTEGER ← -1;
nParams: CARDINAL = 13;
items ← FormSW.AllocateItemDescriptor[nParams];
items[i ← i + 1] ← FormSW.CommandItem[tag: "Stats"L, proc: Stats, place: FormSW.newLine];
items[i ← i + 1] ← FormSW.CommandItem[tag: "Version"L, proc: Version];
items[i ← i + 1] ← FormSW.StringItem[tag: "Target"L, string: @data.target, inHeap: TRUE];
items[i ← i + 1] ← FormSW.CommandItem[
tag: "NameToAddress"L, proc: NameToAddress, place: FormSW.newLine];
items[i ← i + 1] ← FormSW.CommandItem[tag: "NameToCache"L, proc: NameToCache];
items[i ← i + 1] ← FormSW.StringItem[tag: "Name"L, string: @data.name, inHeap: TRUE];
items[i ← i + 1] ← FormSW.CommandItem[
tag: "AddressToName"L, proc: AddressToName, place: FormSW.newLine];
items[i ← i + 1] ← FormSW.CommandItem[tag: "AddressToCache"L, proc: AddressToCache];
items[i ← i + 1] ← FormSW.StringItem[tag: "Address"L, string: @data.address, inHeap: TRUE];
items[i ← i + 1] ← FormSW.CommandItem[
tag: "PupToTcp"L, proc: PupToTcp, place: FormSW.newLine];
items[i ← i + 1] ← FormSW.CommandItem[tag: "TcpToPup"L, proc: TcpToPup];
items[i ← i + 1] ← FormSW.CommandItem[tag: "NS"L, proc: AllNSFormats];
items[i ← i + 1] ← FormSW.StringItem[tag: "Convert"L, string: @data.pupOrTcp, inHeap: TRUE];
RETURN[items, TRUE];
END;
AlreadyActive: ERROR = CODE;
NotActive: ERROR = CODE;
ClientTransition: ToolWindow.TransitionProcType =
BEGIN
SELECT TRUE FROM
old = inactive =>
BEGIN
IF data # NIL THEN ERROR AlreadyActive;
data ← z.NEW[Data];
data↑ ← [
where:, target: z.NEW[StringBody[20]], name: z.NEW[StringBody[20]],
address: z.NEW[StringBody[20]], pupOrTcp: z.NEW[StringBody[20]] ];
String.AppendString[data.target, "ME"L];
[] ← PupDefs.PupPackageMake[];
END;
new = inactive =>
BEGIN
IF data = NIL THEN ERROR NotActive;
PupDefs.PupPackageDestroy[];
z.FREE[@data.target];
z.FREE[@data.name];
z.FREE[@data.address];
z.FREE[@data];
END;
ENDCASE;
END;
-- Main Body
Init[];
END.