-- file Pass3B.Mesa -- last modified by Satterthwaite, October 7, 1979 2:57 PM DIRECTORY ComData: FROM "comdata" USING [definitionsOnly, textIndex], Copier: FROM "copier" USING [ CreateFileTable, EnterFile, FillModule, LocateTables, SearchFileCtx, UnknownModule], LiteralOps: FROM "literalops" USING [StringValue], Log: FROM "log" USING [ErrorHti, ErrorSei, ErrorTree], P3: FROM "p3" USING [ Mark, EnterIdList, Exp, MakeIdTable, MakeFrameRecord, MakePointerType, RAttr, RPop, RType], Symbols: FROM "symbols" USING [seType, ctxType, mdType, bodyType, SERecord, CTXRecord, HTIndex, ISEIndex, CSEIndex, CTXIndex, IncludedCTXIndex, CBTIndex, ISENull, CTXNull, BTNull, OwnMdi, typeANY], SymbolOps: FROM "symbolops" USING [LinkMode, MakeNonCtxSe, SearchContext, UnderType], SymbolTable: FROM "symboltable" USING [SetCacheSize, CacheSize], Table: FROM "table" USING [Base, Notifier, AddNotify, Allocate, DropNotify], Tree: FROM "tree" USING [Index, Link, Map, Null, Scan, Test, treeType], TreeOps: FROM "treeops" USING [GetNode, ListLength, ScanList, SearchList, UpdateList]; Pass3B: PROGRAM IMPORTS Copier, LiteralOps, Log, P3, SymbolTable, SymbolOps, Table, TreeOps, dataPtr: ComData EXPORTS P3 = BEGIN OPEN TreeOps, SymbolOps, Symbols, P3; tb: Table.Base; -- tree base address (local copy) seb: Table.Base; -- se table base address (local copy) ctxb: Table.Base; -- context table base address (local copy) mdb: Table.Base; -- module table base address (local copy) bb: Table.Base; -- body table base address (local copy) BCDNotify: Table.Notifier = BEGIN -- called by allocator whenever table area is repacked tb ← base[Tree.treeType]; seb ← base[seType]; ctxb ← base[ctxType]; mdb ← base[mdType]; bb ← base[bodyType]; END; -- directory processing Directory: PUBLIC Tree.Scan = BEGIN nIdLists: CARDINAL; Table.AddNotify[BCDNotify]; nIdLists ← DirectoryScan[t]; MakeIdTable[nIdLists]; ScanList[t, DirectoryItem]; Table.DropNotify[BCDNotify]; END; DirectoryScan: PROCEDURE [t: Tree.Link] RETURNS [nLists: CARDINAL] = BEGIN FileEntry: Tree.Scan = BEGIN node: Tree.Index = GetNode[t]; id: HTIndex = WITH tb[node].son[1] SELECT FROM symbol => seb[index].hash, ENDCASE => ERROR; [] ← Copier.EnterFile[id, TreeStringValue[tb[node].son[2]]]; IF tb[node].son[3] # Tree.Null THEN nLists ← nLists+1; END; n: CARDINAL = ListLength[t]; nLists ← 0; Copier.CreateFileTable[n]; IF n # 0 THEN BEGIN ScanList[t, FileEntry]; Copier.LocateTables[n] END; RETURN END; TreeStringValue: PROCEDURE [t: Tree.Link] RETURNS [STRING] = BEGIN WITH e:t SELECT FROM literal => WITH e.info SELECT FROM string => RETURN [LiteralOps.StringValue[index]]; ENDCASE; ENDCASE; ERROR END; DirectoryItem: Tree.Scan = BEGIN node: Tree.Index = GetNode[t]; saveIndex: CARDINAL = dataPtr.textIndex; saveSize: CARDINAL = SymbolTable.CacheSize[]; dataPtr.textIndex ← tb[node].info; -- clear the symbol cache SymbolTable.SetCacheSize[0]; SymbolTable.SetCacheSize[256]; tb[node].attr2 ← tb[node].attr3 ← P3.Mark; WITH id: tb[node].son[1] SELECT FROM symbol => BEGIN sei: ISEIndex = id.index; type: CSEIndex; bti: CBTIndex; Copier.FillModule[sei ! Copier.UnknownModule => BEGIN Log.ErrorHti[moduleId, hti]; RESUME END]; type ← UnderType[seb[sei].idType]; WITH seb[type] SELECT FROM definition => tb[node].son[3] ← IncludedIds[defCtx, tb[node].son[3]]; transfer => IF (bti ← seb[sei].idInfo) # BTNull THEN tb[node].son[3] ←IncludedIds[bb[bti].localCtx, tb[node].son[3]]; ENDCASE => NULL; END; ENDCASE => ERROR; -- restore symbol caching SymbolTable.SetCacheSize[saveSize]; dataPtr.textIndex ← saveIndex; END; IncludedIds: PROCEDURE [ctx: CTXIndex, list: Tree.Link] RETURNS [val: Tree.Link] = BEGIN includedCtx: IncludedCTXIndex; IncludedId: Tree.Map = BEGIN WITH t SELECT FROM hash => BEGIN hti: HTIndex = index; sei: ISEIndex; found, duplicate, update: BOOLEAN; CheckDuplicate: Tree.Test = BEGIN RETURN [WITH t SELECT FROM symbol => IF index = sei THEN ~(duplicate ← TRUE) ELSE TRUE, ENDCASE => FALSE]; END; sei ← SearchContext[hti, ctx]; IF sei = ISENull THEN BEGIN [found, sei] ← Copier.SearchFileCtx[hti, includedCtx]; update ← found; END ELSE BEGIN found ← TRUE; update ← LinkMode[sei] = manifest; duplicate ← FALSE; SearchList[list, CheckDuplicate]; IF duplicate THEN Log.ErrorHti[duplicateId, hti] END; IF found THEN BEGIN IF update THEN seb[sei].idCtx ← CTXNull; v ← [symbol[index: sei]]; END ELSE BEGIN Log.ErrorHti[unknownId, hti]; v ← t END; END; ENDCASE => ERROR; RETURN END; WITH c: ctxb[ctx] SELECT FROM included => IF list # Tree.Null THEN BEGIN includedCtx ← LOOPHOLE[ctx]; c.restricted ← TRUE; mdb[c.module].shared ← TRUE; val ← UpdateList[list, IncludedId]; mdb[c.module].shared ← FALSE; EnterIdList[includedCtx, val]; END ELSE val ← Tree.Null; ENDCASE => ERROR; RETURN END; -- import/export processing ModulePrefix: PUBLIC Tree.Scan = BEGIN node: Tree.Index = GetNode[t]; Table.AddNotify[BCDNotify]; ScanList[tb[node].son[1], ImportItem]; tb[node].son[2] ← UpdateList[tb[node].son[2], ExportId]; ScanList[tb[node].son[3], Sharing]; BEGIN -- fix up OwnMdi entry subNode: Tree.Index = GetNode[tb[node].son[5]]; mdb[OwnMdi].moduleId ← WITH tb[subNode].son[1] SELECT FROM symbol => seb[index].hash, ENDCASE => ERROR; END; Table.DropNotify[BCDNotify]; END; ImportItem: Tree.Scan = BEGIN node: Tree.Index = GetNode[t]; sei: ISEIndex; type, vType: CSEIndex; ctx: CTXIndex; includedCtx: IncludedCTXIndex; const: BOOLEAN; saveIndex: CARDINAL = dataPtr.textIndex; dataPtr.textIndex ← tb[node].info; tb[node].attr2 ← tb[node].attr3 ← P3.Mark; sei ← WITH tb[node].son[1] SELECT FROM symbol => index, ENDCASE => ERROR; tb[node].son[2] ← Exp[tb[node].son[2], typeANY]; vType ← RType[]; const ← RAttr[].const; RPop[]; WITH v: seb[vType] SELECT FROM definition => WITH c: ctxb[v.defCtx] SELECT FROM included => BEGIN includedCtx ← LOOPHOLE[v.defCtx]; ctx ← Table.Allocate[ctxType, SIZE[imported CTXRecord]]; ctxb[ctx] ← CTXRecord[ mark: FALSE, varUpdated: FALSE, seList: ISENull, level: c.level, extension: imported[includeLink: includedCtx]]; type ← MakeNonCtxSe[SIZE[definition cons SERecord]]; seb[type] ← SERecord[mark3: TRUE, mark4: TRUE, body: cons[definition[ nGfi: v.nGfi, named: tb[node].attr1, defCtx: ctx]]]; IF ~tb[node].attr1 THEN mdb[c.module].defaultImport ← ctx ELSE IF dataPtr.definitionsOnly THEN Log.ErrorSei[nonDefinition, sei]; END; ENDCASE => BEGIN type ← typeANY; Log.ErrorTree[notPortable, tb[node].son[2]]; END; transfer => BEGIN IF v.mode # program OR dataPtr.definitionsOnly THEN Log.ErrorTree[notPortable, tb[node].son[2]]; seb[sei].immutable ← TRUE; type ← MakePointerType[MakeFrameRecord[tb[node].son[2]], typeANY]; const ← FALSE; END; ENDCASE => BEGIN IF vType # typeANY THEN Log.ErrorTree[typeClash, tb[node].son[2]]; type ← typeANY; END; seb[sei].idType ← type; seb[sei].immutable ← TRUE; seb[sei].constant ← const; seb[sei].idInfo ← 1; seb[sei].mark3 ← TRUE; dataPtr.textIndex ← saveIndex; END; ExportId: Tree.Map = BEGIN type: CSEIndex; v ← Exp[t, typeANY]; type ← RType[]; RPop[]; WITH d: seb[type] SELECT FROM definition => BEGIN WITH ctxb[d.defCtx] SELECT FROM included => mdb[module].exported ← TRUE; ENDCASE => Log.ErrorTree[notPortable, v]; END; ENDCASE => IF type # typeANY THEN Log.ErrorTree[typeClash, v]; RETURN END; Sharing: Tree.Scan = BEGIN v: Tree.Link = Exp[t, typeANY]; type: CSEIndex = RType[]; ctx: CTXIndex; sei: ISEIndex; ctx ← CTXNull; WITH seb[type] SELECT FROM definition => ctx ← defCtx; transfer => WITH v SELECT FROM symbol => BEGIN sei ← index; IF seb[sei].mark4 AND seb[sei].constant AND mode = program THEN ctx ← bb[LOOPHOLE[seb[sei].idInfo, CBTIndex]].localCtx; END; ENDCASE; ENDCASE; IF ctx # CTXNull THEN WITH ctxb[ctx] SELECT FROM included => mdb[module].shared ← TRUE; ENDCASE ELSE IF type # typeANY THEN Log.ErrorTree[typeClash, v]; RPop[]; END; END.