CedarDLMapper.mesa; Edited by Schroeder on March 21, 1983 8:32 am
Last Edited by: RWeaver, February 10, 1984 10:50 am
Hal Murray, April 7, 1986 1:00:19 am PST
Hal Murray May 6, 1985 9:25:03 pm PDT
John Larson, July 6, 1986 0:41:24 am PDT
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: BOOLEANFALSE;
allRegistries: ROPENIL;
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: BOOLEANFALSE;
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: BOOLEANFALSE;
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: BOOLEANFALSE;
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];
done ← FALSE
};
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: BOOLEANFALSE;
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: BOOLEANFALSE;
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: ROPENARROW[k];
b: ROPENARROW[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: BOOLEANFALSE;
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: ROPENIL] = {
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: ROPENIL] = {
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: ROPENIL] = {
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: ROPENIL] = {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[];
}.