Expand:
PROC [groups, groupsDone, members:
LIST
OF
ROPE]
RETURNS [
LIST
OF
ROPE] =
{
EnumerateGroup:
PROC [group:
ROPE]
RETURNS [
LIST
OF
ROPE] =
{
TRUSTED {
info: GVNames.MemberInfo = GVNames.GetMembers[group];
WITH i: info
SELECT
FROM
group => RETURN[i.members];
notFound, noChange, individual, noChange, individual, allDown => RETURN[NIL];
ENDCASE => RETURN[NIL];
};
};
GetNextGroup:
PROC
RETURNS [
ROPE] =
{
group: ROPE;
IF groups = NIL OR groups.first = NIL THEN RETURN[NIL];
group ¬ groups.first;
groups ¬ groups.rest;
groupsDone ¬ CONS[group, groupsDone];
RETURN[group];
};
RememberGroup:
PROC [group:
ROPE] =
{
IF IsInList[group, groupsDone] OR IsInList[group, groups] THEN RETURN;
groups ¬ CONS[group, groups];
};
RememberMember:
PROC [member:
ROPE] =
{
IF IsInList[member, members] THEN RETURN;
members ¬ CONS[member, members];
};
Merge:
PROC [a, b:
LIST
OF
ROPE]
RETURNS [
LIST
OF
ROPE] =
{
temp: LIST OF ROPE;
IF a = NIL OR a.first = NIL THEN RETURN[b];
IF b = NIL OR b.first = NIL THEN RETURN[a];
FOR temp ¬ a, temp.rest
WHILE temp.rest #
NIL
DO
ENDLOOP;
temp.rest ¬ b;
RETURN[a];
};
IsInList:
PROC [name:
ROPE, list:
LIST
OF
ROPE]
RETURNS [
BOOL] =
{
FOR list ¬ list, list.rest
WHILE list #
NIL
DO
IF Rope.Equal[name, list.first]THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
IsGroup:
PROC [name:
ROPE]
RETURNS [
BOOL] =
{
RETURN[Rope.Find[name, "^."] # -1];
};
thisGroup: ROPE;
thisGroupMembers: LIST OF ROPE;
thisGroup ¬ GetNextGroup[];
IF thisGroup = NIL THEN RETURN[members];
thisGroupMembers ¬ EnumerateGroup[thisGroup];
FOR l:
LIST
OF
ROPE ¬ thisGroupMembers, l.rest
WHILE l #
NIL
DO
thisMember: ROPE ¬ l.first;
IF IsGroup[thisMember]
THEN RememberGroup[thisMember]
ELSE RememberMember[thisMember];
ENDLOOP;
thisGroupMembers ¬ Merge[members, Expand[groups, groupsDone, members]];
RETURN[thisGroupMembers];
};
ExpandFast: PROC [groups, groupsDone, members: RedBlackTree.Table] RETURNS [RedBlackTree.Table] =
{
EnumerateGroup: PROC [group: ROPE] RETURNS [LIST OF ROPE] =
{
TRUSTED {
info: GVNames.MemberInfo = GVNames.GetMembers[group];
WITH i: info SELECT FROM
group => RETURN[i.members];
notFound, noChange, individual, noChange, individual, allDown => RETURN[NIL];
ENDCASE => RETURN[NIL];
};
};
GetNextGroup: PROC RETURNS [ROPE] =
{
group: ROPE ← RedBlackTree.LookupSmallest[groups];
IF group = NIL THEN RETURN[NIL];
RedBlackTree.Delete[groups, group];
RedBlackTree.Insert[groupsDone, group, ??];
RETURN[group];
};
RememberGroup: PROC [group: ROPE] =
{
IF IsInList[group, groupsDone] OR IsInList[group, groups] THEN RETURN;
groups ← CONS[group, groups];
};
RememberMember: PROC [member: ROPE] =
{
IF IsInList[member, members] THEN RETURN;
members ← CONS[member, members];
};
Merge: PROC [a, b: LIST OF ROPE] RETURNS [LIST OF ROPE] =
{
temp: LIST OF ROPE;
IF a = NIL OR a.first = NIL THEN RETURN[b];
IF b = NIL OR b.first = NIL THEN RETURN[a];
FOR temp ← a, temp.rest WHILE temp.rest # NIL DO
ENDLOOP;
temp.rest ← b;
RETURN[a];
};
IsInList: PROC [name: ROPE, list: LIST OF ROPE] RETURNS [BOOL] =
{
FOR list ← list, list.rest WHILE list # NIL DO
IF Rope.Equal[name, list.first]THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
};
IsGroup: PROC [name: ROPE] RETURNS [BOOL] =
{
RETURN[Rope.Find[name, "^."] # -1];
};
thisGroup: ROPE;
thisGroupMembers: LIST OF ROPE;
thisGroup ← GetNextGroup[];
IF thisGroup = NIL THEN RETURN[members];
thisGroupMembers ← EnumerateGroup[thisGroup];
FOR l: LIST OF ROPE ← thisGroupMembers, l.rest WHILE l # NIL DO
thisMember: ROPE ← l.first;
IF IsGroup[thisMember]
THEN RememberGroup[thisMember]
ELSE RememberMember[thisMember];
ENDLOOP;
thisGroupMembers ← Merge[members, Expand[groups, groupsDone, members]];
RETURN[thisGroupMembers];
};