DIRECTORY
Basics USING [Comparison],
Buttons USING [Button, ButtonProc, Create],
Containers USING [ChildXBound, ChildYBound, Container, Create],
Labels USING [Create, Label, Set],
Menus USING [CreateEntry, CreateMenu, InsertMenuEntry, Menu, MenuProc],
Rules USING [Create, Rule],
ViewerIO USING [CreateViewerStreams],
ViewerOps USING [CreateViewer, PaintViewer, SetMenu, SetOpenHeight],
ViewerClasses USING [Viewer],
ViewerTools USING [MakeNewTextViewer, GetContents, SetContents, SetSelection],
FS USING [StreamOpen],
GVBasics USING [oldestTime],
GVNames
USING [CheckStamp, GetList, GetMembers,
GetRemark, ListType, MemberInfo, RemarkInfo, RListHandle],
Histogram,
IO USING [card, Flush, noWhereStream, PutF, PutFR, PutRope, STREAM, time],
RedBlackTree USING [Create, EnumerateIncreasing, Insert, Key, Lookup, Table, UserData],
Rope USING [Cat, Compare, Find, Length, ROPE, SkipOver, SkipTo, Substr];
CedarDLMapper:
CEDAR
MONITOR
IMPORTS Buttons, Containers, Labels, Menus, Rules, ViewerIO, ViewerOps, ViewerTools, FS, GVNames, Histogram, IO, RedBlackTree, Rope = {
ROPE: TYPE = Rope.ROPE;
entryHeight: CARDINAL = 15;
entryVSpace: CARDINAL = 10;
entryHSpace: CARDINAL = 10;
heightSoFar: CARDINAL ← 0;
container: Containers.Container;
currentGroups, totalGroups: Labels.Label;
currentName: Labels.Label;
exceptions: ViewerClasses.Viewer;
inStr, outStr: IO.STREAM;
fullFileName, conFileName, ARPAFileName, registries: ViewerClasses.Viewer;
BuildOuter:
PROC = {
myMenu: Menus.Menu ← Menus.CreateMenu[];
container ← Containers.Create[ info: [name: "DLMap", scrollable: FALSE] ];
Menus.InsertMenuEntry[menu: myMenu,
entry: Menus.CreateEntry[name: "DoIt", proc: DoIt]
];
Menus.InsertMenuEntry[menu: myMenu,
entry: Menus.CreateEntry[name: "Stop", proc: StopIt]
];
ViewerOps.SetMenu[viewer: container, menu: myMenu];
BuildUserInput[];
BuildUserFeedback[];
BuildExceptions[];
ViewerOps.SetOpenHeight[viewer: container, clientHeight: heightSoFar];
ViewerOps.PaintViewer[viewer: container, hint: all];
};
BuildUserInput:
PROC = {
Bl1, Bl2, Bl3, Bl4: Buttons.Button;
heightSoFar ← heightSoFar+entryVSpace/2;
Bl1 ← Buttons.Create[info: [name: "Full map file name:", parent: container, border:
FALSE,
wy: heightSoFar], proc: ForceSelToFullFileName];
fullFileName ← ViewerTools.MakeNewTextViewer[info: [parent: container,
wx: Bl1.wx+Bl1.ww+entryHSpace, wy: heightSoFar, ww: 0, wh: entryHeight,
data: defaultFullFileName, scrollable: FALSE, border: FALSE], paint: FALSE];
Containers.ChildXBound[container, fullFileName];
heightSoFar ← heightSoFar+entryVSpace+Bl1.wh;
Bl2 ← Buttons.Create[info: [name: "Condensed map file name:", parent: container,
border: FALSE, wy: heightSoFar], proc: ForceSelToConFileName];
conFileName ← ViewerTools.MakeNewTextViewer[info: [parent: container,
wx: Bl2.wx+Bl2.ww+entryHSpace, wy: heightSoFar, ww: 0, wh: entryHeight,
data: defaultConFileName, scrollable: FALSE, border: FALSE], paint: FALSE];
Containers.ChildXBound[container, conFileName];
heightSoFar ← heightSoFar+entryVSpace+Bl2.wh;
Bl3 ← Buttons.Create[info: [name: "Arpa DL map file name:", parent: container,
border: FALSE, wy: heightSoFar], proc: ForceSelToARPAFileName];
ARPAFileName ← ViewerTools.MakeNewTextViewer[info: [parent: container,
wx: Bl3.wx+Bl3.ww+entryHSpace, wy: heightSoFar, ww: 0, wh: entryHeight,
data: defaultARPAFileName, scrollable: FALSE, border: FALSE], paint: FALSE];
Containers.ChildXBound[container, ARPAFileName];
heightSoFar ← heightSoFar+entryVSpace+Bl3.wh;
Bl4 ← Buttons.Create[info: [name: "Registries:", parent: container, border:
FALSE,
wy: heightSoFar], proc: ForceSelToRegistries];
registries ← ViewerTools.MakeNewTextViewer[info: [parent: container,
wx: Bl4.wx+Bl4.ww+entryHSpace, wy: heightSoFar, ww: 0, wh: 4*entryHeight,
data: defaultRegistries, scrollable: TRUE, border: FALSE], paint: FALSE];
Containers.ChildXBound[container, registries];
heightSoFar ← heightSoFar+entryVSpace+registries.wh;
};
ForceSelToFullFileName: Buttons.ButtonProc = {
IF mouseButton#red THEN ViewerTools.SetContents[fullFileName, defaultFullFileName]
ELSE ViewerTools.SetSelection[fullFileName];
};
ForceSelToConFileName: Buttons.ButtonProc = {
IF mouseButton#red THEN ViewerTools.SetContents[conFileName, defaultConFileName]
ELSE ViewerTools.SetSelection[conFileName];
};
ForceSelToARPAFileName: Buttons.ButtonProc = {
IF mouseButton#red THEN ViewerTools.SetContents[ARPAFileName, defaultARPAFileName]
ELSE ViewerTools.SetSelection[ARPAFileName];
};
ForceSelToRegistries: Buttons.ButtonProc = {
IF mouseButton#red THEN ViewerTools.SetContents[registries, defaultRegistries]
ELSE ViewerTools.SetSelection[registries];
};
BuildUserFeedback:
PROC = {
lg, ln, of: Labels.Label;
r1: Rules.Rule;
r1 ← Rules.Create[info: [parent: container, wx: 0, wy: heightSoFar, ww: 0, wh: 1]];
Containers.ChildXBound[container, r1];
heightSoFar ← heightSoFar+entryVSpace;
lg ← Labels.Create[info: [name: "DL's:", parent: container,
wx: 0, wy: heightSoFar, border: FALSE]];
currentGroups ← Labels.Create[info: [name: "0000", parent: container,
wx: lg.wx+lg.ww+entryHSpace, wy: heightSoFar, border: TRUE]];
Labels.Set[currentGroups, "0"];
of ← Labels.Create[info: [name: "of", parent: container,
wx: currentGroups.wx+currentGroups.ww+entryHSpace, wy: heightSoFar, border: FALSE]];
totalGroups ← Labels.Create[info: [name: "0000", parent: container,
wx: of.wx+of.ww+entryHSpace, wy: heightSoFar, border: TRUE]];
Labels.Set[totalGroups, "0"];
heightSoFar ← heightSoFar+entryVSpace+of.wh;
ln ← Labels.Create[info: [name: "Current Name:", parent: container,
wx: 0, wy: heightSoFar, border: FALSE]];
currentName ← Labels.Create[info: [name: "", parent: container,
wx: ln.wx+ln.ww+entryHSpace, wy: heightSoFar, border: FALSE]];
Labels.Set[currentName, "none"];
Containers.ChildXBound[container, currentName];
heightSoFar ← heightSoFar+entryVSpace+of.wh;
};
BuildExceptions:
PROC = {
r2: Rules.Rule;
r2 ← Rules.Create[info: [parent: container,
wx: 0, wy: heightSoFar, ww: 0, wh: 1]];
Containers.ChildXBound[container, r2];
heightSoFar ← heightSoFar+entryVSpace;
exceptions ← ViewerOps.CreateViewer[flavor: $Typescript,
info: [name: "", parent: container, wx: 0, wy: heightSoFar, wh: 5*entryHeight,
border: FALSE]];
heightSoFar ← heightSoFar+entryVSpace+exceptions.wh;
Containers.ChildXBound[container, exceptions];
Containers.ChildYBound[container, exceptions];
[in: inStr, out: outStr] ← ViewerIO.CreateViewerStreams[name: "", viewer: exceptions,
backingFile: "DLMap.log"];
};
**************** start of operational code ****************
mapperStopped: ERROR = CODE;
mappingInProgress: BOOLEAN ← FALSE;
allRegistries: ROPE ← NIL;
defaultRegistries: ROPE = "DLOS EOSA ES FX Henr OSDA PA PASA RX Siemens WBST X XRCC";
defaultFullFileName: ROPE = "///GV/FullDLMap.txt";
defaultConFileName: ROPE = "///GV/DLMap.txt";
defaultARPAFileName: ROPE = "///GV/ARPA-DLMap.txt";
stop: BOOLEAN ← FALSE;
DoIt: Menus.MenuProc = {
IF ReserveMapper[] THEN
{
Map[ ! mapperStopped => {outStr.PutF["\nStopped at %t.\n\n", IO.time[]]; CONTINUE} ];
ReleaseMapper[];
};
}; -- DoIt--
StopIt: Menus.MenuProc = {SetStop[]};
ReserveMapper:
ENTRY
PROC
RETURNS [
BOOLEAN] = {
IF mappingInProgress
THEN RETURN [FALSE]
ELSE {mappingInProgress ← TRUE; RETURN[TRUE]};
};
ReleaseMapper: ENTRY PROC = {mappingInProgress ← FALSE; stop ← FALSE};
SetStop: ENTRY PROC = {stop ← TRUE};
StopSet: ENTRY PROC RETURNS [BOOLEAN] = {RETURN [stop]};
Stopped:
PROC
RETURNS [
BOOLEAN] = {
IF StopSet[] THEN ERROR mapperStopped ELSE RETURN[FALSE]};
ReportAllDown:
PROC [dot:
BOOLEAN, name:
ROPE] = {
IF dot
THEN outStr.PutRope["."]
ELSE outStr.PutF["\nAll down: %g. ", [rope[name]]];
};
ForWordsInRopeDo: PROC [r: ROPE, work: PROC[ROPE] RETURNS[done: BOOLEAN]]
RETURNS [stopped:
BOOLEAN] = {
parsePosition: CARDINAL ← Rope.SkipOver[r, 0, " "]; -- skip initial blanks
UNTIL parsePosition = Rope.Length[r]
DO
--parse registry input--
start: CARDINAL = parsePosition;
parsePosition ← Rope.SkipTo[r, parsePosition, " "];
IF work[Rope.Substr[r, start, parsePosition-start]] THEN RETURN [stopped: TRUE];
parsePosition ← Rope.SkipOver[r, parsePosition, " "];
ENDLOOP;
RETURN [stopped: FALSE]
}; -- ForWordsInRopeDo --
CheckRegistryValidity:
PROC [reg:
ROPE]
RETURNS [done:
BOOLEAN] = {
printDot: BOOLEAN ← FALSE;
UNTIL Stopped[]
DO
SELECT GVNames.CheckStamp[Rope.Cat[reg, ".gv"]]
FROM
group =>
NULL;
individual, notFound => {
outStr.PutF["%g%g\n\n", [rope[reg]], [rope[" is not a valid registry."]]];
ERROR mapperStopped
};
allDown =>
{ReportAllDown[printDot, reg]; printDot←TRUE; LOOP};
ENDCASE =>
ERROR;
EXIT;
ENDLOOP;
RETURN [done: FALSE]
}; --CheckRegistryValidity--
CreateOutputFile: PROC[n: ROPE] RETURNS [IO.STREAM] =
{
RETURN [
IF Rope.Length[n] = 0
THEN
IO.noWhereStream
ELSE FS.StreamOpen[n, create]]
};
GroupNotFound: ERROR = CODE;
GetRList:
PROC [n:
ROPE, t: GVNames.ListType]
RETURNS [l:
ROPE] = {
printDot: BOOLEAN ← FALSE;
UNTIL Stopped[]
DO
WITH GVNames.GetList[n, GVBasics.oldestTime, t]
SELECT
FROM
g: GVNames.MemberInfo[group] => {
AddNameToRope:
PROC [m:
ROPE]
RETURNS [done:
BOOL] = {
IF l # NIL THEN l ← Rope.Cat[l, ", "];
l ← Rope.Cat[l, m];
l ← NIL;
EnumerateRList[g.members, AddNameToRope];
};
a: GVNames.MemberInfo[allDown] =>
{ReportAllDown[printDot, n]; printDot←TRUE; LOOP};
ENDCASE =>
ERROR GroupNotFound;
EXIT;
ENDLOOP;
}; --GetRList--
GetMembers:
PROC [g:
ROPE]
RETURNS [rLH: GVNames.RListHandle, c:
CARDINAL] = {
printDot: BOOLEAN ← FALSE;
UNTIL Stopped[]
DO
WITH GVNames.GetMembers[g]
SELECT
FROM
g: GVNames.MemberInfo[group] => {rLH ← g.members; c ← g.count};
a: GVNames.MemberInfo[allDown] =>
{ReportAllDown[printDot, g]; printDot←TRUE; LOOP};
ENDCASE => ERROR GroupNotFound;
EXIT;
ENDLOOP;
}; --GetMembers--
GetRemark:
PROCEDURE [g:
ROPE]
RETURNS [r:
ROPE] = {
printDot: BOOLEAN ← FALSE;
UNTIL Stopped[]
DO
info: GVNames.RemarkInfo;
[info, r] ← GVNames.GetRemark[g];
SELECT info
FROM
group => IF Rope.Length[r] = 0 THEN r ← NIL;
allDown =>
{ReportAllDown[printDot, g]; printDot←TRUE; LOOP};
ENDCASE => ERROR GroupNotFound;
EXIT;
ENDLOOP;
}; --GetRemark--
CardToRope: PROC [c: CARDINAL] RETURNS [ROPE] = INLINE
{RETURN [IO.PutFR[v1: IO.card[c]]]};
DLInfo:
TYPE =
RECORD [
name: ROPE,
printable, notFound: BOOLEAN,
in, ind: CARDINAL,
remark, owners, friends: ROPE,
sub: LIST OF REF DLInfo ];
GetKey:
PROC [data: RedBlackTree.UserData]
RETURNS [key: RedBlackTree.Key] = {
WITH data
SELECT
FROM
r: ROPE => key ← r;
m: REF DLInfo => key ← m.name;
ENDCASE => ERROR;
};
MyCompare:
PROC [k: RedBlackTree.Key, data: RedBlackTree.UserData]
RETURNS [Basics.Comparison] = {
a: ROPE ← NARROW[k];
b: ROPE ← NARROW[GetKey[data]];
RETURN [Rope.Compare[a, b, FALSE]]
}; --MyCompare--
EnumerateRList:
PROC [r: GVNames.RListHandle,
p:
PROCEDURE [
ROPE]
RETURNS [
BOOLEAN] ] = {
FOR r ← r, r.rest UNTIL r=NIL OR p[r.first] DO ENDLOOP};
Map:
PROC = {
GetEntry:
PROC [n:
ROPE]
RETURNS [d:
REF DLInfo] = {
d ← NARROW[RedBlackTree.Lookup[tree, n]];
IF d =
NIL
THEN {
d ←
NEW [DLInfo ← [name:n, printable:
FALSE, notFound:
FALSE, in:0, ind:0,
remark:NIL, owners:NIL, friends:NIL, sub:NIL]];
RedBlackTree.Insert[tree, d, n];
};
}; --GetEntry--
EnumerateRegistry:
PROC [reg:
ROPE]
RETURNS [
BOOLEAN] = {
rG: ROPE = Rope.Cat["groups.", reg];
regRLH: GVNames.RListHandle;
Labels.Set[currentName, rG];
[regRLH, ] ← GetMembers[rG ! GroupNotFound =>
{outStr.PutF["\n%g not found?", [rope[rG]]]; ERROR mapperStopped}];
EnumerateRList[regRLH, GroupWork];
RETURN[FALSE]
}; --EnumerateRegsitry--
GroupWork:
PROC [group:
ROPE]
RETURNS [done:
BOOLEAN] = {
ContentWork:
PROC [m:
ROPE]
RETURNS [done:
BOOLEAN] = {
done ← FALSE;
IF Rope.SkipTo[m, 0, "^"] = Rope.Length[m]
THEN gDI.ind ← gDI.ind + 1
ELSE {
end: LIST OF REF DLInfo;
mDI: REF DLInfo = GetEntry[m];
mDI.in ← mDI.in + 1;
IF gDI.sub = NIL
THEN gDI.sub ←
CONS[mDI,
NIL]
ELSE FOR end ← gDI.sub, end.rest UNTIL end.rest = NIL DO
REPEAT FINISHED => end.rest ← CONS[mDI, NIL];
ENDLOOP;
};
}; --ContentWork--
gDI: REF DLInfo ← NIL;
rLH: GVNames.RListHandle;
count: CARDINAL;
notFound: BOOLEAN ← FALSE;
Labels.Set[currentName, group];
Labels.Set[totalGroups, CardToRope[totalGrp ← totalGrp + 1]];
[rLH, count] ← GetMembers[group ! GroupNotFound => {notFound ← TRUE; CONTINUE}];
IF NOT notFound THEN gram.DataPoint[count];
IF Rope.SkipTo[group, 0, "^"] = Rope.Length[group] THEN RETURN [done: FALSE];
gDI ← GetEntry[group];
gDI.printable ← TRUE;
IF notFound
THEN gDI.notFound ←
TRUE
ELSE {
IF fFH#
IO.noWhereStream
THEN {
-- need extra info for the full listing --
EnumerateRList[rLH, ContentWork];
gDI.owners ← GetRList[group, owners];
};
gDI.remark ← GetRemark[group];
gDI.friends ← GetRList[group, friends];
};
RETURN [done: FALSE]
}; -- GroupWork--
AlreadyDoneThis: SIGNAL [new: REF DLInfo] RETURNS [BOOLEAN] = CODE;
WC:
PROC [r1, r2, r3, r4:
ROPE ←
NIL] = {
IF r1#NIL THEN cFH.PutRope[r1];
IF r2#NIL THEN cFH.PutRope[r2];
IF r3#NIL THEN cFH.PutRope[r3];
IF r4#NIL THEN cFH.PutRope[r4]
};
WF:
PROC [r1, r2, r3, r4:
ROPE ←
NIL] = {
IF r1#NIL THEN fFH.PutRope[r1];
IF r2#NIL THEN fFH.PutRope[r2];
IF r3#NIL THEN fFH.PutRope[r3];
IF r4#NIL THEN fFH.PutRope[r4]
};
WA:
PROC [r1, r2, r3, r4:
ROPE ←
NIL] = {
IF r1#NIL THEN aFH.PutRope[r1];
IF r2#NIL THEN aFH.PutRope[r2];
IF r3#NIL THEN aFH.PutRope[r3];
IF r4#NIL THEN aFH.PutRope[r4]
};
W: PROC [r1, r2, r3, r4: ROPE ← NIL] = {WF[r1, r2, r3, r4]; WC[r1, r2, r3, r4]};
PrintDLEntry:
PROC [dl: RedBlackTree.UserData]
RETURNS [
BOOLEAN] = {
dlInfo: REF DLInfo = NARROW [dl];
IF NOT dlInfo.printable OR dlInfo.notFound THEN RETURN[FALSE];
Labels.Set[currentName, dlInfo.name];
Labels.Set[currentGroups, CardToRope[currentGrp ← currentGrp+1]];
W["\n"];
IF Rope.Find[dlInfo.remark, "@"] > -1
THEN {
WA[dlInfo.name]; WA[" - ", dlInfo.remark, "\n"]
};
W[dlInfo.name];
IF dlInfo.remark#NIL THEN {W[" - ", dlInfo.remark]; dlInfo.remark ← NIL};
WF["\n\t", CardToRope[dlInfo.ind], " individual", IF dlInfo.ind=1 THEN NIL ELSE "s"];
IF dlInfo.in#0 THEN
WF["; in ", CardToRope[dlInfo.in], " other DL", IF dlInfo.in=1 THEN NIL ELSE "s"];
WF["\n"];
WF["\tOwners: "];
IF dlInfo.owners=NIL
THEN WF[" Default", "\n"]
ELSE {WF[dlInfo.owners, "\n"]; dlInfo.owners ← NIL};
WF["\tFriends: "];
IF dlInfo.friends=NIL
THEN WF[" None", "\n"]
ELSE {WF[dlInfo.friends, "\n"]; dlInfo.friends ← NIL};
PrintSubstructure[dlInfo ! AlreadyDoneThis => RESUME [new=dlInfo]];
RETURN[FALSE]
};
PrintSubstructure:
PROC [top:
REF DLInfo] = {
dots: ROPE = ". . . . . . . . . . "; -- 10 dot/space for indenting --
indention ← indention+1;
FOR dlList:
LIST
OF
REF DLInfo ← top.sub, dlList.rest
UNTIL dlList =
NIL
DO
dl: REF DLInfo = dlList.first;
WF[Rope.Substr[dots, 0, MIN[indention*2, Rope.Length[dots]]], dl.name, " - "];
SELECT
TRUE
FROM
(NOT dl.printable) =>
WF["not expanded.\n"];
(dl.notFound) =>
WF["not found.\n"];
(indention=1 AND top.ind=0 AND dlList=top.sub AND dlList.rest=NIL) =>
WF["is the only contained group; see that entry.\n"];
(SIGNAL AlreadyDoneThis[dl]) =>
WF["**loop**\n"];
ENDCASE => {
WF[CardToRope[dl.ind], "\n"];
PrintSubstructure[dl ! AlreadyDoneThis => IF new=dl THEN RESUME[TRUE] ];
};
ENDLOOP;
indention ← indention-1;
}; --PrintSubstructure--
tree: RedBlackTree.Table = RedBlackTree.Create[GetKey, MyCompare];
inputRegs: ROPE = ViewerTools.GetContents[registries];
aFH: IO.STREAM = CreateOutputFile[ViewerTools.GetContents[ARPAFileName]];
cFH: IO.STREAM = CreateOutputFile[ViewerTools.GetContents[conFileName]];
fFH: IO.STREAM = CreateOutputFile[ViewerTools.GetContents[fullFileName]];
currentGrp, totalGrp: CARDINAL ← 0;
indention: CARDINAL ← 0;
gram: Histogram.Gram = Histogram.NewGram[0, 2000];
IF cFH=IO.noWhereStream AND fFH=IO.noWhereStream AND aFH=IO.noWhereStream THEN
{outStr.PutRope["\nNo output files."]; RETURN};
outStr.PutF["Running at %t.", IO.time[]];
Labels.Set[currentName, "none"];
Labels.Set[totalGroups, "0"];
Labels.Set[currentGroups, "0"];
[] ← ForWordsInRopeDo[inputRegs, CheckRegistryValidity];
[] ← ForWordsInRopeDo[inputRegs, EnumerateRegistry];
W["Distribution list map of ", inputRegs];
WA["Arpanet redistribution list map of ", inputRegs];
W[".\n\nProduced at ", IO.PutFR[v1: IO.time[]]];
WA[".\n\nProduced at ", IO.PutFR[v1: IO.time[]]];
WC["\n\nTry using the ""Maintain"" program to add/remove yourself to/from a DL. "];
WC["If ""Maintain"" responds with ""you're not allowed to do that"", try adding/deleting yourself to firstPart-GV^.reg."];
WC["If that also fails, then send a message to ""Owners-firstPart^.reg"" requesting to be added/removed."];
W["\n\n"];
WA["\n\n"];
[] ← RedBlackTree.EnumerateIncreasing[tree, PrintDLEntry];
W["\n\nEnd of listing.\n"];
WA["\n\nEnd of listing.\n"];
fFH.Flush[];
cFH.Flush[];
aFH.Flush[];
gram.Print[outStr, "\n\nNumber of members in a group."];
outStr.PutF["\nDone at %t.\n\n", IO.time[]];
}; --Map--
BuildOuter[];
}.