MobFileLookup.mesa
Copyright Ó 1985, 1989, 1991 by Xerox Corporation. All rights reserved.
Satterthwaite on April 18, 1986 11:55:20 am PST
Maxwell, August 11, 1983 2:39 pm
Paul Rovner, September 8, 1983 5:33 pm
Russ Atkinson, March 7, 1985 0:17:16 am PST
Andy Litman March 21, 1988 11:47:53 pm PST
JKF July 22, 1989 4:18:37 pm PDT
Foote, July 1, 1991 1:40 pm PDT
Willie-s, September 25, 1991 8:30 pm PDT
DIRECTORY
Alloc USING [AddNotify, Bounds, DropNotify, Handle, Notifier, Top, Units],
MobDefs USING [FTIndex, FTNull, FTRecord, fttype, NameRecord, NullVersion, sstype, sttype],
MobFileDefs USING [],
MobUtilDefs USING [FreeMob, NameForHti, MobHandle, ReadMob],
CinderSysOps USING [Close, Open, OpenKind],
ConvertUnsafe USING [SubString, SubStringToRope],
IO USING [STREAM],
Rope USING [Concat, FromProc, ROPE],
MobSymbols USING [HTIndex, STIndex, STRecord],
MobMapper USING [BadMobContents],
Table USING [Base];
MobFileLookup: PROGRAM
IMPORTS Alloc, ConvertUnsafe, MobMapper, MobUtilDefs, CinderSysOps, Rope
EXPORTS MobFileDefs = {
FileSequence: TYPE ~ RECORD [SEQUENCE length: NAT OF MobUtilDefs.MobHandle];
fileArray: REF FileSequence;
table: Alloc.Handle;
ftb, stb: Table.Base;
Notifier: Alloc.Notifier ~ {ftb ¬ base[MobDefs.fttype]; stb ¬ base[MobDefs.sttype]};
BuildFileTable: PUBLIC PROC[ownTable: Alloc.Handle] ~ {
OPEN MobSymbols;
stLimit: STIndex;
table ¬ ownTable;
table.AddNotify[Notifier];
stLimit ¬ table.Top[MobDefs.sttype];
FOR sti: STIndex ¬ STIndex.FIRST, sti+STRecord.SIZE UNTIL sti=stLimit DO
WITH s~~stb[sti] SELECT FROM
external =>
WITH p~~s SELECT FROM
file => IF p.fti = MobDefs.FTNull THEN p.fti ¬ AddFile[s.hti];
ENDCASE;
ENDCASE;
ENDLOOP;
fileArray ¬ NEW[FileSequence[table.Bounds[MobDefs.fttype].size/MobDefs.FTRecord.SIZE]];
FOR i: NAT IN [0..fileArray.length) DO fileArray[i] ¬ NIL ENDLOOP};
AddFile: PROC[hti: MobSymbols.HTIndex] RETURNS[fti: MobDefs.FTIndex] ~ {
ftLimit: MobDefs.FTIndex ~ table.Top[MobDefs.fttype];
name: MobDefs.NameRecord ~ MobUtilDefs.NameForHti[hti];
FOR fti ¬ MobDefs.FTIndex.FIRST, (fti + MobDefs.FTRecord.SIZE) UNTIL fti = ftLimit DO
IF ftb[fti].name = name THEN RETURN ENDLOOP;
fti ¬ table.Units[MobDefs.fttype, MobDefs.FTRecord.SIZE];
ftb[fti] ¬ [name~name, version~MobDefs.NullVersion];
RETURN};
EraseFileTable: PUBLIC PROC ~ {
FOR i: NAT IN [0..fileArray.length) DO
IF fileArray[i] # NIL THEN {
MobUtilDefs.FreeMob[fileArray[i]];
fileArray[i] ¬ NIL};
ENDLOOP;
FREE[@fileArray];
table.DropNotify[Notifier];
table ¬ NIL};
IndexForFti: PROC[fti: MobDefs.FTIndex] RETURNS[CARD] ~ INLINE {
RETURN[LOOPHOLE[fti, CARD]/MobDefs.FTRecord.SIZE]};
MobFileErr: PUBLIC ERROR[err: Rope.ROPE] ~ CODE;
UnknownFile: PUBLIC ERROR[fti: MobDefs.FTIndex] ~ CODE;
CapabilityForFile: PUBLIC PROC[fti: MobDefs.FTIndex] RETURNS[mobh: MobUtilDefs.MobHandle] ~ {
index: CARD ~ IndexForFti[fti];
ssd: ConvertUnsafe.SubString;
IF index >= fileArray.length THEN ERROR UnknownFile[fti];
IF fileArray[index] = NIL THEN {
ftb: Table.Base ¬ table.Bounds[MobDefs.fttype].base;
name: MobDefs.NameRecord ~ ftb[fti].name;
ssb: LONG STRING ¬ table.Bounds[MobDefs.sstype].base;
mobStream: IO.STREAM;
ssd ¬ [base~ssb, offset~name+1, length~MIN[ssb.text[name].ORD, 100]];
mobStream ¬ CinderSysOps.Open[NormalizeFileName[in~ssd], $read].stream;
IF mobStream = NIL THEN ERROR UnknownFile[fti];
fileArray[index] ¬ MobUtilDefs.ReadMob[mobStream ! MobMapper.BadMobContents => GO TO Oops];
[] ¬ CinderSysOps.Close[mobStream];
IF fileArray[index] = NIL THEN ERROR UnknownFile[fti];
EXITS
Oops => ERROR MobFileErr[err: Rope.Concat["MobMapper.BadMobContents raised for ", ConvertUnsafe.SubStringToRope[ssd]]];
};
RETURN [fileArray[index]]};
NormalizeFileName: PROC[in: ConvertUnsafe.SubString] RETURNS[Rope.ROPE] = {
dot: BOOL ¬ FALSE;
i: CARDINAL ¬ in.offset;
EachChar: SAFE PROC RETURNS[c: CHAR] ~ TRUSTED {
c ¬ in.base[i];
i ¬ i + 1;
SELECT c FROM
IN ['A..'Z] => c ← Ascii.Lower[c];
'. => dot ¬ TRUE;
ENDCASE;
RETURN};
name: Rope.ROPE = Rope.FromProc[MIN[in.length, CARDINAL[in.base.length - in.offset]], EachChar];
RETURN[IF ~dot THEN name.Concat[".mob"] ELSE name]};
}.