DIRECTORY Ascii: TYPE USING [SP, CR, NUL], CommanderOps: TYPE USING [AddCommand, CommandBlockHandle], File: TYPE USING [Capability], FileSegment: TYPE USING [Pages], FileStream: TYPE USING [Create, EndOf, GetCapability], Heap: TYPE USING [ Create, Delete, Error, Expand, FreeNode, FreeString, Handle, MakeNode, MakeString], ListerDefs: TYPE USING [ IncorrectVersion, Load, MultipleModules, NoCode, NoFGT, NoFile, NoSymbols, SetRoutineSymbols, WriteFileID, WriteLine, WriteString], LongString: TYPE USING [ AppendChar, AppendString, EquivalentSubStrings, SubString, SubStringDescriptor, UpperCase], OSMiscOps: TYPE USING [FindFile], OutputDefs: TYPE USING [ CloseOutput, OpenOutput, PutChar, PutCR, PutLongString, PutLongSubString, outStream], Stream: TYPE USING [Delete, GetChar, Handle], Symbols: TYPE USING [BTIndex, CTXIndex, HTIndex, ISEIndex, ISENull, MDIndex, SENull], SymbolTable: TYPE USING [Acquire, Base, Release]; ListUsing: PROGRAM IMPORTS CommanderOps, FileStream, Heap, ListerDefs, LongString, OutputDefs, OSMiscOps, Stream, SymbolTable = { OPEN ListerDefs, OutputDefs, Symbols; symbols: SymbolTable.Base; myHeap: Heap.Handle _ NIL; LongSubString: TYPE = LONG POINTER TO LongString.SubStringDescriptor; Alloc: PROC [nwords: CARDINAL] RETURNS [p: LONG POINTER] = { OPEN Heap; p _ MakeNode[ myHeap, nwords ! Error => IF type = insufficientSpace THEN {Expand[myHeap, 1]; RETRY}]}; Free: PROC [p: LONG POINTER] = {Heap.FreeNode[myHeap, p]}; AllocString: PROC [nchars: CARDINAL] RETURNS [s: LONG STRING] = { OPEN Heap; s _ MakeString[ myHeap, nchars ! Error => IF type = insufficientSpace THEN {Expand[myHeap, 1]; RETRY}]}; FreeString: PROC [s: LONG STRING] = {Heap.FreeString[myHeap, s]}; InitHeap: PROC = {IF myHeap = NIL THEN myHeap _ Heap.Create[5]}; EraseHeap: PROC = {Heap.Delete[myHeap]; myHeap _ NIL}; PutVeryLongSubString: PROC [s: LongSubString] = { ss: LongString.SubStringDescriptor _ s^; PutLongSubString[@ss]}; StringCompare: PROC [s1, s2: LONG STRING] RETURNS [INTEGER] = { c1, c2: CHAR; FOR i: CARDINAL IN [0..MIN[s1.length, s2.length]) DO c1 _ LongString.UpperCase[s1[i]]; c2 _ LongString.UpperCase[s2[i]]; IF c1 < c2 THEN RETURN[-1]; IF c1 > c2 THEN RETURN[1]; ENDLOOP; RETURN[ SELECT TRUE FROM s1.length < s2.length => -1, s1.length > s2.length => 1, ENDCASE => 0]}; CompareNames: PROC [n1, n2: LongSubString] RETURNS [INTEGER] = { c1, c2: CHAR; FOR i: CARDINAL IN [0..MIN[n1.length, n2.length]) DO c1 _ LongString.UpperCase[n1.base[n1.offset + i]]; c2 _ LongString.UpperCase[n2.base[n2.offset + i]]; SELECT c1 - c2 FROM < 0 => RETURN[-1]; > 0 => RETURN[1]; ENDCASE; ENDLOOP; SELECT INTEGER[ n1.length - n2.length] FROM < 0 => RETURN[-1]; > 0 => RETURN[1]; ENDCASE => RETURN[0]}; SortNames: PROC [na: LONG DESCRIPTOR FOR ARRAY OF LongString.SubStringDescriptor] = { j: INTEGER; key: LongString.SubStringDescriptor; FOR i: CARDINAL IN [1..LENGTH[na]) DO key _ na[i]; j _ i - 1; WHILE j >= 0 AND CompareNames[@na[j], @key] > 0 DO temp: CARDINAL = j + 1; na[temp] _ na[j]; j _ j - 1; ENDLOOP; j _ j + 1; na[j] _ key; ENDLOOP}; GenCtx: PROC [ctx: Symbols.CTXIndex, p: PROC [Symbols.ISEIndex]] = { OPEN symbols; sei: Symbols.ISEIndex; FOR sei _ FirstCtxSe[ctx], NextSe[sei] UNTIL sei = SENull DO p[sei]; ENDLOOP}; PrintUsing: PROC = { OPEN Symbols, symbols; bti: BTIndex; ctx: CTXIndex; sei: ISEIndex; hti: HTIndex; mdi: MDIndex; i, n, idir, ndir: CARDINAL; first: BOOL _ TRUE; desc: LongString.SubStringDescriptor; modname: LongString.SubString = @desc; desc2: LongString.SubStringDescriptor; filename: LongString.SubString = @desc2; mname: LongSubString; DirRec: TYPE = RECORD [dirname: LongString.SubStringDescriptor, dirsei: ISEIndex]; da: LONG DESCRIPTOR FOR ARRAY OF DirRec; na: LONG DESCRIPTOR FOR ARRAY OF LongString.SubStringDescriptor; firstCopiedHash: Symbols.HTIndex; countids: PROC [sei: ISEIndex] = { IF seb[sei].hash < firstCopiedHash THEN n _ n + 1}; insertid: PROC [sei: ISEIndex] = { OPEN symbols; IF seb[sei].hash < firstCopiedHash THEN { ss: LongString.SubStringDescriptor; SubStringForName[LOOPHOLE[@ss], seb[sei].hash]; na[i] _ ss; i _ i + 1}}; PutCR[]; FOR hti IN (0..LENGTH[ht]) DO IF ht[hti].ssIndex = ht[hti - 1].ssIndex THEN { firstCopiedHash _ hti; EXIT}; REPEAT FINISHED => firstCopiedHash _ LENGTH[ht]; ENDLOOP; ndir _ 0; FOR sei _ FirstCtxSe[stHandle.directoryCtx], NextSe[sei] UNTIL sei = ISENull DO ndir _ ndir + 1; ENDLOOP; IF ndir = 0 THEN RETURN; da _ DESCRIPTOR[Alloc[SIZE[DirRec]*ndir], ndir]; ndir _ 0; FOR sei _ FirstCtxSe[stHandle.directoryCtx], NextSe[sei] UNTIL sei = ISENull DO i: INTEGER _ ndir - 1; SubStringForName[LOOPHOLE[modname], seb[sei].hash]; WHILE i >= 0 AND CompareNames[@da[i].dirname, modname] > 0 DO da[i + 1] _ da[i]; i _ i - 1; ENDLOOP; i _ i + 1; -- for compiler da[i] _ [modname^, sei]; ndir _ ndir + 1; ENDLOOP; FOR idir IN [0..ndir) DO mname _ @da[idir].dirname; sei _ da[idir].dirsei; WITH seb[UnderType[seb[sei].idType]] SELECT FROM definition => { isei: ISEIndex; ctx _ defCtx; FOR isei _ FirstCtxSe[stHandle.importCtx], NextSe[isei] UNTIL isei = ISENull DO WITH seb[UnderType[seb[isei].idType]] SELECT FROM definition => WITH ctxb[defCtx] SELECT FROM imported => IF includeLink = ctx THEN {ctx _ defCtx; EXIT}; ENDCASE; ENDCASE; ENDLOOP}; transfer => {bti _ seb[sei].idInfo; ctx _ bb[bti].localCtx}; ENDCASE => ERROR; n _ 0; GenCtx[ctx, countids]; WITH ctxb[ctx] SELECT FROM included => mdi _ module; imported => { mdi _ ctxb[includeLink].module; GenCtx[includeLink, countids]}; ENDCASE => LOOP; -- main body IF n > 0 THEN na _ DESCRIPTOR[Alloc[SIZE[LongString.SubStringDescriptor]*n], n]; IF n = 0 AND ~mdb[mdi].exported THEN LOOP; i _ 0; GenCtx[ctx, insertid]; WITH ctxb[ctx] SELECT FROM imported => GenCtx[includeLink, insertid]; ENDCASE; IF first THEN PutLongString["DIRECTORY"L] ELSE PutChar[',]; PutCR[]; first _ FALSE; PutLongString[" "L]; PutVeryLongSubString[mname]; SubStringForName[LOOPHOLE[filename], mdb[mdi].fileId]; FOR j: CARDINAL IN [0..filename.length) DO IF filename.base[filename.offset + j] = '. THEN { filename.length _ j; EXIT}; ENDLOOP; IF ~Equivalent[mname, filename] THEN { PutLongString[": FROM """L]; PutLongSubString[filename]; PutChar['"]} ELSE PutLongString[": TYPE"L]; PutLongString[" USING ["L]; IF n > 0 THEN { SortNames[na]; PutVeryLongSubString[@na[0]]; FOR i IN (0..LENGTH[na]) DO PutLongString[", "L]; PutVeryLongSubString[@na[i]]; ENDLOOP; Free[BASE[na]]}; PutChar[']]; ENDLOOP; Free[BASE[da]]; PutChar[';]; PutCR[]; PutCR[]; PutCR[]; RETURN}; Equivalent: PROC [s1, s2: LongSubString] RETURNS [BOOL] = { ss1: LongString.SubStringDescriptor _ s1^; ss2: LongString.SubStringDescriptor _ s2^; RETURN [LongString.EquivalentSubStrings[@ss1, @ss2]]}; Item: TYPE = RECORD [ link: LONG POINTER TO Item, value: LONG STRING, sublink: LONG POINTER TO Item]; Head: LONG POINTER TO Item _ NIL; CopyString: PROC [old: LONG STRING] RETURNS [copy: LONG STRING] = { IF old = NIL THEN RETURN[NIL]; copy _ AllocString[old.length]; LongString.AppendString[copy, old]}; MakeItem: PROC [value: LONG STRING, link: LONG POINTER TO Item] RETURNS [item: LONG POINTER TO Item] = { item _ Alloc[SIZE[Item]]; item^ _ [link: link, value: value, sublink: NIL]}; AddItem: PROC [ value: LONG STRING, list: LONG POINTER TO LONG POINTER TO Item, copyString: BOOL _ TRUE] RETURNS [item: LONG POINTER TO Item] = { prev: LONG POINTER TO Item _ NIL; FOR item _ list^, item.link UNTIL item = NIL DO SELECT StringCompare[ item.value, value] FROM 0 => EXIT; 1 => { item _ MakeItem[IF copyString THEN CopyString[value] ELSE value, item]; IF prev = NIL THEN list^ _ item ELSE prev.link _ item; EXIT}; ENDCASE; prev _ item; REPEAT FINISHED => { item _ MakeItem[IF copyString THEN CopyString[value] ELSE value, NIL]; IF prev = NIL THEN list^ _ item ELSE prev.link _ item}; ENDLOOP}; GetToken: PROC [in: Stream.Handle, s: LONG STRING] RETURNS [term: CHAR] = { s.length _ 0; DO IF FileStream.EndOf[in] THEN GOTO eof; IF (term _ in.GetChar[]) > Ascii.SP THEN EXIT; ENDLOOP; WHILE term IN ['a..'z] OR term IN ['A..'Z] OR term IN ['0..'9] DO LongString.AppendChar[s, term]; IF FileStream.EndOf[in] THEN GOTO eof; term _ in.GetChar[]; ENDLOOP; EXITS eof => term _ Ascii.NUL}; compressing: BOOL _ FALSE; list: BOOL _ FALSE; Compress: PROC [file: STRING] = { fh: File.Capability; dh: Stream.Handle; compressing _ TRUE; InitHeap[]; OpenOutput[file, ".ul$"L]; fh _ FileStream.GetCapability[outStream]; ListerDefs.WriteLine["UsingList:"L]; UsingList[file]; CloseOutput[]; dh _ FileStream.Create[fh]; OpenOutput[file, ".ul"L]; ListerDefs.WriteLine["Compressing:"L]; CompressIt[dh]; CloseOutput[]; Stream.Delete[dh]; EraseHeap[]; Head _ NIL; compressing _ FALSE}; UsingList: PROC [cmd: STRING] = { s: STRING _ [100]; ch: CHAR; cs: Stream.Handle _ FileStream.Create[OSMiscOps.FindFile[cmd]]; list _ TRUE; IF ~compressing THEN InitHeap[]; UNTIL FileStream.EndOf[cs] DO s.length _ 0; WHILE ~FileStream.EndOf[cs] AND (ch _ cs.GetChar[]) # ' DO LongString.AppendChar[s, ch]; ENDLOOP; IF s.length > 0 THEN { IF compressing THEN ListerDefs.WriteString[" "L]; ListerDefs.WriteLine[s]; Using[s]}; ENDLOOP; Stream.Delete[cs]; IF ~compressing THEN EraseHeap[]; list _ FALSE}; Using: PROC [root: STRING] = { OPEN LongString; i: CARDINAL; defs: BOOL _ FALSE; bcdFile: STRING _ [100]; sseg: FileSegment.Pages; IF ~list AND ~compressing THEN InitHeap[]; AppendString[bcdFile, root]; FOR i IN [0..bcdFile.length) DO IF bcdFile[i] = '. THEN EXIT; REPEAT FINISHED => AppendString[bcdFile, ".bcd"L]; ENDLOOP; BEGIN [symbols: sseg] _ Load[ bcdFile ! NoFGT => RESUME; NoCode => {defs _ TRUE; RESUME}; NoSymbols, IncorrectVersion, MultipleModules => GOTO badformat; NoFile => GOTO badname]; symbols _ SymbolTable.Acquire[sseg]; ListerDefs.SetRoutineSymbols[symbols]; IF ~compressing THEN OpenOutput[root, ".ul"L]; WriteFileID[]; IF symbols.sourceFile # NIL THEN { PutLongString[" Source: "L]; PutLongString[symbols.sourceFile]; PutCR[]}; PrintUsing[]; SymbolTable.Release[symbols]; IF ~compressing THEN CloseOutput[]; IF ~list AND ~compressing THEN EraseHeap[]; EXITS badformat => ListerDefs.WriteString["Bad Format!"L]; badname => ListerDefs.WriteString["File Not Found!"L]; END}; CompressIt: PROC [input: Stream.Handle] = { OPEN Ascii; term: CHAR; user: STRING _ [40]; userCopy: LONG STRING; interface: STRING _ [40]; used: STRING _ [40]; int: LONG POINTER TO Item; DO userCopy _ NIL; IF (term _ GetToken[input, user]) = NUL THEN EXIT; ListerDefs.WriteString[" "L]; ListerDefs.WriteLine[user]; UNTIL term = '; OR term = CR AND StringCompare[interface, "DIRECTORY"L] = 0 DO term _ GetToken[input, interface] ENDLOOP; IF term = '; THEN LOOP; UNTIL term = '; DO term _ GetToken[input, interface]; UNTIL term = ', OR term = '[ OR term = '; DO term _ GetToken[input, used] ENDLOOP; IF term = '; THEN EXIT; IF term = '[ THEN { intitem: LONG POINTER TO Item _ AddItem[interface, @Head]; item: LONG POINTER TO Item; IF userCopy = NIL THEN userCopy _ CopyString[user]; DO term _ GetToken[input, used]; item _ AddItem[used, @intitem.sublink]; [] _ AddItem[userCopy, @item.sublink, FALSE]; IF term = '] THEN EXIT; ENDLOOP; term _ GetToken[input, used]}; ENDLOOP; ENDLOOP; FOR int _ Head, int.link UNTIL int = NIL DO item, user: LONG POINTER TO Item; c: CHAR; IF int.sublink = NIL THEN LOOP; PutLongString[int.value]; PutCR[]; FOR item _ int.sublink, item.link UNTIL item = NIL DO PutLongString[" "L]; PutLongString[item.value]; PutChar[SP]; c _ '(; FOR user _ item.sublink, user.link UNTIL user = NIL DO PutChar[c]; c _ SP; PutLongString[user.value]; ENDLOOP; PutChar[')]; PutCR[]; ENDLOOP; PutCR[]; ENDLOOP}; command: CommanderOps.CommandBlockHandle; command _ CommanderOps.AddCommand["Using", LOOPHOLE[Using], 1]; command.params[0] _ [type: string, prompt: "Filename"]; command _ CommanderOps.AddCommand["UsingList", LOOPHOLE[UsingList], 1]; command.params[0] _ [type: string, prompt: "Filename"]; command _ CommanderOps.AddCommand["CompressUsing", LOOPHOLE[Compress], 1]; command.params[0] _ [type: string, prompt: "Filename"]; }. ÀListUsing.mesa modified by Bruce, 13-Jan-81 11:05:04 modified by Sweet, May 16, 1980 9:37 AM modified by Satterthwaite, May 10, 1983 12:58 pm SetFileAccess[fh, Read + Write + Append]; Ê:˜Jšœ™Jšœ%™%Jšœ(™(Jšœ0™0J˜šÏk ˜ Jš œœœœœœ˜ Jšœœœ"˜:Jšœœœ˜Jšœ œœ ˜ Jšœ œœ ˜6šœœœ˜J˜S—šœ œœ˜J˜?J˜C—šœ œœ˜J˜[—Jšœ œœ ˜!šœ œœ˜J˜U—Jšœœœ˜-Jšœ œœB˜UJšœ œœ˜1J˜—šœ ˜š˜J˜CJ˜"—Jšœ!˜%J˜J˜Jšœœ˜Jš œœœœœ ˜EJ˜š Ïnœœ œœœœ˜