-- File: OthelloNS.mesa - last edit:
-- AOF 5-Feb-88 18:19:40
-- HGM 5-Oct-85 13:14:24
-- Copyright (C) 1984, 1985, 1988 by Xerox Corporation. All rights reserved.
DIRECTORY
Format USING [HostNumber, NetworkAddress, NetworkNumber, NetFormat, StringProc],
OthelloDefs USING [
AbortingCommand, CheckUserAbort, CommandProcessor, IndexTooLarge, MyNameIs,
NewLine, ReadChar, RegisterCommandProc, WriteChar, WriteLine, WriteLongNumber,
WriteString],
OthelloForgot USING [GetNameWithSpaces],
Process USING [Detach, Yield],
Runtime USING [UnboundProcedure],
String USING [AppendChar, AppendNumber, AppendString],
System USING [
HostNumber, NetworkAddress, NetworkNumber,
nullHostNumber, nullNetworkNumber, nullSocketNumber, SocketNumber],
Unformat USING [Error, NetworkAddress],
AddressTranslation USING [Error, PrintError, StringToNetworkAddress],
Buffer USING [],
NSBuffer USING [Body, Buffer],
Driver USING [GetDeviceChain, Device],
EthernetDriverFriends USING [EtherStatsInfo],
InrFriends USING [DriverDetails, GetRouteInfo],
NS3MBit USING [GetInfo],
NSConstants USING [echoerSocket],
NSTypes USING [maxIDPDataWords],
SptpOps USING [GetProtocolInfo, StatsRecord],
SptpProtocol USING [ProtocolObject],
Protocol1 USING [GetContext],
Pup10MBit USING [EnumerateTranslation],
PupTypes USING [PupHostID],
PupRouterDefs USING [NetworkContext],
Router USING [
endEnumeration, EnumerateRoutingTable, infinity, NoTableEntryForNet,
startEnumeration],
RoutingTable USING [NetworkContext],
Socket USING [
ChannelHandle, Create, Delete, GetAssignedAddress, GetPacket, GetPacketBytes,
GetSendBuffer, PutPacket, ReturnBuffer, SetDestination, SetPacketWords,
SetWaitTime, TimeOut];
OthelloNS: PROGRAM
IMPORTS
Format, NS3MBit, OthelloDefs, OthelloForgot, Process, Runtime, String,
Unformat, AddressTranslation, Driver, InrFriends, SptpOps, Protocol1, Pup10MBit,
Router, Socket
EXPORTS Buffer =
BEGIN
Device: PUBLIC TYPE = Driver.Device;
EchoUser: PROCEDURE =
BEGIN
funny, late, missed: LONG CARDINAL ← 0;
recv, sent: LONG CARDINAL ← 0;
wrong: LONG CARDINAL ← 0;
him: System.NetworkAddress;
soc: Socket.ChannelHandle;
packetNumber: CARDINAL ← 0;
b: NSBuffer.Buffer;
body: NSBuffer.Body;
pktBody: LONG POINTER TO ARRAY [0..0) OF WORD;
pleaseStop: BOOLEAN ← FALSE;
Watch: PROCEDURE =
BEGIN
[] ← OthelloDefs.ReadChar[ ! ABORTED => CONTINUE];
pleaseStop ← TRUE;
END;
OthelloForgot.GetNameWithSpaces["Echo to: "L, @echoName];
him ← GetAddress[echoName, NSConstants.echoerSocket !
Trouble => OthelloDefs.AbortingCommand[reason]];
soc ← Socket.Create[System.nullSocketNumber];
Socket.SetWaitTime[soc, 5000];
WriteAddresses[Socket.GetAssignedAddress[soc]];
OthelloDefs.WriteString[" => "L];
WriteAddresses[him];
OthelloDefs.NewLine[];
Process.Detach[FORK Watch[]];
UNTIL pleaseStop DO
cycle: CARDINAL;
IF (((packetNumber ← packetNumber + 1) MOD 5) = 0) THEN Process.Yield[];
cycle ← packetNumber MOD NSTypes.maxIDPDataWords;
IF cycle = 0 THEN OthelloDefs.WriteLine[""L];
body ← (b ← Socket.GetSendBuffer[soc]).ns;
Socket.SetDestination[b, him];
Socket.SetPacketWords[b, cycle + 1];
body.packetType ← echo;
body.echoType ← echoRequest;
pktBody ← @body.nsWords;
FOR k: CARDINAL IN [0..cycle) DO
pktBody[k + 1] ← (k*400B + packetNumber); ENDLOOP;
Socket.PutPacket[soc, b];
sent ← sent + 1;
-- now receive the echo or any back logged echos
DO
b ← Socket.GetPacket[soc !
Socket.TimeOut =>
BEGIN missed ← missed + 1; OthelloDefs.WriteChar['?]; EXIT; END];
pktBody ← @body.nsWords;
SELECT TRUE FROM
(Socket.GetPacketBytes[b] # 2*(cycle + 1))
OR (b.ns.echoType # echoResponse)
OR ((cycle # 0) AND (pktBody[0 + 1] # (0*400B + packetNumber))) =>
BEGIN -- probably a late packet, but could be trash, or error
late ← late + 1;
OthelloDefs.WriteChar['#];
Socket.ReturnBuffer[b];
LOOP;
END;
ENDCASE =>
BEGIN -- the echo we were looking for
FOR k: CARDINAL IN [0..cycle) DO
IF pktBody[k + 1] # (k*400B + packetNumber) THEN
BEGIN wrong ← wrong + 1; OthelloDefs.WriteChar['~]; GOTO Wrong; END;
ENDLOOP;
OthelloDefs.WriteChar['!];
recv ← recv + 1;
Socket.ReturnBuffer[b];
EXIT;
EXITS Wrong => EXIT;
END;
ENDLOOP;
ENDLOOP;
Socket.Delete[soc];
OthelloDefs.NewLine[];
OthelloDefs.WriteString["Out: "L];
OthelloDefs.WriteLongNumber[sent];
OthelloDefs.WriteString[", In: "L];
OthelloDefs.WriteLongNumber[recv];
IF sent # 0 THEN {
OthelloDefs.WriteString[" ("L];
OthelloDefs.WriteLongNumber[(recv*100)/sent];
OthelloDefs.WriteLine["%)"L];
IF late # 0 THEN {
OthelloDefs.WriteString["Late: "L];
OthelloDefs.WriteLongNumber[late];
OthelloDefs.WriteString[" ("L];
OthelloDefs.WriteLongNumber[(late*100)/sent];
OthelloDefs.WriteLine["%)"L]; };
IF missed # 0 THEN {
OthelloDefs.WriteString["Missing: "L];
OthelloDefs.WriteLongNumber[missed];
OthelloDefs.WriteString[" ("L];
OthelloDefs.WriteLongNumber[(missed*100)/sent];
OthelloDefs.WriteLine["%)"L]; }; };
IF funny # 0 THEN {
OthelloDefs.WriteLongNumber[funny];
OthelloDefs.WriteLine[" funny"L]; };
IF wrong # 0 THEN {
OthelloDefs.WriteLongNumber[wrong];
OthelloDefs.WriteLine[" wrong data"L]; };
END;
PrintRoutingTable: PROCEDURE =
BEGIN
PrintOne: PROCEDURE [net: System.NetworkNumber, delay: CARDINAL] =
BEGIN
hickup: BOOLEAN ← FALSE;
delay2: CARDINAL;
details: InrFriends.DriverDetails;
[delay2, details] ← InrFriends.GetRouteInfo[net !
Runtime.UnboundProcedure, Router.NoTableEntryForNet =>
BEGIN hickup ← TRUE; CONTINUE; END];
IF hickup THEN duds ← duds + 1 ELSE nets ← nets + 1;
IF k = 0 THEN OthelloDefs.WriteChar['|];
WriteProductNetNumber[net];
WriteNetNumber[net];
OthelloDefs.WriteChar[' ];
SELECT TRUE FROM
hickup => OthelloDefs.WriteString[" ????? "];
ENDCASE => WriteNetAndHost[details.driverNetwork, details.via.host];
D4[delay];
IF delay # delay2 THEN OthelloDefs.WriteChar['?] ELSE OthelloDefs.WriteChar[' ];
OthelloDefs.WriteString["|"L];
IF (k ← k + 1) = 2 THEN BEGIN OthelloDefs.NewLine[]; k ← 0; Process.Yield[]; END;
END;
k, nets, duds: CARDINAL ← 0;
OthelloDefs.NewLine[];
OthelloDefs.WriteLine[" Local NS Routing Table."L];
OthelloDefs.WriteString["| Net Via Dly "L];
OthelloDefs.WriteLine[ "| Net Via Dly |"L];
OthelloDefs.WriteString["|-------------------------------------------"L];
OthelloDefs.WriteLine[ "|-------------------------------------------|"L];
BEGIN
PrintOne[System.nullNetworkNumber, 0]; -- Enumeration skips net 0
FOR delay: CARDINAL IN [0..Router.infinity) DO
net: System.NetworkNumber ← Router.startEnumeration;
DO
net ← Router.EnumerateRoutingTable[net, delay];
IF net = Router.endEnumeration THEN EXIT;
PrintOne[net, delay];
OthelloDefs.CheckUserAbort[! ABORTED => GOTO Exit];
ENDLOOP;
REPEAT Exit => NULL;
ENDLOOP;
END;
IF k # 0 THEN OthelloDefs.NewLine[];
IF nets > 1 THEN
BEGIN
OthelloDefs.WriteString["There are "L];
WriteDecimal[nets - 1];
OthelloDefs.WriteLine[" active networks."L];
END;
IF duds > 0 THEN
BEGIN
OthelloDefs.WriteString["There are "L];
WriteDecimal[duds];
OthelloDefs.WriteLine[" dead slots."L];
END;
END;
PrintDeviceStats: PROCEDURE =
BEGIN
firstDevice: Device ← Driver.GetDeviceChain[];
FOR network: Device ← firstDevice, network.next UNTIL network = NIL DO
OthelloDefs.CheckUserAbort[ ! ABORTED => EXIT];
SELECT network.device FROM
ethernet, ethernetOne =>
BEGIN
pup: PupRouterDefs.NetworkContext ← Protocol1.GetContext[network, pup];
ns: RoutingTable.NetworkContext ← Protocol1.GetContext[network, ns];
stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats;
OthelloDefs.WriteString["Ethernet"L];
IF network.device = ethernetOne THEN OthelloDefs.WriteString["One"L];
OthelloDefs.WriteString[" Statistics for Pup "L];
WriteNumber[pup.pupNetNumber, 8, 0];
OthelloDefs.WriteString["#"L];
WriteNumber[pup.pupHostNumber, 8, 0];
OthelloDefs.WriteString["#, NS net "L];
WriteNetNumbers[ns.netNumber];
OthelloDefs.WriteLine["."L];
IF stats = NIL THEN
BEGIN
OthelloDefs.WriteLine["*** NO DRIVER STATS ***"L];
LOOP;
END;
OthelloDefs.WriteString[" Rcv: pkts "L];
OthelloDefs.WriteLongNumber[stats.packetsRecv];
OthelloDefs.WriteString[", words "L];
OthelloDefs.WriteLongNumber[stats.wordsRecv];
OthelloDefs.WriteString[", bad "L];
OthelloDefs.WriteLongNumber[stats.badRecvStatus];
OthelloDefs.WriteString[", missed "L];
OthelloDefs.WriteLongNumber[stats.packetsMissed];
IF stats.idleInput # 0 THEN
BEGIN
OthelloDefs.WriteString[", idle "L];
OthelloDefs.WriteLongNumber[stats.idleInput];
END;
OthelloDefs.NewLine[];
IF stats.badRecvStatus # 0 OR stats.okButDribble # 0 THEN
BEGIN
OthelloDefs.WriteString[" crc "L];
OthelloDefs.WriteLongNumber[stats.badCrc];
OthelloDefs.WriteString[", bad alignment but ok crc "L];
OthelloDefs.WriteLongNumber[stats.badAlignmentButOkCrc];
OthelloDefs.WriteString[", crc and bad alignment "L];
OthelloDefs.WriteLongNumber[stats.crcAndBadAlignment];
OthelloDefs.NewLine[];
OthelloDefs.WriteString[" ok but dribble "L];
OthelloDefs.WriteLongNumber[stats.okButDribble];
OthelloDefs.WriteString[", too long "L];
OthelloDefs.WriteLongNumber[stats.packetTooLong];
OthelloDefs.WriteString[", overrun "L];
OthelloDefs.WriteLongNumber[stats.overrun];
OthelloDefs.NewLine[];
END;
OthelloDefs.WriteString[" Xmit: pkts "L];
OthelloDefs.WriteLongNumber[stats.packetsSent];
OthelloDefs.WriteString[", words "L];
OthelloDefs.WriteLongNumber[stats.wordsSent];
OthelloDefs.WriteString[", bad "L];
OthelloDefs.WriteLongNumber[stats.badSendStatus];
OthelloDefs.NewLine[];
IF stats.stuckOutput # 0 OR stats.badSendStatus # 0
OR stats.tooManyCollisions # 0 THEN
BEGIN
OthelloDefs.WriteString[" underrun "L];
OthelloDefs.WriteLongNumber[stats.underrun];
OthelloDefs.WriteString[", stuck "L];
OthelloDefs.WriteLongNumber[stats.stuckOutput];
OthelloDefs.WriteString[", too many collisions "L];
OthelloDefs.WriteLongNumber[stats.tooManyCollisions];
OthelloDefs.NewLine[];
END;
OthelloDefs.WriteString[" Lds:"L];
FOR i: CARDINAL IN [0..16) DO
OthelloDefs.WriteChar[' ]; OthelloDefs.WriteLongNumber[stats.loadTable[i]]; ENDLOOP;
OthelloDefs.NewLine[];
END;
phonenet =>
BEGIN
pup: PupRouterDefs.NetworkContext ← Protocol1.GetContext[network, pup];
ns: RoutingTable.NetworkContext ← Protocol1.GetContext[network, ns];
stats: LONG POINTER TO SptpOps.StatsRecord = network.stats;
info: SptpProtocol.ProtocolObject;
SptpOps.GetProtocolInfo[network, @info];
OthelloDefs.WriteString["PhoneNet Statistics for Pup "L];
WriteNumber[pup.pupNetNumber, 8, 0];
OthelloDefs.WriteString["#"L];
WriteNumber[pup.pupHostNumber, 8, 0];
OthelloDefs.WriteString["#, NS net "L];
WriteNetNumbers[ns.netNumber];
OthelloDefs.WriteString[", Line "L];
OthelloDefs.WriteLongNumber[network.lineNumber];
OthelloDefs.WriteString[", "L];
OthelloDefs.WriteLongNumber[network.lineSpeed];
OthelloDefs.WriteString["KB"L];
SELECT TRUE FROM
(info.state # data) => OthelloDefs.WriteString[", Down"L];
(info.him = info.me) => OthelloDefs.WriteString[", Looped"L];
ENDCASE => {
OthelloDefs.NewLine[];
OthelloDefs.WriteString[" Up to "L];
WriteHostNumbers[info.him]};
OthelloDefs.NewLine[];
OthelloDefs.WriteString[" Recv: pkts "L];
OthelloDefs.WriteLongNumber[stats.pktsReceived];
OthelloDefs.WriteString[", bytes "L];
OthelloDefs.WriteLongNumber[stats.bytesReceived];
OthelloDefs.NewLine[];
OthelloDefs.WriteString[" Bad crc "L];
OthelloDefs.WriteLongNumber[stats.checksumError];
OthelloDefs.WriteString[", data lost "L];
OthelloDefs.WriteLongNumber[stats.dataLost];
OthelloDefs.WriteString[", device error "L];
OthelloDefs.WriteLongNumber[stats.deviceError];
OthelloDefs.WriteString[", other error "L];
OthelloDefs.WriteLongNumber[stats.disaster];
OthelloDefs.NewLine[];
OthelloDefs.WriteString[" Send: pkts "L];
OthelloDefs.WriteLongNumber[stats.packetsSent];
OthelloDefs.WriteString[", bytes "L];
OthelloDefs.WriteLongNumber[stats.bytesSent];
OthelloDefs.NewLine[];
<< OthelloDefs.WriteString[" NS "L];
OthelloDefs.WriteLongNumber[stats.stats[nsSent]];
OthelloDefs.WriteString[" "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.nsBytesSend]];
OthelloDefs.WriteString[", Pups "L];
OthelloDefs.WriteLongNumber[stats.stats[pupSent]];
OthelloDefs.WriteString[" "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.pupBytesSend]];
OthelloDefs.WriteString[", Leaf "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.leafPktsSend]];
OthelloDefs.WriteString[" "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.leafBytesSend]];
OthelloDefs.NewLine[];
IF stats.stats[sendErrorBadStatus] # 0 OR stats.stats[queueTooOld] # 0 THEN {
OthelloDefs.WriteString[" Bad "L];
OthelloDefs.WriteLongNumber[stats.stats[sendErrorBadStatus]];
OthelloDefs.WriteString[", stuck "L];
OthelloDefs.WriteLongNumber[stats.stats[queueTooOld]];
OthelloDefs.NewLine[]; };
OthelloDefs.WriteString[" Queue too long "L];
OthelloDefs.WriteLongNumber[stats.stats[congestion]];
OthelloDefs.WriteString[", NS "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.nsCongestion]];
OthelloDefs.WriteString[", Pup "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.pupCongestion]];
OthelloDefs.NewLine[];
OthelloDefs.WriteString[" Conn too greedy "L];
OthelloDefs.WriteLongNumber[stats.stats[connTooGreedy]];
OthelloDefs.WriteString[", NS "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.nsTooGreedy]];
OthelloDefs.WriteString[", Pup "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.pupTooGreedy]];
OthelloDefs.NewLine[];
IF stats.stats[PhoneNetExtras.nsDupsFiltered] # 0 THEN {
OthelloDefs.WriteString[" NS duplicates discarded: "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.nsDupsFiltered]];
OthelloDefs.NewLine[]; };
IF stats.stats[PhoneNetExtras.pupDupsFiltered] # 0 THEN {
OthelloDefs.WriteString[" BSP probes/duplicates discarded: "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.pupDupsFiltered]];
OthelloDefs.NewLine[]; };
IF stats.stats[PhoneNetExtras.leafDupsFiltered] # 0 THEN {
OthelloDefs.WriteString[" Leaf duplicates discarded: "L];
OthelloDefs.WriteLongNumber[stats.stats[PhoneNetExtras.leafDupsFiltered]];
OthelloDefs.NewLine[]; };
>> END;
ENDCASE => NULL;
ENDLOOP;
END;
PrintTranslationCache: PROCEDURE =
BEGIN
firstDevice: Device ← Driver.GetDeviceChain[];
FOR network: Device ← firstDevice, network.next UNTIL network = NIL DO
OthelloDefs.CheckUserAbort[ ! ABORTED => EXIT];
SELECT network.device FROM
ethernet =>
BEGIN
pup: PupRouterDefs.NetworkContext ← Protocol1.GetContext[network, pup];
ns: RoutingTable.NetworkContext ← Protocol1.GetContext[network, ns];
stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats;
OthelloDefs.WriteString["8=>48 Translation Cache for Pup "L];
WriteNumber[pup.pupNetNumber, 8, 0];
OthelloDefs.WriteString["#"L];
WriteNumber[pup.pupHostNumber, 8, 0];
OthelloDefs.WriteString["#, NS net "L];
WriteNetNumbers[ns.netNumber];
OthelloDefs.WriteLine["."L];
FOR i: NAT IN [0..377B] DO
pup: PupTypes.PupHostID ← [i];
ns: System.HostNumber ← Pup10MBit.EnumerateTranslation[pup, network].translation;
IF ns = System.nullHostNumber THEN LOOP;
OthelloDefs.WriteString[" "L];
WriteNumber[pup, 8, 3];
OthelloDefs.WriteString[" => "L];
WriteHostNumbers[ns];
OthelloDefs.WriteLine["."L];
ENDLOOP;
END;
ethernetOne =>
BEGIN
pup: PupRouterDefs.NetworkContext ← Protocol1.GetContext[network, pup];
ns: RoutingTable.NetworkContext ← Protocol1.GetContext[network, ns];
stats: LONG POINTER TO EthernetDriverFriends.EtherStatsInfo ← network.stats;
OthelloDefs.WriteString["8<=48 Translation Cache for Pup "L];
WriteNumber[pup.pupNetNumber, 8, 0];
OthelloDefs.WriteString["#"L];
WriteNumber[pup.pupHostNumber, 8, 0];
OthelloDefs.WriteString["#, NS net "L];
WriteNetNumbers[ns.netNumber];
OthelloDefs.WriteLine["."L];
FOR i: NAT IN [0..377B] DO
pup: PupTypes.PupHostID ← [i];
ns: System.HostNumber ← NS3MBit.GetInfo[pup, network];
IF ns = System.nullHostNumber THEN LOOP;
OthelloDefs.WriteString[" "L];
WriteNumber[pup, 8, 3];
OthelloDefs.WriteString[" <= "L];
WriteHostNumbers[ns];
OthelloDefs.WriteLine["."L];
ENDLOOP;
END;
ENDCASE => NULL;
ENDLOOP;
END;
WriteAddresses: PROCEDURE [a: System.NetworkAddress] =
BEGIN
Push: Format.StringProc = BEGIN OthelloDefs.WriteString[s]; END;
Format.NetworkAddress[Push, a, productSoftware];
OthelloDefs.WriteString["="L];
Format.NetworkAddress[Push, a, octal];
END;
WriteHostNumbers: PROCEDURE [host: System.HostNumber] =
BEGIN
Push: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
BEGIN OthelloDefs.WriteString[s]; END;
Format.HostNumber[Push, host, productSoftware];
OthelloDefs.WriteString["="L];
Format.HostNumber[Push, host, octal];
END;
WriteNetNumbers: PROCEDURE [net: System.NetworkNumber] =
BEGIN
Push: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
BEGIN OthelloDefs.WriteString[s]; END;
Format.NetworkNumber[Push, net, productSoftware];
OthelloDefs.WriteString["="L];
Format.NetworkNumber[Push, net, octal];
END;
WriteProductNetNumber: PROCEDURE [net: System.NetworkNumber] =
BEGIN
Push: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
BEGIN
THROUGH [s.length..6) DO OthelloDefs.WriteChar[' ]; ENDLOOP;
OthelloDefs.WriteString[s];
END;
Format.NetworkNumber[Push, net, productSoftware];
END;
WriteNetNumber: PROCEDURE [net: System.NetworkNumber] =
BEGIN
Push: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
BEGIN
THROUGH [s.length..6) DO OthelloDefs.WriteChar[' ]; ENDLOOP;
OthelloDefs.WriteString[s];
END;
Format.NetworkNumber[Push, net, octal];
END;
WriteNetAndHost: PROCEDURE [
net: System.NetworkNumber, host: System.HostNumber] =
BEGIN
Append: Format.StringProc = BEGIN String.AppendString[temp, s]; END;
temp: STRING = [50];
Format.NetworkNumber[Append, net, productSoftware];
String.AppendChar[temp, '.];
Format.HostNumber[Append, host, productSoftware];
String.AppendChar[temp, '.];
THROUGH [temp.length..25) DO OthelloDefs.WriteChar[' ]; ENDLOOP;
OthelloDefs.WriteString[temp];
END;
WriteDecimal: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 10, 0]; END;
D4: PROCEDURE [n: CARDINAL] = BEGIN WriteNumber[n, 10, 4]; END;
WriteNumber: PROCEDURE [n, radix, width: CARDINAL] =
BEGIN
temp: STRING = [25];
String.AppendNumber[temp, n, radix];
THROUGH [temp.length..width) DO OthelloDefs.WriteChar[' ]; ENDLOOP;
OthelloDefs.WriteString[temp];
END;
Trouble: ERROR [reason: LONG STRING] = CODE;
GetAddress: PROCEDURE [host: LONG STRING, socket: System.SocketNumber]
RETURNS [addr: System.NetworkAddress] =
BEGIN
localFailed: BOOLEAN ← FALSE;
IF host = NIL THEN ERROR Trouble ["NIL => Address Fault"L];
addr ← Unformat.NetworkAddress[host, octal !
Unformat.Error => BEGIN localFailed ← TRUE; CONTINUE; END ];
IF localFailed THEN
BEGIN
addr ← AddressTranslation.StringToNetworkAddress[host !
AddressTranslation.Error =>
BEGIN
temp: STRING = [200];
proc: Format.StringProc = {String.AppendString[temp, s]};
AddressTranslation.PrintError[errorRecord, proc];
ERROR Trouble[temp];
END].addr;
addr.socket ← socket; -- CH returns trash in socket
END;
IF addr.socket = System.nullSocketNumber THEN addr.socket ← socket;
END;
echoName: LONG STRING ← NIL;
Commands: PROCEDURE [index: CARDINAL] =
BEGIN
SELECT index FROM
0 =>
BEGIN
OthelloDefs.MyNameIs[myNameIs: "Echo User"L, myHelpIs: "NS echo user"L];
EchoUser[];
END;
1 =>
BEGIN
OthelloDefs.MyNameIs[
myNameIs: "Routing Tables"L,
myHelpIs: "Show this machine's NS routing table"L];
PrintRoutingTable[];
END;
2 =>
BEGIN
OthelloDefs.MyNameIs[
myNameIs: "Print Device Statistics"L,
myHelpIs: "Print Device dependent Statistics for all drivers"L];
PrintDeviceStats[];
END;
3 =>
BEGIN
OthelloDefs.MyNameIs[
myNameIs: "Print Translation Cache(s)"L,
myHelpIs: "Print 48/8 and 8/48 Address Translation Cache(s) for all drivers"L];
PrintTranslationCache[];
END;
ENDCASE => OthelloDefs.IndexTooLarge;
END;
commandProcessor: OthelloDefs.CommandProcessor ← [Commands];
-- initialization
OthelloDefs.RegisterCommandProc[@commandProcessor];
END.....