DIRECTORY Alloc: TYPE USING [Base, Handle, Notifier, Selector], BasicTime: TYPE USING [GMT], BcdDefs: TYPE, ConvertUnsafe: TYPE USING [EqualSubStrings, SubString, SubStringToRope], FileIO: TYPE USING [Open], FileSegment: TYPE USING [Pages, nullPages], FS: TYPE USING [Read, OpenFile, nullOpenFile], IO: TYPE USING [card, CR, PutChar, Put, PutF, PutRope, rope, STREAM, time], ListerUtil: TYPE USING [], OSMiscOps: TYPE USING [FileError, FindFile], PrincOps: TYPE USING [PageCount], Rope: TYPE USING [Cat, Find, Flatten, Length, ROPE], Symbols: TYPE USING [ bodyType, ctxType, Name, nullName, htType, ISEIndex, mdType, SENull, seType, ssType], SymbolSegment: TYPE USING [Base, extType, ltType, treeType, Tables], SymbolTable: TYPE USING [Base], UnsafeStorage: TYPE USING [GetSystemUZone], VM: TYPE USING [AddressForPageNumber, Interval, nullInterval, Allocate, Free]; ListerUtilities: PROGRAM IMPORTS ConvertUnsafe, FileIO, FS, IO, OSMiscOps, Rope, UnsafeStorage, VM EXPORTS Alloc, ListerUtil = { UnknownModule: PUBLIC ERROR = CODE; version, creator, source: BcdDefs.VersionStamp; filename: Rope.ROPE; symbols: SymbolTable.Base; bases: PRIVATE ARRAY SymbolSegment.Tables OF Alloc.Base; SetRoutineSymbols: PUBLIC PROC [s: SymbolTable.Base] = { OPEN s.stHandle; symbase: SymbolSegment.Base _ LOOPHOLE[s.stHandle]; symbols _ s; bases[SymbolSegment.treeType] _ symbase + treeBlock.offset; bases[Symbols.seType] _ symbase + seBlock.offset; bases[Symbols.htType] _ symbase + htBlock.offset; bases[Symbols.ssType] _ symbase + ssBlock.offset; bases[Symbols.ctxType] _ symbase + ctxBlock.offset; bases[Symbols.mdType] _ symbase + mdBlock.offset; bases[Symbols.bodyType] _ symbase + bodyBlock.offset; bases[SymbolSegment.ltType] _ symbase + litBlock.offset; bases[SymbolSegment.extType] _ symbase + extBlock.offset; UpdateBases[]}; NotifyLink: TYPE = LONG POINTER TO NotifyNode; NotifyNode: TYPE = RECORD [notifier: Alloc.Notifier, link: NotifyLink]; notifyList: NotifyLink _ NIL; AddNotify: PUBLIC PROC [h: Alloc.Handle, proc: Alloc.Notifier] = { p: NotifyLink = (UnsafeStorage.GetSystemUZone[]).NEW[NotifyNode _ [notifier: proc, link: notifyList]]; notifyList _ p; proc[DESCRIPTOR[bases]]}; DropNotify: PUBLIC PROC [h: Alloc.Handle, proc: Alloc.Notifier] = { p, q: NotifyLink; IF notifyList = NIL THEN RETURN; p _ notifyList; IF p.notifier = proc THEN notifyList _ p.link ELSE { DO q _ p; p _ p.link; IF p = NIL THEN RETURN; IF p.notifier = proc THEN EXIT ENDLOOP; q.link _ p.link}; (UnsafeStorage.GetSystemUZone[]).FREE[@p]}; UpdateBases: PROC = { FOR p: NotifyLink _ notifyList, p.link UNTIL p = NIL DO p.notifier[DESCRIPTOR[bases]] ENDLOOP}; Bounds: PUBLIC PROC [h: Alloc.Handle, table: Alloc.Selector] RETURNS [base: Alloc.Base, size: CARDINAL] = { OPEN symbols.stHandle; RETURN [bases[table], SELECT table FROM SymbolSegment.treeType => treeBlock.size, Symbols.seType => seBlock.size, Symbols.htType => htBlock.size, Symbols.ssType => ssBlock.size, Symbols.ctxType => ctxBlock.size, Symbols.mdType => mdBlock.size, Symbols.bodyType => bodyBlock.size, SymbolSegment.ltType => litBlock.size, SymbolSegment.extType => extBlock.size, ENDCASE => ERROR]}; SetExtension: PUBLIC PROC [root, extension: Rope.ROPE] RETURNS[name: Rope.ROPE]= { IF Rope.Find[root, "."] < 0 THEN root _ Rope.Cat[root, ".", extension]; RETURN[root]}; CreateStream: PUBLIC PROC [name: Rope.ROPE] RETURNS [IO.STREAM] = { RETURN [FileIO.Open[name]]}; LoadBcd: PUBLIC PROC [fileId: Rope.ROPE] RETURNS [bcd: FileSegment.Pages] = { file: FS.OpenFile; file _ OSMiscOps.FindFile[fileId, $read ! OSMiscOps.FileError => {GO TO noFile}]; filename _ fileId; bcd _ ReadHeader[file]; RETURN EXITS noFile => bcd _ FileSegment.nullPages}; LoadModule: PUBLIC PROC [bcd: FileSegment.Pages, typeId: Rope.ROPE] RETURNS [mti: BcdDefs.MTIndex, code, symbols: FileSegment.Pages] = { mti _ BcdDefs.MTNull; code _ symbols _ FileSegment.nullPages; IF bcd # FileSegment.nullPages THEN { BcdBase: PROC [p: LONG POINTER] RETURNS [BcdDefs.Base] = INLINE { RETURN [LOOPHOLE[p, BcdDefs.Base]]}; bcdInterval: VM.Interval = MapPages[bcd]; bcdBase: BcdDefs.BcdBase = VM.AddressForPageNumber[bcdInterval.page]; mtb: BcdDefs.Base = BcdBase[bcdBase + bcdBase.mtOffset]; ftb: BcdDefs.Base = BcdBase[bcdBase + bcdBase.ftOffset]; sgb: BcdDefs.Base = BcdBase[bcdBase + bcdBase.sgOffset]; nString: BcdDefs.NameString = LOOPHOLE[bcdBase + bcdBase.ssOffset]; AcquireFile: PROC [fti: BcdDefs.FTIndex] RETURNS [file: FS.OpenFile] = { IF fti = BcdDefs.FTSelf THEN file _ [bcd.file] ELSE { d: ConvertUnsafe.SubString _ [@nString.string, TRASH, TRASH]; fileName: Rope.ROPE; fileInterval: VM.Interval; fileBase: BcdDefs.BcdBase; d.offset _ ftb[fti].name; d.length _ nString.size[ftb[fti].name]; fileName _ ConvertUnsafe.SubStringToRope[d]; fileName _ SetExtension[fileName, "bcd"]; file _ OSMiscOps.FindFile[fileName, $read ! OSMiscOps.FileError => {GO TO NoFile}]; fileInterval _ MapPages[[file, [base: 0, pages: 1]]]; fileBase _ VM.AddressForPageNumber[fileInterval.page]; IF fileBase.versionIdent # BcdDefs.VersionID OR fileBase.version # ftb[fti].version THEN { VM.Free[fileInterval]; GO TO BadFile}; VM.Free[fileInterval]; EXITS NoFile, BadFile => file _ FS.nullOpenFile}; RETURN}; d1: ConvertUnsafe.SubString; d2: ConvertUnsafe.SubString _ [@nString.string, TRASH, TRASH]; d1.offset _ 0; d1.length _ typeId.Length[]; d1.base _ LOOPHOLE[Rope.Flatten[typeId]]; mti _ BcdDefs.MTIndex.FIRST; UNTIL mti = bcdBase.mtLimit DO d2.offset _ mtb[mti].name; d2.length _ nString.size[mtb[mti].name]; IF ConvertUnsafe.EqualSubStrings[d1, d2, FALSE] THEN EXIT; mti _ mti + (WITH m: mtb[mti] SELECT FROM direct => BcdDefs.MTRecord.direct.SIZE + m.length*BcdDefs.Link.SIZE, indirect => BcdDefs.MTRecord.indirect.SIZE, multiple => BcdDefs.MTRecord.multiple.SIZE, ENDCASE => ERROR); REPEAT FINISHED => IF bcdBase.nModules = 1 THEN mti _ BcdDefs.MTIndex.FIRST ELSE {FreeInterval[bcdInterval]; ERROR UnknownModule}; ENDLOOP; IF ~bcdBase.definitions THEN { code.file _ AcquireFile[sgb[mtb[mti].code.sgi].file]; IF code.file # FS.nullOpenFile THEN code.span _ [sgb[mtb[mti].code.sgi].base, sgb[mtb[mti].code.sgi].pages]}; IF sgb[mtb[mti].sseg].pages # 0 THEN { symbols.file _ AcquireFile[sgb[mtb[mti].sseg].file]; IF symbols.file # FS.nullOpenFile THEN symbols.span _ [ sgb[mtb[mti].sseg].base, sgb[mtb[mti].sseg].pages + sgb[mtb[mti].sseg].extraPages]}; FreeInterval[bcdInterval]}; RETURN}; MapPages: PUBLIC PROC [pages: FileSegment.Pages] RETURNS [s: VM.Interval] = { IF pages = FileSegment.nullPages THEN s _ VM.nullInterval ELSE { pointer: LONG POINTER; s _ VM.Allocate[pages.span.pages]; pointer _ VM.AddressForPageNumber[s.page]; FS.Read[file: [pages.file], from: pages.span.base, nPages: pages.span.pages, to: pointer]}; RETURN}; FreeInterval: PUBLIC PROC [s: VM.Interval] = { IF s # VM.nullInterval THEN VM.Free[s]}; ReadHeader: PROC [file: FS.OpenFile] RETURNS [ bcdPages: FileSegment.Pages _ FileSegment.nullPages] = { headerInterval: VM.Interval _ VM.nullInterval; DeleteHeader: PROC = { IF headerInterval # VM.nullInterval THEN { VM.Free[headerInterval]; headerInterval _ VM.nullInterval}}; IF file # FS.nullOpenFile THEN { ENABLE { UNWIND => {NULL}; ANY => {GO TO badFile}}; BcdBase: PROC [p: LONG POINTER] RETURNS [BcdDefs.Base] = INLINE { RETURN [LOOPHOLE[p, BcdDefs.Base]]}; bcd: BcdDefs.BcdBase; nPages: CARDINAL _ 8; DO headerInterval _ VM.Allocate[nPages]; bcd _ VM.AddressForPageNumber[headerInterval.page]; FS.Read[file: file, from: 0, nPages: nPages, to: bcd]; IF bcd.versionIdent # BcdDefs.VersionID THEN GO TO badFile; IF nPages >= bcd.nPages THEN EXIT; nPages _ bcd.nPages; VM.Free[headerInterval]; headerInterval _ VM.nullInterval ENDLOOP; bcdPages _ [file, [0, bcd.nPages]]; version _ bcd.version; creator _ bcd.creator; source _ bcd.sourceVersion; DeleteHeader[]; EXITS badFile => {DeleteHeader[]; bcdPages _ FileSegment.nullPages}}; RETURN}; PutVersionId: PUBLIC PROC [out: IO.STREAM, stamp: BcdDefs.VersionStamp] = { OPEN IO; StampWords: CARDINAL = BcdDefs.VersionStamp.SIZE; str: PACKED ARRAY [0..4*StampWords) OF [0..16) = LOOPHOLE[stamp]; digit: STRING = "0123456789abcdef"L; PutChar[out, '"]; FOR i: NAT IN [0..4*StampWords) DO PutChar[out, digit[str[i]]] ENDLOOP; IO.Put[out, IO.rope["\" ("], IO.time[LOOPHOLE[stamp.time]], IO.rope[", "]]; PutMachine[out, stamp]; PutChar[out, ')]}; WriteOneVersion: PROC [ out: IO.STREAM, version: LONG POINTER TO BcdDefs.VersionStamp, tag: Rope.ROPE] = { OPEN IO; IF version = NIL THEN RETURN; PutRope[out, tag]; PutTime[out, LOOPHOLE[version.time]]; PutRope[out, " on "]; PutMachine[out, version^]; PutChar[out, IO.CR]}; PutVersions: PUBLIC PROC [ out: IO.STREAM, version, creator, source: LONG POINTER TO BcdDefs.VersionStamp _ NIL] = { WriteOneVersion[out, version, " created "]; WriteOneVersion[out, creator, " creator "]; WriteOneVersion[out, source, " source "]; IO.PutChar[out, '\n]}; PutTime: PUBLIC PROC [out: IO.STREAM, time: BasicTime.GMT] = { IO.Put[out, IO.time[time]]}; PutMachine: PUBLIC PROC [out: IO.STREAM, stamp: BcdDefs.VersionStamp] = { out.PutF["%b#%b#", IO.card[stamp.net], IO.card[stamp.host]]}; PutFileID: PUBLIC PROC [out: IO.STREAM] = { OPEN IO; PutRope[out, filename]; PutRope[out, ", version "]; PutVersionId[out, version]; PutRope[out, "\n source "]; PutTime[out, LOOPHOLE[source.time]]; PutRope[out, "\n creator "]; PutVersionId[out, creator]; PutRope[out, "\n\n"]}; PutHti: PUBLIC PROC [out: IO.STREAM, name: Symbols.Name] = { OPEN IO; IF name = Symbols.nullName THEN {PutRope[out, "(anonymous)"]; RETURN} ELSE out.PutRope[ConvertUnsafe.SubStringToRope[symbols.SubStringForName[name]]]}; PutSei: PUBLIC PROC [out: IO.STREAM, sei: Symbols.ISEIndex] = { PutHti[out, IF sei = Symbols.SENull THEN Symbols.nullName ELSE symbols.seb[sei].hash]}; tty: IO.STREAM; Message: PUBLIC PROC [s: Rope.ROPE] = {IF tty # NIL THEN tty.PutRope[s]}; SetTypescript: PUBLIC PROC [typescript: IO.STREAM] = {tty _ typescript}; GetTypescript: PUBLIC PROC RETURNS [IO.STREAM] = {RETURN[tty]}; }. file ListerUtilities.mesa last edited by Satterthwaite on May 12, 1983 12:30 pm Last Edited by: Maxwell, August 12, 1983 8:42 am MessageWindow: TYPE USING [Append, Blink], TTY interface ELSE {MessageWindow.Append[s, TRUE]; MessageWindow.Blink[]}}; Ê ÿ˜Jšœ™Jšœ5™5J™0J˜šÏk ˜ Jšœœœ$˜5Jšœ œœœ˜Jšœ œ˜Jšœœœ/˜HJšœœœ˜Jšœ œœ˜+Jšœœœ ˜.Jš œœœœ%œ˜KJšœ œœ˜Jšœœœ™*Jšœ œœ˜,Jšœ œœ ˜!Jšœœœœ˜4šœ œœ˜J˜šœœ˜%š žœœœœœœ˜AJšœœ˜$—Jšœ œ˜)Jšœœ(˜EJ˜8J˜8J˜8Jšœœ˜CJ˜šž œœœœ˜HJšœœ˜.šœ˜Jšœ/œœ˜=Jšœœ˜Jšœœ ˜Jšœ˜J˜BJ˜,J˜)˜)Jšœœœ ˜)—J˜5Jšœ œ)˜6šœ*˜,šœ%œ˜-Jšœœœ ˜&——Jšœ˜š˜Jšœœ˜+——Jšœ˜J˜—J˜Jšœ0œœ˜>J˜J˜Jšœ œ˜)Jšœœ˜šœ˜J˜DJšœ'œœœ˜:šœ œ œ˜)Jšœ"œœ˜DJšœ&œ˜+Jšœ&œ˜+Jšœœ˜—š˜šœ˜ Jšœœ˜8Jšœœ˜6——Jšœ˜—šœœ˜J˜5šœ œ˜#J˜I——šœœ˜&J˜4šœœ˜&˜J˜J˜;———Jšœ˜—Jšœ˜J˜J˜—š žœœœœœ˜MJšœœœ ˜9šœ˜Jšœ œœ˜Jšœœ˜"Jšœ œ˜*JšœY˜[—Jšœ˜J˜—šž œœœœ˜.Jšœœœœ ˜(J˜J˜—šž œœœ œ˜.J˜8Jšœœ œ˜.J˜šž œœ˜šœœœ˜*Jšœ˜Jšœœ˜#J˜——šœœœ˜ šœ˜Jšœœ˜Jšœœœ ˜—š žœœœœœœ˜AJšœœ˜$—Jšœ˜Jšœœ˜š˜Jšœœ˜%Jšœœ+˜3Jšœ4˜6Jšœ&œœœ ˜;Jšœœœ˜"J˜Jšœ)œ ˜:Jšœ˜—J˜#J˜J˜J˜J˜š˜J˜?——Jšœ˜J˜J˜—š ž œœœœœ"˜KJšœœ˜Jšœ œœ˜1Jš œœœœ œ˜AJšœœ˜$J˜Jš œœœœœ˜GJš œ œœœœ ˜KJ˜J˜J˜—šžœœ˜Jšœœœ˜Jš œ œœœ!œ˜BJšœœ˜Jšœ œœœ˜J˜Jšœ œ˜%J˜J˜Jšœ œœ˜J˜—šž œœœ˜Jšœœœ˜Jš œœœœœ˜IJ˜+J˜.J˜,Jšœ˜J˜—š žœœœœœœ˜>Jšœ œ˜J˜—š ž œœœœœ"˜IJšœœœ˜=J˜—š ž œœœœœ˜+Jšœœ˜J˜J˜7Jšœ,œ˜CJ˜9J˜J˜—š žœœœœœ˜