-- BootDir.mesa (Last edit by: Gobbel date: December 19, 1980 9:23 PM)
-- Last modified October 18, 1983 4:05 PM by Taft
DIRECTORY
BootDirDefs USING [cmd, file, germ, DirEntry, DirEntryEType, DirEntryType, DirEntryPtr, uCode],
InlineDefs USING [BcplLongNumber, BcplToMesaLongNumber, BITAND],
IODefs USING [WriteChar, WriteString],
NXDefs USING [illPtr, NewLine],
OsStaticDefs USING [OsStatics],
ProcessDefs USING [Yield],
PupDefs USING [GetFreePupBuffer, GetPupContentsBytes, PupBuffer, PupRouterBroadcastThis, PupSocket, PupSocketID, PupSocketMake, ReturnFreePupBuffer, SecondsToTocks, SetPupContentsWords, UniqueLocalPupSocketID],
PupTypes USING [fillInPupAddress, miscSrvSoc, PupAddress],
StringDefs USING [AppendChar, BcplSTRING, BcplToMesaString, EquivalentStrings, EquivalentSubStrings, SubStringDescriptor],
SystemDefs USING [AllocateHeapNode, AllocateHeapString, FreeHeapNode, FreeHeapString],
TimeDefs USING [PackedTime];
BootDir: MONITOR
IMPORTS InlineDefs, NXDefs, IODefs, ProcessDefs, PupDefs, StringDefs, SystemDefs
EXPORTS BootDirDefs =
BEGIN OPEN BootDirDefs;
BootReplyEntry: TYPE = RECORD [
bfn: CARDINAL,
date: InlineDefs.BcplLongNumber,
name: StringDefs.BcplSTRING];
dirHeadPtr: DirEntryPtr ← NIL;
charsPerLine: CARDINAL = 80; -- arbitrariness
killProber: PUBLIC BOOLEAN ← FALSE;
ProbeProcess: PUBLIC PROC =
BEGIN OPEN PupDefs, PupTypes;
me: PupSocketID ← UniqueLocalPupSocketID[];
dirSocket: PupSocket ← PupSocketMake[me, fillInPupAddress, SecondsToTocks[2]];
buffer: PupBuffer;
last: ORDERED POINTER;
p: ORDERED POINTER TO BootReplyEntry;
THROUGH [1..5] DO
buffer ← GetFreePupBuffer[];
buffer.source.socket ← me;
buffer.dest.socket ← miscSrvSoc;
buffer.pupType ← bootDirReq;
SetPupContentsWords[buffer, 0];
PupRouterBroadcastThis[buffer];
DO
buffer ← dirSocket.get[];
IF buffer=NIL THEN EXIT;
last ← LOOPHOLE[(@buffer.pupBody) + GetPupContentsBytes[buffer]/2];
IF buffer.pupType=bootDirReply THEN
FOR p ← LOOPHOLE[@buffer.pupBody], p+((p.name.length+2)/2)+3 UNTIL p>=last DO
IF killProber=TRUE THEN RETURN;
InsertBootReply[p, buffer.source]
ENDLOOP;
ReturnFreePupBuffer[buffer];
IF killProber=TRUE THEN RETURN;
ProcessDefs.Yield[];
ENDLOOP;
ProcessDefs.Yield[];
ENDLOOP;
END;
InsertBootReply: PROC [p: POINTER TO BootReplyEntry, host: PupTypes.PupAddress] =
BEGIN OPEN StringDefs, SystemDefs;
alto: BOOLEAN = OsStaticDefs.OsStatics.AltoVersion.engineeringnumber<4;
new: DirEntryPtr ← AllocateHeapNode[SIZE[DirEntry]];
ssBoot: SubStringDescriptor ← ["oot"L, 0, 3];
ssPb: SubStringDescriptor ← [".pb"L, 0, 3];
ssUCode: SubStringDescriptor ← [".eb"L, 0, 3];
ssGerm: SubStringDescriptor ← [".eg"L, 0, 3];
ssNew: SubStringDescriptor;
packedTime: TimeDefs.PackedTime;
BEGIN
new.name ← AllocateHeapString[p.name.length];
BcplToMesaString[@p.name, new.name];
packedTime ← InlineDefs.BcplToMesaLongNumber[p.date];
ssNew ← SubStringDescriptor[new.name, new.name.length-3, 3];
SELECT TRUE FROM
EquivalentSubStrings[@ssNew, @ssBoot] =>
new.vp ← file[sysType: alto, bfn: p.bfn, host: host, date: packedTime];
EquivalentSubStrings[@ssNew, @ssPb] =>
BEGIN
IF alto THEN GOTO DontWantIt;
new.vp ← file[sysType: pilot, bfn: p.bfn, host: host, date: packedTime];
END;
EquivalentSubStrings[@ssNew, @ssUCode] =>
BEGIN
IF alto THEN GOTO DontWantIt;
new.vp ← uCode[bfn: p.bfn, host: host, date: packedTime];
END;
EquivalentSubStrings[@ssNew, @ssGerm] =>
BEGIN
IF alto THEN GOTO DontWantIt;
new.vp ← germ[bfn: p.bfn, host: host, date: packedTime];
END;
ENDCASE => GOTO DontWantIt;
EXITS DontWantIt =>
{FreeHeapString[new.name]; FreeHeapNode[new]; RETURN};
END;
InsertDirEntry[new];
END;
InsertDirEntry: PUBLIC ENTRY PROC [new: DirEntryPtr] =
BEGIN OPEN StringDefs, SystemDefs;
prev: DirEntryPtr ← NIL;
t: DirEntryPtr;
IF dirHeadPtr=NIL THEN BEGIN dirHeadPtr ← new; new.next ← NIL; RETURN END;
FOR t ← dirHeadPtr, t.next DO
IF EquivalentStrings[new.name, t.name] THEN
WITH entry: new SELECT FROM
cmd =>
BEGIN FreeHeapString[new.name]; FreeHeapNode[new]; RETURN END;
file =>
WITH old: t SELECT FROM
file =>
IF entry.date>old.date THEN
BEGIN old.date ← entry.date; old.host ← entry.host; old.bfn ← entry.bfn; RETURN END
ELSE BEGIN FreeHeapString[new.name]; FreeHeapNode[new]; RETURN END;
ENDCASE;
uCode, germ =>
WITH old: t SELECT FROM
uCode, germ =>
IF entry.date>old.date THEN
BEGIN old.date ← entry.date; old.host ← entry.host; old.bfn ← entry.bfn; RETURN END
ELSE BEGIN FreeHeapString[new.name]; FreeHeapNode[new]; RETURN END;
ENDCASE;
ENDCASE;
IF LexicallyLessThan[new.name, t.name] THEN BEGIN InsertAfter[prev, new]; EXIT END;
IF t.next=NIL THEN BEGIN InsertAfter[t, new]; EXIT END;
prev ← t;
ENDLOOP;
END;
InsertAfter: PROC [prev, new: DirEntryPtr] =
BEGIN
IF prev=NIL THEN
BEGIN
new.next ← dirHeadPtr;
dirHeadPtr ← new;
RETURN;
END;
new.next ← prev.next;
prev.next ← new;
END;
LexicallyLessThan: PROC [s1, s2: STRING] RETURNS [BOOLEAN] =
BEGIN
i: CARDINAL;
FOR i IN [0..MIN[s1.length, s2.length]) DO
SELECT UpperCase[s1[i]] FROM
<UpperCase[s2[i]] => RETURN[TRUE];
>UpperCase[s2[i]] => RETURN[FALSE];
ENDCASE;
ENDLOOP;
RETURN[s1.length<s2.length];
END;
ListPossibleMatches: PUBLIC ENTRY PROC [s: STRING, type: DirEntryType] =
BEGIN OPEN IODefs; ENABLE UNWIND => NULL; -- release monitor lock on user abort
first: BOOLEAN ← TRUE;
entry, firstMatch, lastMatch: DirEntryPtr;
pos: CARDINAL ← 3;
WriteString[" "];
[firstMatch, lastMatch] ← GetBounds[s, type];
FOR entry ← firstMatch, entry.next UNTIL entry=lastMatch.next DO
IF ~Intersecting[type, entry.type] THEN LOOP;
IF ~first THEN WriteString[", "L] ELSE first ← FALSE;
IF pos+entry.name.length+3>charsPerLine THEN
{NXDefs.NewLine[]; WriteString[" "]; pos ← 3};
WriteString[entry.name];
pos ← pos+entry.name.length+3;
ENDLOOP;
WriteChar[’;];
END;
GetBounds: PROC [s: STRING, type: DirEntryType] RETURNS [first, last: DirEntryPtr] =
BEGIN OPEN IODefs, StringDefs;
ss: SubStringDescriptor ← [s, 0, s.length];
ssDir: SubStringDescriptor;
entry: DirEntryPtr ← NIL;
first ← last ← NIL;
FOR entry ← dirHeadPtr, entry.next UNTIL entry=NIL DO
IF ~Intersecting[type, entry.type] OR ss.length>entry.name.length THEN LOOP;
ssDir ← [entry.name, 0, ss.length];
IF EquivalentSubStrings[@ss, @ssDir] THEN {IF first=NIL THEN first ← entry; last ← entry};
ENDLOOP;
END;
Intersecting: PROC [a: DirEntryType, b: DirEntryEType] RETURNS [BOOLEAN] =
BEGIN
RETURN[SELECT b FROM
cmd => InlineDefs.BITAND[a, cmd]#0,
file => InlineDefs.BITAND[a, file]#0,
germ => InlineDefs.BITAND[a, germ]#0,
uCode => InlineDefs.BITAND[a, uCode]#0,
ENDCASE => ERROR];
END;
Lookup: PUBLIC ENTRY PROC [s: STRING, type: DirEntryType ← cmd+file, complete: BOOLEAN ← TRUE] RETURNS [DirEntryPtr] =
BEGIN OPEN IODefs, StringDefs;
ss: SubStringDescriptor ← [s, 0, s.length];
ssDir: SubStringDescriptor;
entry, firstMatch, lastMatch: DirEntryPtr ← NIL;
[firstMatch, lastMatch] ← GetBounds[s, type];
IF firstMatch=NIL THEN RETURN[NIL];
IF lastMatch=firstMatch OR firstMatch.name.length=s.length THEN
{IF complete THEN FOR i: CARDINAL IN [ss.length..firstMatch.name.length) DO WriteChar[firstMatch.name[i]] ENDLOOP; RETURN[firstMatch]; };
IF ~complete THEN RETURN[NXDefs.illPtr];
ss.base ← firstMatch.name;
DO -- complete up to point of non-uniqueness
ss.length ← ss.length+1;
FOR entry ← firstMatch, entry.next UNTIL entry=lastMatch.next DO
IF ~Intersecting[type, entry.type] OR ss.length>entry.name.length THEN LOOP;
ssDir ← [entry.name, 0, ss.length];
IF ~EquivalentSubStrings[@ss, @ssDir] THEN RETURN[NXDefs.illPtr];
ENDLOOP;
WriteChar[firstMatch.name[ss.length-1]];
AppendChar[s, firstMatch.name[ss.length-1]];
ENDLOOP;
END;
UpperCase: PROC [c: CHARACTER] RETURNS [CHARACTER] =
INLINE {RETURN[IF (c>=’a AND c<=’z) THEN c-40B ELSE c]};
END...
LOG
Time: February 17, 1980 6:19 PM By: Gobbel Action: Created file.